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 \ 66 do \ 67 { 68#define _SWR_MACRO_END \ 69 _SWR_WARN_DISABLE \ 70 } \ 71 while (0) \ 72 _SWR_WARN_RESTORE 73 74#if defined(_MSC_VER) 75#define SWR_ASSUME(e, ...) \ 76 _SWR_MACRO_START __assume(e); \ 77 _SWR_MACRO_END 78#elif defined(__clang__) 79#define SWR_ASSUME(e, ...) \ 80 _SWR_MACRO_START __builtin_assume(e); \ 81 _SWR_MACRO_END 82#elif defined(__GNUC__) 83#define SWR_ASSUME(e, ...) \ 84 _SWR_MACRO_START((e) ? ((void)0) : __builtin_unreachable()); \ 85 _SWR_MACRO_END 86#else 87#define SWR_ASSUME(e, ...) \ 88 _SWR_MACRO_START ASSUME(e); \ 89 _SWR_MACRO_END 90#endif 91 92#if !defined(SWR_ENABLE_ASSERTS) 93 94#if !defined(NDEBUG) 95#define SWR_ENABLE_ASSERTS 1 96#else 97#define SWR_ENABLE_ASSERTS 0 98#endif // _DEBUG 99 100#endif // SWR_ENABLE_ASSERTS 101 102#if !defined(SWR_ENABLE_REL_ASSERTS) 103#define SWR_ENABLE_REL_ASSERTS 1 104#endif 105 106#if SWR_ENABLE_ASSERTS || SWR_ENABLE_REL_ASSERTS 107#include "assert.h" 108 109#if !defined(__cplusplus) 110 111#pragma message("C++ is required for SWR Asserts, falling back to assert.h") 112 113#if SWR_ENABLE_ASSERTS 114#define SWR_ASSERT(e, ...) assert(e) 115#endif 116 117#if SWR_ENABLE_REL_ASSERTS 118#define SWR_REL_ASSERT(e, ...) assert(e) 119#endif 120 121#else 122 123bool SwrAssert(bool chkDebugger, 124 bool& enabled, 125 const char* pExpression, 126 const char* pFileName, 127 uint32_t lineNum, 128 const char* function, 129 const char* pFmtString = nullptr, 130 ...); 131 132void SwrTrace( 133 const char* pFileName, uint32_t lineNum, const char* function, const char* pFmtString, ...); 134 135#define _SWR_ASSERT(chkDebugger, e, ...) \ 136 _SWR_MACRO_START \ 137 bool expFailed = !(e); \ 138 if (expFailed) \ 139 { \ 140 static bool swrAssertEnabled = true; \ 141 expFailed = SwrAssert( \ 142 chkDebugger, swrAssertEnabled, #e, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \ 143 if (expFailed) \ 144 { \ 145 DEBUGBREAK; \ 146 } \ 147 } \ 148 _SWR_MACRO_END 149 150#define _SWR_INVALID(chkDebugger, ...) \ 151 _SWR_MACRO_START \ 152 static bool swrAssertEnabled = true; \ 153 bool expFailed = SwrAssert( \ 154 chkDebugger, swrAssertEnabled, "", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \ 155 if (expFailed) \ 156 { \ 157 DEBUGBREAK; \ 158 } \ 159 _SWR_MACRO_END 160 161#define _SWR_TRACE(_fmtstr, ...) SwrTrace(__FILE__, __LINE__, __FUNCTION__, _fmtstr, ##__VA_ARGS__); 162 163#if SWR_ENABLE_ASSERTS 164#define SWR_ASSERT(e, ...) _SWR_ASSERT(true, e, ##__VA_ARGS__) 165#define SWR_ASSUME_ASSERT(e, ...) SWR_ASSERT(e, ##__VA_ARGS__) 166#define SWR_TRACE(_fmtstr, ...) _SWR_TRACE(_fmtstr, ##__VA_ARGS__) 167#endif // SWR_ENABLE_ASSERTS 168 169#if SWR_ENABLE_REL_ASSERTS 170#define SWR_REL_ASSERT(e, ...) _SWR_ASSERT(false, e, ##__VA_ARGS__) 171#define SWR_REL_ASSUME_ASSERT(e, ...) SWR_REL_ASSERT(e, ##__VA_ARGS__) 172#define SWR_REL_TRACE(_fmtstr, ...) _SWR_TRACE(_fmtstr, ##__VA_ARGS__) 173 174// SWR_INVALID is always enabled 175// Funky handling to allow 0 arguments with g++/gcc 176// This is needed because you can't "swallow commas" with ##_VA_ARGS__ unless 177// there is a first argument to the macro. So having a macro that can optionally 178// accept 0 arguments is tricky. 179#define _SWR_INVALID_0() _SWR_INVALID(false) 180#define _SWR_INVALID_1(...) _SWR_INVALID(false, ##__VA_ARGS__) 181#define _SWR_INVALID_VARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N 182#define _SWR_INVALID_VARGS(...) _SWR_INVALID_VARGS_(__VA_ARGS__, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) 183#define _SWR_INVALID_VARGS_0() 1, 2, 3, 4, 5, 6, 7, 9, 9, 10 184#define _SWR_INVALID_CONCAT_(a, b) a##b 185#define _SWR_INVALID_CONCAT(a, b) _SWR_INVALID_CONCAT_(a, b) 186#define SWR_INVALID(...) \ 187 _SWR_INVALID_CONCAT(_SWR_INVALID_, _SWR_INVALID_VARGS(_SWR_INVALID_VARGS_0 __VA_ARGS__())) \ 188 (__VA_ARGS__) 189 190#define SWR_STATIC_ASSERT(expression, ...) \ 191 static_assert((expression), "Failed:\n " #expression "\n " __VA_ARGS__); 192 193#endif // SWR_ENABLE_REL_ASSERTS 194 195#endif // C++ 196 197#endif // SWR_ENABLE_ASSERTS || SWR_ENABLE_REL_ASSERTS 198 199// Needed to allow passing bitfield members to sizeof() in disabled asserts 200template <typename T> 201static bool SwrSizeofWorkaround(T) 202{ 203 return false; 204} 205 206#if !SWR_ENABLE_ASSERTS 207#define SWR_ASSERT(e, ...) \ 208 _SWR_MACRO_START(void) sizeof(SwrSizeofWorkaround(e)); \ 209 _SWR_MACRO_END 210#define SWR_ASSUME_ASSERT(e, ...) SWR_ASSUME(e, ##__VA_ARGS__) 211#define SWR_TRACE(_fmtstr, ...) \ 212 _SWR_MACRO_START(void)(0); \ 213 _SWR_MACRO_END 214#endif 215 216#if !SWR_ENABLE_REL_ASSERTS 217#define SWR_REL_ASSERT(e, ...) \ 218 _SWR_MACRO_START(void) sizeof(SwrSizeofWorkaround(e)); \ 219 _SWR_MACRO_END 220#define SWR_INVALID(...) \ 221 _SWR_MACRO_START(void)(0); \ 222 _SWR_MACRO_END 223#define SWR_REL_ASSUME_ASSERT(e, ...) SWR_ASSUME(e, ##__VA_ARGS__) 224#define SWR_REL_TRACE(_fmtstr, ...) \ 225 _SWR_MACRO_START(void)(0); \ 226 _SWR_MACRO_END 227#define SWR_STATIC_ASSERT(e, ...) \ 228 _SWR_MACRO_START(void) sizeof(SwrSizeofWorkaround(e)); \ 229 _SWR_MACRO_END 230#endif 231 232#if defined(_MSC_VER) 233#define SWR_FUNCTION_DECL __FUNCSIG__ 234#elif (defined(__GNUC__) || defined(__clang__)) 235#define SWR_FUNCTION_DECL __PRETTY_FUNCTION__ 236#else 237#define SWR_FUNCTION_DECL __FUNCTION__ 238#endif 239 240#define SWR_NOT_IMPL SWR_INVALID("%s not implemented", SWR_FUNCTION_DECL) 241 242#endif //__SWR_ASSERT_H__ 243