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>
SwrSizeofWorkaround(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