diff --git a/src/common/assert.h b/src/common/assert.h index 2c7216464..1533cb569 100644 --- a/src/common/assert.h +++ b/src/common/assert.h @@ -10,41 +10,43 @@ // For asserts we'd like to keep all the junk executed when an assert happens away from the // important code in the function. One way of doing this is to put all the relevant code inside a -// lambda and force the compiler to not inline it. Unfortunately, MSVC seems to have no syntax to -// specify __declspec on lambda functions, so what we do instead is define a noinline wrapper -// template that calls the lambda. This seems to generate an extra instruction at the call-site -// compared to the ideal implementation (which wouldn't support ASSERT_MSG parameters), but is good -// enough for our purposes. -template -#if defined(_MSC_VER) -[[msvc::noinline, noreturn]] -#elif defined(__GNUC__) -[[gnu::cold, gnu::noinline, noreturn]] -#endif -static void -assert_noinline_call(const Fn& fn) { - fn(); - Crash(); - exit(1); // Keeps GCC's mouth shut about this actually returning -} +// lambda and force the compiler to not inline it. #define ASSERT(_a_) \ do \ if (!(_a_)) { \ - assert_noinline_call([] { LOG_CRITICAL(Debug, "Assertion Failed!"); }); \ + []() CITRA_NO_INLINE { \ + LOG_CRITICAL(Debug, "Assertion Failed!"); \ + Crash(); \ + exit(1); \ + }(); \ } \ while (0) #define ASSERT_MSG(_a_, ...) \ do \ if (!(_a_)) { \ - assert_noinline_call([&] { LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \ + [&]() CITRA_NO_INLINE { \ + LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); \ + Crash(); \ + exit(1); \ + }(); \ } \ while (0) -#define UNREACHABLE() assert_noinline_call([] { LOG_CRITICAL(Debug, "Unreachable code!"); }) +#define UNREACHABLE() \ + ([]() CITRA_NO_INLINE { \ + LOG_CRITICAL(Debug, "Unreachable code!"); \ + Crash(); \ + exit(1); \ + }()) + #define UNREACHABLE_MSG(...) \ - assert_noinline_call([&] { LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); }) + ([&]() CITRA_NO_INLINE { \ + LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); \ + Crash(); \ + exit(1); \ + }()) #ifdef _DEBUG #define DEBUG_ASSERT(_a_) ASSERT(_a_) diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 1420675d4..446965e90 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -28,6 +28,12 @@ #define FORCE_INLINE inline __attribute__((always_inline)) #endif +#ifdef _MSC_VER +#define CITRA_NO_INLINE __declspec(noinline) +#else +#define CITRA_NO_INLINE __attribute__((noinline)) +#endif + #ifndef _MSC_VER #ifdef ARCHITECTURE_x86_64