From 69f34b359c0ec0d4517050fe274883421c4c119b Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sun, 3 Aug 2025 16:09:42 +0100 Subject: 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. --- src/inputhud.c | 4 ---- src/l4d1democompat.c | 9 +-------- src/langext.h | 14 ++++++++++++++ src/mem.h | 5 +---- src/sst.c | 10 +--------- src/vcall.h | 5 ----- 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 diff --git a/src/mem.h b/src/mem.h index 726018f..86d310e 100644 --- a/src/mem.h +++ b/src/mem.h @@ -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. */ diff --git a/src/sst.c b/src/sst.c index 25e396c..7fd0275 100644 --- a/src/sst.c +++ b/src/sst.c @@ -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; -- cgit v1.2.3-54-g00ecf