diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/assert.cpp | 7 | ||||
-rw-r--r-- | src/common/assert.h | 55 | ||||
-rw-r--r-- | src/common/settings.cpp | 2 |
3 files changed, 34 insertions, 30 deletions
diff --git a/src/common/assert.cpp b/src/common/assert.cpp index b44570528..6026b7dc2 100644 --- a/src/common/assert.cpp +++ b/src/common/assert.cpp @@ -6,8 +6,13 @@ #include "common/settings.h" -void assert_handle_failure() { +void assert_fail_impl() { if (Settings::values.use_debug_asserts) { Crash(); } } + +[[noreturn]] void unreachable_impl() { + Crash(); + throw std::runtime_error("Unreachable code"); +} diff --git a/src/common/assert.h b/src/common/assert.h index dbfd8abaf..8c927fcc0 100644 --- a/src/common/assert.h +++ b/src/common/assert.h @@ -9,44 +9,43 @@ // Sometimes we want to try to continue even after hitting an assert. // However touching this file yields a global recompilation as this header is included almost // everywhere. So let's just move the handling of the failed assert to a single cpp file. -void assert_handle_failure(); -// 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 <typename Fn> -#if defined(_MSC_VER) -[[msvc::noinline]] -#elif defined(__GNUC__) -[[gnu::cold, gnu::noinline]] +void assert_fail_impl(); +[[noreturn]] void unreachable_impl(); + +#ifdef _MSC_VER +#define YUZU_NO_INLINE __declspec(noinline) +#else +#define YUZU_NO_INLINE __attribute__((noinline)) #endif -static void -assert_noinline_call(const Fn& fn) { - fn(); - assert_handle_failure(); -} #define ASSERT(_a_) \ - do \ - if (!(_a_)) { \ - assert_noinline_call([] { LOG_CRITICAL(Debug, "Assertion Failed!"); }); \ + ([&]() YUZU_NO_INLINE { \ + if (!(_a_)) [[unlikely]] { \ + LOG_CRITICAL(Debug, "Assertion Failed!"); \ + assert_fail_impl(); \ } \ - while (0) + }()) #define ASSERT_MSG(_a_, ...) \ - do \ - if (!(_a_)) { \ - assert_noinline_call([&] { LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \ + ([&]() YUZU_NO_INLINE { \ + if (!(_a_)) [[unlikely]] { \ + LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); \ + assert_fail_impl(); \ } \ - while (0) + }()) + +#define UNREACHABLE() \ + do { \ + LOG_CRITICAL(Debug, "Unreachable code!"); \ + unreachable_impl(); \ + } while (0) -#define UNREACHABLE() assert_noinline_call([] { LOG_CRITICAL(Debug, "Unreachable code!"); }) #define UNREACHABLE_MSG(...) \ - assert_noinline_call([&] { LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); }) + do { \ + LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); \ + unreachable_impl(); \ + } while (0) #ifdef _DEBUG #define DEBUG_ASSERT(_a_) ASSERT(_a_) diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 6ffab63af..751549583 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -147,7 +147,7 @@ void UpdateRescalingInfo() { info.down_shift = 0; break; default: - UNREACHABLE(); + ASSERT(false); info.up_scale = 1; info.down_shift = 0; } |