From 6e9bbe397c4846f440e57163e56694f95f5d9128 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sun, 27 Aug 2023 00:02:23 +0100 Subject: Remove vcruntime140.dll dependency This will save users having to install the VS runtime in order to load the plugin. Turns out there was very little to implement to make this work. Turning off stack probing might cause spooky outcomes further down the line but we'll burn that bridge when we get there. --- compile.bat | 14 +++++++++----- src/wincrt.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 src/wincrt.c diff --git a/compile.bat b/compile.bat index 9d8a2a3..1145b27 100644 --- a/compile.bat +++ b/compile.bat @@ -42,9 +42,9 @@ set objs=%objs% .build/%basename%.o :: year to get anything done. typeof=__typeof prevents pedantic warnings caused :: by typeof still technically being an extension, and stdbool gives us :: predefined bool/true/false before compilers start doing that by default -%CC% -m32 -c -flto %cflags% %warnings% -I.build/include -D_CRT_SECURE_NO_WARNINGS -D_DLL ^ --DWIN32_LEAN_AND_MEAN -DNOMINMAX%dmodname% -Dtypeof=__typeof -include stdbool.h ^ --o .build/%basename%.o %1 || exit /b +%CC% -m32 -c -flto -mno-stack-arg-probe %cflags% %warnings% -I.build/include ^ +-D_CRT_SECURE_NO_WARNINGS -D_DLL -DWIN32_LEAN_AND_MEAN -DNOMINMAX%dmodname% ^ +-Dtypeof=__typeof -include stdbool.h -o .build/%basename%.o %1 || exit /b goto :eof :src @@ -90,6 +90,7 @@ setlocal DisableDelayedExpansion :: just tack these on, whatever (repeated condition because of expansion memes) if "%dbg%"=="1" set src=%src% src/dbg.c if "%dbg%"=="1" set src=%src% src/udis86.c +if "%dbg%"=="0" set src=%src% src/wincrt.c %HOSTCC% -municode -O2 %warnings% -D_CRT_SECURE_NO_WARNINGS -include stdbool.h -ladvapi32 ^ -o .build/codegen.exe src/build/codegen.c src/build/cmeta.c || exit /b @@ -104,11 +105,14 @@ llvm-rc /FO .build\dll.res src\dll.rc || exit /b %CC% -shared -O0 -w -o .build/tier0.dll src/stubs/tier0.c %CC% -shared -O0 -w -o .build/vstdlib.dll src/stubs/vstdlib.c for %%b in (%src%) do ( call :cc %%b || exit /b ) -:: we need different library names for debugging because Microsoft. +:: we need different library names for debugging because Microsoft... +:: actually, it's different anyway because we don't use vcruntime for releases +:: any more. see comment in wincrt.c +:: required runtime bits ourselves (which saves 10KiB over static VCRT) if "%dbg%"=="1" ( set clibs=-lmsvcrtd -lvcruntimed -lucrtd ) else ( - set clibs=-lmsvcrt -lvcruntime -lucrt + set clibs=-lucrt ) %CC% -shared -flto %ldflags% -Wl,/IMPLIB:.build/sst.lib,/Brepro,/nodefaultlib ^ -L.build %clibs% -lkernel32 -luser32 -ladvapi32 -lshlwapi -ld3d9 -ldsound ^ diff --git a/src/wincrt.c b/src/wincrt.c new file mode 100644 index 0000000..8ffa6cb --- /dev/null +++ b/src/wincrt.c @@ -0,0 +1,48 @@ +/* This file is dedicated to the public domain. */ + +// We get most of the libc functions from ucrtbase.dll, which comes with +// Windows, but for some reason a few of the intrinsic-y things are part of +// vcruntime, which does *not* come with Windows!!! We can statically link just +// that part but it adds ~12KiB of random useless bloat to our binary. So, let's +// just implement the handful of required things here instead. This is only for +// release/non-debug builds; we want the extra checks in Microsoft's CRT when +// debugging. +// +// Is it actually reasonable to have to do any of this? Of course not. + +// TODO(opt): this feels like a sad implementation, can we do marginally better? +int memcmp(const void *x_, const void *y_, unsigned int sz) { + const char *x = x_, *y = y_; + for (unsigned int i = 0; i < sz; ++i) { + if (x[i] > y[i]) return 1; + if (x[i] < y[i]) return -1; + } + return 0; +} + +void *memcpy(void *restrict x, const void *restrict y, unsigned int sz) { +#ifdef __clang__ + __asm__ volatile ( + "rep movsb\n" : + "=D" (x), "=S" (y), "=c" (sz) : + "0" (x), "1" (y), "2" (sz) : + "memory" + ); +#else // terrible fallback just in case someone wants to use this with MSVC + char *restrict xb = x; const char *restrict yb = y; + for (unsigned int i = 0; i < sz; ++i) xb[i] = yb[i]; +#endif + return x; +} + +int __stdcall _DllMainCRTStartup(void *inst, unsigned int reason, + void *reserved) { + return 1; +} + +#ifdef __clang__ +__attribute__((used)) +#endif +int _fltused = 1; + +// vi: sw=4 ts=4 noet tw=80 cc=80 -- cgit v1.2.3