1 /**************************************************************************** 2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 ****************************************************************************/ 23 24 #ifndef __SWR_ASSERT_H__ 25 #define __SWR_ASSERT_H__ 26 27 #if !defined(__SWR_OS_H__) 28 #error swr_assert.h should not be included directly, please include "common/os.h" instead. 29 #endif 30 31 //============================================================================= 32 // 33 // MACROS defined in this file: 34 // 35 // - SWR_ASSUME(expression, ...): Tell compiler that the expression is true. 36 // Helps with static code analysis as well. 37 // DO NOT USE if code after this dynamically 38 // checks for errors and handles them. The 39 // compiler may optimize out the error check. 40 // 41 // - SWR_ASSERT(expression, ...): Inform the user is expression is false. 42 // This check is only conditionally made, 43 // usually only in debug mode. 44 // 45 // - SWR_REL_ASSERT(expression, ...): Unconditionally enabled version of SWR_ASSERT 46 // 47 // - SWR_ASSUME_ASSERT(expression, ...): Conditionally enabled SWR_ASSERT. Uses 48 // SWR_ASSUME if SWR_ASSERT is disabled. 49 // DO NOT USE in combination with actual 50 // error checking (see SWR_ASSUME) 51 // 52 // - SWR_REL_ASSUME_ASSERT(expression, ...): Same as SWR_REL_ASSERT. 53 // 54 //============================================================================= 55 56 // Stupid preprocessor tricks to avoid -Wall / -W4 warnings 57 #if defined(_MSC_VER) 58 #define _SWR_WARN_DISABLE __pragma(warning(push)) __pragma(warning(disable:4127)) 59 #define _SWR_WARN_RESTORE __pragma(warning(pop)) 60 #else // ! MSVC compiler 61 #define _SWR_WARN_DISABLE 62 #define _SWR_WARN_RESTORE 63 #endif 64 65 #define _SWR_MACRO_START do { 66 #define _SWR_MACRO_END \ 67 _SWR_WARN_DISABLE \ 68 } while(0) \ 69 _SWR_WARN_RESTORE 70 71 72 #if defined(_WIN32) 73 #define SWR_ASSUME(e, ...) _SWR_MACRO_START __assume(e); _SWR_MACRO_END 74 #elif defined(__clang__) 75 #define SWR_ASSUME(e, ...) _SWR_MACRO_START __builtin_assume(e); _SWR_MACRO_END 76 #elif defined(__GNUC__) 77 #define SWR_ASSUME(e, ...) _SWR_MACRO_START ((e) ? ((void)0) : __builtin_unreachable()); _SWR_MACRO_END 78 #else 79 #define SWR_ASSUME(e, ...) _SWR_MACRO_START ASSUME(e); _SWR_MACRO_END 80 #endif 81 82 #if !defined(SWR_ENABLE_ASSERTS) 83 84 #if !defined(NDEBUG) 85 #define SWR_ENABLE_ASSERTS 1 86 #else 87 #define SWR_ENABLE_ASSERTS 0 88 #endif // _DEBUG 89 90 #endif // SWR_ENABLE_ASSERTS 91 92 #if !defined(SWR_ENABLE_REL_ASSERTS) 93 #define SWR_ENABLE_REL_ASSERTS 1 94 #endif 95 96 #if SWR_ENABLE_ASSERTS || SWR_ENABLE_REL_ASSERTS 97 #include "assert.h" 98 99 #if !defined(__cplusplus) 100 101 #pragma message("C++ is required for SWR Asserts, falling back to assert.h") 102 103 #if SWR_ENABLE_ASSERTS 104 #define SWR_ASSERT(e, ...) assert(e) 105 #endif 106 107 #if SWR_ENABLE_REL_ASSERTS 108 #define SWR_REL_ASSERT(e, ...) assert(e) 109 #endif 110 111 #else 112 113 bool SwrAssert( 114 bool chkDebugger, 115 bool& enabled, 116 const char* pExpression, 117 const char* pFileName, 118 uint32_t lineNum, 119 const char* function, 120 const char* pFmtString = nullptr, 121 ...); 122 123 void SwrTrace( 124 const char* pFileName, 125 uint32_t lineNum, 126 const char* function, 127 const char* pFmtString, 128 ...); 129 130 #define _SWR_ASSERT(chkDebugger, e, ...) \ 131 _SWR_MACRO_START \ 132 bool expFailed = !(e);\ 133 if (expFailed) {\ 134 static bool swrAssertEnabled = true;\ 135 expFailed = SwrAssert(chkDebugger, swrAssertEnabled, #e, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);\ 136 if (expFailed) { DEBUGBREAK; }\ 137 }\ 138 _SWR_MACRO_END 139 140 #define _SWR_INVALID(chkDebugger, ...) \ 141 _SWR_MACRO_START \ 142 static bool swrAssertEnabled = true;\ 143 bool expFailed = SwrAssert(chkDebugger, swrAssertEnabled, "", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);\ 144 if (expFailed) { DEBUGBREAK; }\ 145 _SWR_MACRO_END 146 147 #define _SWR_TRACE(_fmtstr, ...) \ 148 SwrTrace(__FILE__, __LINE__, __FUNCTION__, _fmtstr, ##__VA_ARGS__); 149 150 #if SWR_ENABLE_ASSERTS 151 #define SWR_ASSERT(e, ...) _SWR_ASSERT(true, e, ##__VA_ARGS__) 152 #define SWR_ASSUME_ASSERT(e, ...) SWR_ASSERT(e, ##__VA_ARGS__) 153 #define SWR_TRACE(_fmtstr, ...) _SWR_TRACE(_fmtstr, ##__VA_ARGS__) 154 155 #if defined(assert) 156 #undef assert 157 #endif 158 #define assert(exp) SWR_ASSERT(exp) 159 160 #endif // SWR_ENABLE_ASSERTS 161 162 #if SWR_ENABLE_REL_ASSERTS 163 #define SWR_REL_ASSERT(e, ...) _SWR_ASSERT(false, e, ##__VA_ARGS__) 164 #define SWR_REL_ASSUME_ASSERT(e, ...) SWR_REL_ASSERT(e, ##__VA_ARGS__) 165 #define SWR_REL_TRACE(_fmtstr, ...) _SWR_TRACE(_fmtstr, ##__VA_ARGS__) 166 167 // SWR_INVALID is always enabled 168 // Funky handling to allow 0 arguments with g++/gcc 169 // This is needed because you can't "swallow commas" with ##_VA_ARGS__ unless 170 // there is a first argument to the macro. So having a macro that can optionally 171 // accept 0 arguments is tricky. 172 #define _SWR_INVALID_0() _SWR_INVALID(false) 173 #define _SWR_INVALID_1(...) _SWR_INVALID(false, ##__VA_ARGS__) 174 #define _SWR_INVALID_VARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N 175 #define _SWR_INVALID_VARGS(...) _SWR_INVALID_VARGS_(__VA_ARGS__, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) 176 #define _SWR_INVALID_VARGS_0() 1, 2, 3, 4, 5, 6, 7, 9, 9, 10 177 #define _SWR_INVALID_CONCAT_(a, b) a##b 178 #define _SWR_INVALID_CONCAT(a, b) _SWR_INVALID_CONCAT_(a, b) 179 #define SWR_INVALID(...) \ 180 _SWR_INVALID_CONCAT(_SWR_INVALID_,_SWR_INVALID_VARGS(_SWR_INVALID_VARGS_0 __VA_ARGS__ ()))(__VA_ARGS__) 181 #endif 182 183 #endif // C++ 184 185 #endif // SWR_ENABLE_ASSERTS || SWR_ENABLE_REL_ASSERTS 186 187 // Needed to allow passing bitfield members to sizeof() in disabled asserts 188 template<typename T> 189 static bool SwrSizeofWorkaround(T) {return false;} 190 191 #if !SWR_ENABLE_ASSERTS 192 #define SWR_ASSERT(e, ...) _SWR_MACRO_START (void)sizeof(SwrSizeofWorkaround(e)); _SWR_MACRO_END 193 #define SWR_ASSUME_ASSERT(e, ...) SWR_ASSUME(e, ##__VA_ARGS__) 194 #define SWR_TRACE(_fmtstr, ...) _SWR_MACRO_START (void)(0); _SWR_MACRO_END 195 #endif 196 197 #if !SWR_ENABLE_REL_ASSERTS 198 #define SWR_REL_ASSERT(e, ...) _SWR_MACRO_START (void)sizeof(SwrSizeofWorkaround(e)); _SWR_MACRO_END 199 #define SWR_INVALID(...) _SWR_MACRO_START (void)(0); _SWR_MACRO_END 200 #define SWR_REL_ASSUME_ASSERT(e, ...) SWR_ASSUME(e, ##__VA_ARGS__) 201 #define SWR_REL_TRACE(_fmtstr, ...) _SWR_MACRO_START (void)(0); _SWR_MACRO_END 202 #endif 203 204 #if defined(_MSC_VER) 205 #define SWR_FUNCTION_DECL __FUNCSIG__ 206 #elif (defined(__GNUC__) || defined(__clang__)) 207 #define SWR_FUNCTION_DECL __PRETTY_FUNCTION__ 208 #else 209 #define SWR_FUNCTION_DECL __FUNCTION__ 210 #endif 211 212 #define SWR_NOT_IMPL SWR_INVALID("%s not implemented", SWR_FUNCTION_DECL) 213 214 #endif//__SWR_ASSERT_H__ 215