diff options
author | 2025-08-03 16:09:42 +0100 | |
---|---|---|
committer | 2025-08-03 16:09:42 +0100 | |
commit | 69f34b359c0ec0d4517050fe274883421c4c119b (patch) | |
tree | 44bf4ce549129ddf83371d3c6abbe8e2bf6a7869 | |
parent | b11cf48853bc4eccde60bc82180025f0797fa823 (diff) | |
download | sst-69f34b359c0ec0d4517050fe274883421c4c119b.tar.gz sst-69f34b359c0ec0d4517050fe274883421c4c119b.zip |
Tidy up some extensions and remove some ifdefs
Since this codebase is already extremely nonportable, I've decided to
relax the obsessive ifdef-else-error usage around all the extensions.
From now on, if there's no alternative to using an extension, we can
just use that extension. If it's possible to do something in a
relatively portable way, we can still try to do that in order to make
the code somewhat reusable, in contexts where that makes sense.
I also decided to use langext.h for naked functions and tail calls. If
that's used in another codebase build with a different compiler, those
just won't work, but that's fine. The benefit is really just that
there's less ceremony in places where those are used, because it's
likely there'll be a few more such places in the future, and it gets
annoying reading all the double-underscore stuff all over the place.
I still kind of want to do something about all the _WIN32 ifdefs too,
but I've realised that doing so will lead to almost nothing actually
being built on Linux. Then again, none of it currently runs on Linux so
I guess that's a moot point. Will worry about it later, anyway.
-rw-r--r-- | src/inputhud.c | 4 | ||||
-rw-r--r-- | src/l4d1democompat.c | 9 | ||||
-rw-r--r-- | src/langext.h | 14 | ||||
-rw-r--r-- | src/mem.h | 5 | ||||
-rw-r--r-- | src/sst.c | 10 | ||||
-rw-r--r-- | src/vcall.h | 5 | ||||
-rw-r--r-- | src/wincrt.c | 4 |
7 files changed, 21 insertions, 30 deletions
diff --git a/src/inputhud.c b/src/inputhud.c index fbcbe79..6cff487 100644 --- a/src/inputhud.c +++ b/src/inputhud.c @@ -150,16 +150,12 @@ static inline int bsf(uint x) { // doing a straight bsf (e.g. via BitScanForward or __builtin_ctz) creates // a false dependency on many CPUs, which compilers don't understand somehow int ret = 0; -#if defined(__GNUC__) || defined(__clang__) __asm volatile ( "bsf %0, %1\n" : "+r" (ret) : "r" (x) ); return ret; -#else -#error need some sort of inline asm, or a non-broken(!) bitscan intrinsic -#endif } // IMPORTANT: these things must all match the button order in engineapi.h diff --git a/src/l4d1democompat.c b/src/l4d1democompat.c index 4b84dd3..eff6ad0 100644 --- a/src/l4d1democompat.c +++ b/src/l4d1democompat.c @@ -114,14 +114,7 @@ static void VCALLCONV hook_ReadDemoHeader(struct CDemoFile *this) { orig_ReadDemoHeader(this); } -#if defined(__clang__) -__attribute((naked)) -#elif defined(_MSC_VER) -#error Inadequate inline assembly syntax, use Clang instead. -#else -#error No way to do naked functions! We only support Clang at the moment. -#endif -static int hook_midpoint() { +static asm_only int hook_midpoint() { __asm volatile ( "push eax\n" "mov eax, %1\n" diff --git a/src/langext.h b/src/langext.h index d2d9a23..0624b71 100644 --- a/src/langext.h +++ b/src/langext.h @@ -17,6 +17,7 @@ #define unreachable __builtin_unreachable() #define assume(x) ((void)(!!(x) || (unreachable, 0))) #define cold __attribute((__cold__, __noinline__)) +#define asm_only __attribute((__naked__)) // N.B.: may not actually work in GCC? #else #define if_hot(x) if (x) #define if_cold(x) if (x) @@ -25,11 +26,13 @@ #define unreachable __assume(0) #define assume(x) ((void)(__assume(x), 0)) #define cold __declspec(noinline) +#define asm_only __declspec(naked) #else static inline _Noreturn void _invoke_ub() {} #define unreachable (_invoke_ub()) #define assume(x) ((void)(!!(x) || (_invoke_ub(), 0))) #define cold +//#define asm_only // Can't use this without Clang/GCC/MSVC. Too bad. #endif #endif @@ -63,6 +66,17 @@ static inline _Noreturn void _invoke_ub() {} #endif #endif +#ifdef __clang__ +#define tailcall \ + /* Clang forces us to use void return and THEN warns about it ._. */ \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wpedantic\"") \ + __attribute((musttail)) return \ + _Pragma("clang diagnostic pop") +#else +//#define tailcall // Can't use this without Clang. +#endif + #endif // vi: sw=4 ts=4 noet tw=80 cc=80 @@ -49,11 +49,8 @@ static inline s64 mem_loads64(const void *p) { /* Retrieves a pointer from an unaligned pointer-to-pointer. */ static inline void *mem_loadptr(const void *p) { -#if defined(_WIN64) || defined(__x86_64__) - return (void *)mem_loadu64(p); -#else + if (sizeof(void *) == 8) return (void *)mem_loadu64(p); return (void *)mem_loadu32(p); -#endif } /* Retrieves a signed size/offset value from an unaligned pointer. */ @@ -504,15 +504,7 @@ static void hook_plugin_unload_cbv2(const struct con_cmdargs *args) { case UNLOAD_SKIP: return; case UNLOAD_SELF: -#ifdef __clang__ - // thanks clang for forcing use of return here and ALSO warning! -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpedantic" - __attribute((musttail)) return orig_plugin_unload_cb.v2(args); -#pragma clang diagnostic pop -#else -#error We are tied to clang without an assembly solution for this! -#endif + tailcall orig_plugin_unload_cb.v2(args); case UNLOAD_OTHER: orig_plugin_unload_cb.v2(args); EMIT_PluginUnloaded(); diff --git a/src/vcall.h b/src/vcall.h index 20cde7e..f91a6bd 100644 --- a/src/vcall.h +++ b/src/vcall.h @@ -23,13 +23,8 @@ */ #ifdef _WIN32 -#if defined(__GNUC__) || defined(__clang__) #define VCALLCONV __thiscall #else -// XXX: could support MSVC via __fastcall and dummy param, but is there a point? -#error C __thiscall support requires Clang or GCC -#endif -#else #define VCALLCONV #endif diff --git a/src/wincrt.c b/src/wincrt.c index 9e8b9f5..9a0326b 100644 --- a/src/wincrt.c +++ b/src/wincrt.c @@ -10,6 +10,10 @@ // // Is it actually reasonable to have to do any of this? Of course not. +// Note: these functions have ifdefs with non-asm fallbacks just in case this +// file is ever useful somewhere else, but generally we assume this codebase +// will be built with Clang. + int memcmp(const void *restrict x, const void *restrict y, unsigned int sz) { #if defined(__GNUC__) || defined(__clang__) int a, b; |