mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +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
					
				@ -4,24 +4,43 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstdlib>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "common/common_funcs.h"
 | 
					#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
 | 
					// TODO (yuriks) allow synchronous logging so we don't need printf
 | 
				
			||||||
#define ASSERT(_a_) \
 | 
					#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", \
 | 
					        fprintf(stderr, "Assertion Failed!\n\n  Line: %d\n  File: %s\n  Time: %s\n", \
 | 
				
			||||||
                     __LINE__, __FILE__, __TIME__); \
 | 
					                     __LINE__, __FILE__, __TIME__); \
 | 
				
			||||||
        Crash(); \
 | 
					    }); } while (0)
 | 
				
			||||||
    } while (0)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ASSERT_MSG(_a_, ...) \
 | 
					#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", \
 | 
					        fprintf(stderr, "Assertion Failed!\n\n  Line: %d\n  File: %s\n  Time: %s\n", \
 | 
				
			||||||
                     __LINE__, __FILE__, __TIME__); \
 | 
					                     __LINE__, __FILE__, __TIME__); \
 | 
				
			||||||
        fprintf(stderr, __VA_ARGS__); \
 | 
					        fprintf(stderr, __VA_ARGS__); \
 | 
				
			||||||
        fprintf(stderr, "\n"); \
 | 
					        fprintf(stderr, "\n"); \
 | 
				
			||||||
        Crash(); \
 | 
					    }); } while (0)
 | 
				
			||||||
    } while (0)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UNREACHABLE() ASSERT_MSG(false, "Unreachable code!")
 | 
					#define UNREACHABLE() ASSERT_MSG(false, "Unreachable code!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user