/src/shaderc/third_party/spirv-tools/source/opt/log.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2016 Google Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #ifndef SOURCE_OPT_LOG_H_ |
16 | | #define SOURCE_OPT_LOG_H_ |
17 | | |
18 | | #include <cstdio> |
19 | | #include <cstdlib> |
20 | | #include <utility> |
21 | | #include <vector> |
22 | | |
23 | | #include "spirv-tools/libspirv.hpp" |
24 | | |
25 | | // Asserts the given condition is true. Otherwise, sends a message to the |
26 | | // consumer and exits the program with failure code. Accepts the following |
27 | | // formats: |
28 | | // |
29 | | // SPIRV_ASSERT(<message-consumer>, <condition-expression>); |
30 | | // SPIRV_ASSERT(<message-consumer>, <condition-expression>, <message>); |
31 | | // SPIRV_ASSERT(<message-consumer>, <condition-expression>, |
32 | | // <message-format>, <variable-arguments>); |
33 | | // |
34 | | // In the third format, the number of <variable-arguments> cannot exceed (5 - |
35 | | // 2). If more arguments are wanted, grow PP_ARG_N and PP_NARGS in the below. |
36 | | #if !defined(NDEBUG) |
37 | | #define SPIRV_ASSERT(consumer, ...) SPIRV_ASSERT_IMPL(consumer, __VA_ARGS__) |
38 | | #else |
39 | | // Adding a use to avoid errors in the release build related to unused |
40 | | // consumers. |
41 | 157k | #define SPIRV_ASSERT(consumer, ...) (void)(consumer) |
42 | | #endif |
43 | | |
44 | | // Logs a debug message to the consumer. Accepts the following formats: |
45 | | // |
46 | | // SPIRV_DEBUG(<message-consumer>, <message>); |
47 | | // SPIRV_DEBUG(<message-consumer>, <message-format>, <variable-arguments>); |
48 | | // |
49 | | // In the second format, the number of <variable-arguments> cannot exceed (5 - |
50 | | // 1). If more arguments are wanted, grow PP_ARG_N and PP_NARGS in the below. |
51 | | #if !defined(NDEBUG) && defined(SPIRV_LOG_DEBUG) |
52 | | #define SPIRV_DEBUG(consumer, ...) SPIRV_DEBUG_IMPL(consumer, __VA_ARGS__) |
53 | | #else |
54 | | // Adding a use to avoid errors in the release build related to unused |
55 | | // consumers. |
56 | | #define SPIRV_DEBUG(consumer, ...) (void)(consumer) |
57 | | #endif |
58 | | |
59 | | // Helper macros for concatenating arguments. |
60 | | #define SPIRV_CONCATENATE(a, b) SPIRV_CONCATENATE_(a, b) |
61 | | #define SPIRV_CONCATENATE_(a, b) a##b |
62 | | |
63 | | // Helper macro to force expanding __VA_ARGS__ to satisfy MSVC compiler. |
64 | | #define PP_EXPAND(x) x |
65 | | |
66 | | namespace spvtools { |
67 | | |
68 | | // Calls the given |consumer| by supplying the |message|. The |message| is from |
69 | | // the given |source| and |location| and of the given severity |level|. |
70 | | inline void Log(const MessageConsumer& consumer, spv_message_level_t level, |
71 | | const char* source, const spv_position_t& position, |
72 | 0 | const char* message) { |
73 | 0 | if (consumer != nullptr) consumer(level, source, position, message); |
74 | 0 | } |
75 | | |
76 | | // Calls the given |consumer| by supplying the message composed according to the |
77 | | // given |format|. The |message| is from the given |source| and |location| and |
78 | | // of the given severity |level|. |
79 | | template <typename... Args> |
80 | | void Logf(const MessageConsumer& consumer, spv_message_level_t level, |
81 | | const char* source, const spv_position_t& position, |
82 | 0 | const char* format, Args&&... args) { |
83 | | #if defined(_MSC_VER) && _MSC_VER < 1900 |
84 | | // Sadly, snprintf() is not supported until Visual Studio 2015! |
85 | | #define snprintf _snprintf |
86 | | #endif |
87 | |
|
88 | 0 | enum { kInitBufferSize = 256 }; |
89 | |
|
90 | 0 | char message[kInitBufferSize]; |
91 | 0 | const int size = |
92 | 0 | snprintf(message, kInitBufferSize, format, std::forward<Args>(args)...); |
93 | |
|
94 | 0 | if (size >= 0 && size < kInitBufferSize) { |
95 | 0 | Log(consumer, level, source, position, message); |
96 | 0 | return; |
97 | 0 | } |
98 | | |
99 | 0 | if (size >= 0) { |
100 | | // The initial buffer is insufficient. Allocate a buffer of a larger size, |
101 | | // and write to it instead. Force the size to be unsigned to avoid a |
102 | | // warning in GCC 7.1. |
103 | 0 | std::vector<char> longer_message(size + 1u); |
104 | 0 | snprintf(longer_message.data(), longer_message.size(), format, |
105 | 0 | std::forward<Args>(args)...); |
106 | 0 | Log(consumer, level, source, position, longer_message.data()); |
107 | 0 | return; |
108 | 0 | } |
109 | | |
110 | 0 | Log(consumer, level, source, position, "cannot compose log message"); |
111 | |
|
112 | | #if defined(_MSC_VER) && _MSC_VER < 1900 |
113 | | #undef snprintf |
114 | | #endif |
115 | 0 | } Unexecuted instantiation: void spvtools::Logf<char const*>(std::__1::function<void (spv_message_level_t, char const*, spv_position_t const&, char const*)> const&, spv_message_level_t, char const*, spv_position_t const&, char const*, char const*&&) Unexecuted instantiation: void spvtools::Logf<spv::Op const&>(std::__1::function<void (spv_message_level_t, char const*, spv_position_t const&, char const*)> const&, spv_message_level_t, char const*, spv_position_t const&, char const*, spv::Op const&) |
116 | | |
117 | | // Calls the given |consumer| by supplying the given error |message|. The |
118 | | // |message| is from the given |source| and |location|. |
119 | | inline void Error(const MessageConsumer& consumer, const char* source, |
120 | 0 | const spv_position_t& position, const char* message) { |
121 | 0 | Log(consumer, SPV_MSG_ERROR, source, position, message); |
122 | 0 | } |
123 | | |
124 | | // Calls the given |consumer| by supplying the error message composed according |
125 | | // to the given |format|. The |message| is from the given |source| and |
126 | | // |location|. |
127 | | template <typename... Args> |
128 | | inline void Errorf(const MessageConsumer& consumer, const char* source, |
129 | | const spv_position_t& position, const char* format, |
130 | 0 | Args&&... args) { |
131 | 0 | Logf(consumer, SPV_MSG_ERROR, source, position, format, |
132 | 0 | std::forward<Args>(args)...); |
133 | 0 | } Unexecuted instantiation: void spvtools::Errorf<char const*>(std::__1::function<void (spv_message_level_t, char const*, spv_position_t const&, char const*)> const&, char const*, spv_position_t const&, char const*, char const*&&) Unexecuted instantiation: void spvtools::Errorf<spv::Op const&>(std::__1::function<void (spv_message_level_t, char const*, spv_position_t const&, char const*)> const&, char const*, spv_position_t const&, char const*, spv::Op const&) |
134 | | |
135 | | } // namespace spvtools |
136 | | |
137 | | #define SPIRV_ASSERT_IMPL(consumer, ...) \ |
138 | | PP_EXPAND(SPIRV_CONCATENATE(SPIRV_ASSERT_, PP_NARGS(__VA_ARGS__))( \ |
139 | | consumer, __VA_ARGS__)) |
140 | | |
141 | | #define SPIRV_DEBUG_IMPL(consumer, ...) \ |
142 | | PP_EXPAND(SPIRV_CONCATENATE(SPIRV_DEBUG_, PP_NARGS(__VA_ARGS__))( \ |
143 | | consumer, __VA_ARGS__)) |
144 | | |
145 | | #define SPIRV_ASSERT_1(consumer, condition) \ |
146 | | do { \ |
147 | | if (!(condition)) { \ |
148 | | spvtools::Log(consumer, SPV_MSG_INTERNAL_ERROR, __FILE__, \ |
149 | | {static_cast<size_t>(__LINE__), 0, 0}, \ |
150 | | "assertion failed: " #condition); \ |
151 | | std::exit(EXIT_FAILURE); \ |
152 | | } \ |
153 | | } while (0) |
154 | | |
155 | | #define SPIRV_ASSERT_2(consumer, condition, message) \ |
156 | | do { \ |
157 | | if (!(condition)) { \ |
158 | | spvtools::Log(consumer, SPV_MSG_INTERNAL_ERROR, __FILE__, \ |
159 | | {static_cast<size_t>(__LINE__), 0, 0}, \ |
160 | | "assertion failed: " message); \ |
161 | | std::exit(EXIT_FAILURE); \ |
162 | | } \ |
163 | | } while (0) |
164 | | |
165 | | #define SPIRV_ASSERT_more(consumer, condition, format, ...) \ |
166 | | do { \ |
167 | | if (!(condition)) { \ |
168 | | spvtools::Logf(consumer, SPV_MSG_INTERNAL_ERROR, __FILE__, \ |
169 | | {static_cast<size_t>(__LINE__), 0, 0}, \ |
170 | | "assertion failed: " format, __VA_ARGS__); \ |
171 | | std::exit(EXIT_FAILURE); \ |
172 | | } \ |
173 | | } while (0) |
174 | | |
175 | | #define SPIRV_ASSERT_3(consumer, condition, format, ...) \ |
176 | | SPIRV_ASSERT_more(consumer, condition, format, __VA_ARGS__) |
177 | | |
178 | | #define SPIRV_ASSERT_4(consumer, condition, format, ...) \ |
179 | | SPIRV_ASSERT_more(consumer, condition, format, __VA_ARGS__) |
180 | | |
181 | | #define SPIRV_ASSERT_5(consumer, condition, format, ...) \ |
182 | | SPIRV_ASSERT_more(consumer, condition, format, __VA_ARGS__) |
183 | | |
184 | | #define SPIRV_DEBUG_1(consumer, message) \ |
185 | | do { \ |
186 | | spvtools::Log(consumer, SPV_MSG_DEBUG, __FILE__, \ |
187 | | {static_cast<size_t>(__LINE__), 0, 0}, message); \ |
188 | | } while (0) |
189 | | |
190 | | #define SPIRV_DEBUG_more(consumer, format, ...) \ |
191 | | do { \ |
192 | | spvtools::Logf(consumer, SPV_MSG_DEBUG, __FILE__, \ |
193 | | {static_cast<size_t>(__LINE__), 0, 0}, format, \ |
194 | | __VA_ARGS__); \ |
195 | | } while (0) |
196 | | |
197 | | #define SPIRV_DEBUG_2(consumer, format, ...) \ |
198 | | SPIRV_DEBUG_more(consumer, format, __VA_ARGS__) |
199 | | |
200 | | #define SPIRV_DEBUG_3(consumer, format, ...) \ |
201 | | SPIRV_DEBUG_more(consumer, format, __VA_ARGS__) |
202 | | |
203 | | #define SPIRV_DEBUG_4(consumer, format, ...) \ |
204 | | SPIRV_DEBUG_more(consumer, format, __VA_ARGS__) |
205 | | |
206 | | #define SPIRV_DEBUG_5(consumer, format, ...) \ |
207 | | SPIRV_DEBUG_more(consumer, format, __VA_ARGS__) |
208 | | |
209 | | // Macros for counting the number of arguments passed in. |
210 | | #define PP_NARGS(...) PP_EXPAND(PP_ARG_N(__VA_ARGS__, 5, 4, 3, 2, 1, 0)) |
211 | | #define PP_ARG_N(_1, _2, _3, _4, _5, N, ...) N |
212 | | |
213 | | // Tests for making sure that PP_NARGS() behaves as expected. |
214 | | static_assert(PP_NARGS(0) == 1, "PP_NARGS macro error"); |
215 | | static_assert(PP_NARGS(0, 0) == 2, "PP_NARGS macro error"); |
216 | | static_assert(PP_NARGS(0, 0, 0) == 3, "PP_NARGS macro error"); |
217 | | static_assert(PP_NARGS(0, 0, 0, 0) == 4, "PP_NARGS macro error"); |
218 | | static_assert(PP_NARGS(0, 0, 0, 0, 0) == 5, "PP_NARGS macro error"); |
219 | | static_assert(PP_NARGS(1 + 1, 2, 3 / 3) == 3, "PP_NARGS macro error"); |
220 | | static_assert(PP_NARGS((1, 1), 2, (3, 3)) == 3, "PP_NARGS macro error"); |
221 | | |
222 | | #endif // SOURCE_OPT_LOG_H_ |