mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #6053 from Morph1984/assert-noinline
common/assert: Use noinline lambda instead of a wrapper template
This commit is contained in:
		
						commit
						d84b3d9330
					
				
					 2 changed files with 29 additions and 21 deletions
				
			
		|  | @ -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 <typename Fn> | ||||
| #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_) | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue