Home | History | Annotate | Download | only in common
      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