1 | /* |
2 | * SPDX-License-Identifier: Apache-2.0 |
3 | */ |
4 | |
5 | // ATTENTION: The code in this file is highly EXPERIMENTAL. |
6 | // Adventurous users should note that the APIs will probably change. |
7 | |
8 | #pragma once |
9 | |
10 | #include <stdexcept> |
11 | #include <string> |
12 | |
13 | namespace ONNX_NAMESPACE { |
14 | |
15 | struct assert_error : public std::runtime_error { |
16 | public: |
17 | explicit assert_error(const std::string& msg) : runtime_error(msg) {} |
18 | }; |
19 | |
20 | struct tensor_error : public assert_error { |
21 | public: |
22 | explicit tensor_error(const std::string& msg) : assert_error(msg) {} |
23 | }; |
24 | |
25 | std::string barf(const char* fmt, ...); |
26 | |
27 | [[noreturn]] void throw_assert_error(std::string&); |
28 | |
29 | [[noreturn]] void throw_tensor_error(std::string&); |
30 | |
31 | } // namespace ONNX_NAMESPACE |
32 | |
33 | #if defined(__GNUC__) || defined(__ICL) || defined(__clang__) |
34 | #define _ONNX_EXPECT(x, y) (__builtin_expect((x), (y))) |
35 | #else |
36 | #define _ONNX_EXPECT(x, y) (x) |
37 | #endif |
38 | |
39 | #define ONNX_ASSERT(cond) \ |
40 | if (_ONNX_EXPECT(!(cond), 0)) { \ |
41 | std::string error_msg = \ |
42 | ::ONNX_NAMESPACE::barf("%s:%u: %s: Assertion `%s` failed.", __FILE__, __LINE__, __func__, #cond); \ |
43 | throw_assert_error(error_msg); \ |
44 | } |
45 | |
46 | // The following is used to prevent MSVC from passing the whole __VA_ARGS__ list |
47 | // as the first parameter value to a macro call. |
48 | #define ONNX_EXPAND(x) x |
49 | |
50 | // Note: msg must be a string literal |
51 | #define _ONNX_ASSERTM(cond, msg, ...) \ |
52 | if (_ONNX_EXPECT(!(cond), 0)) { \ |
53 | std::string error_msg = ::ONNX_NAMESPACE::barf( \ |
54 | "%s:%u: %s: Assertion `%s` failed: " msg, __FILE__, __LINE__, __func__, #cond, __VA_ARGS__); \ |
55 | throw_assert_error(error_msg); \ |
56 | } |
57 | |
58 | // The trailing ' ' argument is a hack to deal with the extra comma when ... is empty. |
59 | // Another way to solve this is ##__VA_ARGS__ in _ONNX_ASSERTM, but this is a non-portable |
60 | // extension we shouldn't use. |
61 | #define ONNX_ASSERTM(...) ONNX_EXPAND(_ONNX_ASSERTM(__VA_ARGS__, " ")) |
62 | |
63 | #define _TENSOR_ASSERTM(cond, msg, ...) \ |
64 | if (_ONNX_EXPECT(!(cond), 0)) { \ |
65 | std::string error_msg = ::ONNX_NAMESPACE::barf( \ |
66 | "%s:%u: %s: Assertion `%s` failed: " msg, __FILE__, __LINE__, __func__, #cond, __VA_ARGS__); \ |
67 | throw_tensor_error(error_msg); \ |
68 | } |
69 | |
70 | #define TENSOR_ASSERTM(...) ONNX_EXPAND(_TENSOR_ASSERTM(__VA_ARGS__, " ")) |
71 | |