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
 | // 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
 | // 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
 | // lambda and force the compiler to not inline it.
 | ||||||
| // 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
 |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| #define ASSERT(_a_)                                                                                \ | #define ASSERT(_a_)                                                                                \ | ||||||
|     do                                                                                             \ |     do                                                                                             \ | ||||||
|         if (!(_a_)) {                                                                              \ |         if (!(_a_)) {                                                                              \ | ||||||
|             assert_noinline_call([] { LOG_CRITICAL(Debug, "Assertion Failed!"); });                \ |             []() CITRA_NO_INLINE {                                                                 \ | ||||||
|  |                 LOG_CRITICAL(Debug, "Assertion Failed!");                                          \ | ||||||
|  |                 Crash();                                                                           \ | ||||||
|  |                 exit(1);                                                                           \ | ||||||
|  |             }();                                                                                   \ | ||||||
|         }                                                                                          \ |         }                                                                                          \ | ||||||
|     while (0) |     while (0) | ||||||
| 
 | 
 | ||||||
| #define ASSERT_MSG(_a_, ...)                                                                       \ | #define ASSERT_MSG(_a_, ...)                                                                       \ | ||||||
|     do                                                                                             \ |     do                                                                                             \ | ||||||
|         if (!(_a_)) {                                                                              \ |         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) |     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(...)                                                                       \ | #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 | #ifdef _DEBUG | ||||||
| #define DEBUG_ASSERT(_a_) ASSERT(_a_) | #define DEBUG_ASSERT(_a_) ASSERT(_a_) | ||||||
|  |  | ||||||
|  | @ -28,6 +28,12 @@ | ||||||
| #define FORCE_INLINE inline __attribute__((always_inline)) | #define FORCE_INLINE inline __attribute__((always_inline)) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef _MSC_VER | ||||||
|  | #define CITRA_NO_INLINE __declspec(noinline) | ||||||
|  | #else | ||||||
|  | #define CITRA_NO_INLINE __attribute__((noinline)) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #ifndef _MSC_VER | #ifndef _MSC_VER | ||||||
| 
 | 
 | ||||||
| #ifdef ARCHITECTURE_x86_64 | #ifdef ARCHITECTURE_x86_64 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue