mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Merge pull request #584 from yuriks/outline-asserts
Asserts: Use lambdas to keep assertion code away from the main code path
This commit is contained in:
		
						commit
						ba8ce6c8f5
					
				
					 1 changed files with 25 additions and 6 deletions
				
			
		|  | @ -4,24 +4,43 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <cstdlib> | ||||
| 
 | ||||
| #include "common/common_funcs.h" | ||||
| 
 | ||||
| // 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) | ||||
|     __declspec(noinline, noreturn) | ||||
| #elif defined(__GNUC__) | ||||
|     __attribute__((noinline, noreturn, cold)) | ||||
| #endif | ||||
| static void assert_noinline_call(const Fn& fn) { | ||||
|     fn(); | ||||
|     Crash(); | ||||
|     exit(1); // Keeps GCC's mouth shut about this actually returning
 | ||||
| } | ||||
| 
 | ||||
| // TODO (yuriks) allow synchronous logging so we don't need printf
 | ||||
| #define ASSERT(_a_) \ | ||||
|     do if (!(_a_)) {\ | ||||
|     do if (!(_a_)) { assert_noinline_call([] { \ | ||||
|         fprintf(stderr, "Assertion Failed!\n\n  Line: %d\n  File: %s\n  Time: %s\n", \ | ||||
|                      __LINE__, __FILE__, __TIME__); \ | ||||
|         Crash(); \ | ||||
|     } while (0) | ||||
|     }); } while (0) | ||||
| 
 | ||||
| #define ASSERT_MSG(_a_, ...) \ | ||||
|     do if (!(_a_)) {\ | ||||
|     do if (!(_a_)) { assert_noinline_call([&] { \ | ||||
|         fprintf(stderr, "Assertion Failed!\n\n  Line: %d\n  File: %s\n  Time: %s\n", \ | ||||
|                      __LINE__, __FILE__, __TIME__); \ | ||||
|         fprintf(stderr, __VA_ARGS__); \ | ||||
|         fprintf(stderr, "\n"); \ | ||||
|         Crash(); \ | ||||
|     } while (0) | ||||
|     }); } while (0) | ||||
| 
 | ||||
| #define UNREACHABLE() ASSERT_MSG(false, "Unreachable code!") | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue