From edbe7600f588638a39655b64c3390944c752911a Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Tue, 14 Jun 2022 07:21:34 -0400 Subject: [PATCH] common/assert: Use noinline lambda instead of a wrapper template MSVC now supports specifying __declspec on lambda functions --- src/common/assert.h | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) 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_)