Halide 19.0.0
Halide compiler and libraries
Loading...
Searching...
No Matches
Error.h
Go to the documentation of this file.
1#ifndef HALIDE_ERROR_H
2#define HALIDE_ERROR_H
3
4#include <sstream>
5#include <stdexcept>
6
7#include "Debug.h"
8#include "runtime/HalideRuntime.h" // for HALIDE_ALWAYS_INLINE
9
10namespace Halide {
11
12/** Query whether Halide was compiled with exceptions. */
14
15/** A base class for Halide errors.
16 *
17 * Note that this deliberately does *not* descend from std::runtime_error, or
18 * even std::exception; unfortunately, std::runtime_error is not marked as
19 * DLLEXPORT on Windows, but Error needs to be marked as such, and mismatching
20 * DLLEXPORT annotations in a class inheritance hierarchy in this way can lead
21 * to ODR violations. Instead, we just attempt to replicate the API of
22 * runtime_error here. */
24 Error() = delete;
25
26 // Give each class a non-inlined constructor so that the type
27 // doesn't get separately instantiated in each compilation unit.
28 explicit Error(const char *msg);
29 explicit Error(const std::string &msg);
30
31 Error(const Error &);
33 Error(Error &&) noexcept;
34 Error &operator=(Error &&) noexcept;
35
36 virtual ~Error();
37
38 virtual const char *what() const noexcept;
39
40private:
41 // Using a std::string here will cause MSVC to complain about the fact
42 // that class std::string isn't declared DLLEXPORT, even though the
43 // field is private; rather than suppress the warning, we'll just use
44 // an old-fashioned new-and-delete to keep it nice and clean.
45 char *what_;
46};
47
48/** An error that occurs while running a JIT-compiled Halide pipeline. */
50 explicit RuntimeError(const char *msg);
51 explicit RuntimeError(const std::string &msg);
52};
53
54/** An error that occurs while compiling a Halide pipeline that Halide
55 * attributes to a user error. */
57 explicit CompileError(const char *msg);
58 explicit CompileError(const std::string &msg);
59};
60
61/** An error that occurs while compiling a Halide pipeline that Halide
62 * attributes to an internal compiler bug, or to an invalid use of
63 * Halide's internals. */
65 explicit InternalError(const char *msg);
66 explicit InternalError(const std::string &msg);
67};
68
69/** CompileTimeErrorReporter is used at compile time (*not* runtime) when
70 * an error or warning is generated by Halide. Note that error() is called
71 * a fatal error has occurred, and returning to Halide may cause a crash;
72 * implementations of CompileTimeErrorReporter::error() should never return.
73 * (Implementations of CompileTimeErrorReporter::warning() may return but
74 * may also abort(), exit(), etc.)
75 */
77public:
78 virtual ~CompileTimeErrorReporter() = default;
79 virtual void warning(const char *msg) = 0;
80 virtual void error(const char *msg) = 0;
81};
82
83/** The default error reporter logs to stderr, then throws an exception
84 * (if HALIDE_WITH_EXCEPTIONS) or calls abort (if not). This allows customization
85 * of that behavior if a more gentle response to error reporting is desired.
86 * Note that error_reporter is expected to remain valid across all Halide usage;
87 * it is up to the caller to ensure that this is the case (and to do any
88 * cleanup necessary).
89 */
91
92namespace Internal {
93
95 enum {
96 User = 0x0001,
97 Warning = 0x0002,
98 Runtime = 0x0004
99 };
100
101 std::ostringstream msg;
102 const int flags;
103
104 ErrorReport(const char *f, int l, const char *cs, int flags);
105
106 // Just a trick used to convert RValue into LValue
108 return *this;
109 }
110
111 template<typename T>
112 ErrorReport &operator<<(const T &x) {
113 msg << x;
114 return *this;
115 }
116
117 /** When you're done using << on the object, and let it fall out of
118 * scope, this errors out, or throws an exception if they are
119 * enabled. This is a little dangerous because the destructor will
120 * also be called if there's an exception in flight due to an
121 * error in one of the arguments passed to operator<<. We handle
122 * this by only actually throwing if there isn't an exception in
123 * flight already.
124 */
125 ~ErrorReport() noexcept(false);
126};
127
128// This uses operator precedence as a trick to avoid argument evaluation if
129// an assertion is true: it is intended to be used as part of the
130// _halide_internal_assertion macro, to coerce the result of the stream
131// expression to void (to match the condition-is-false case).
133public:
135 // This has to be an operator with a precedence lower than << but
136 // higher than ?:
139};
140
141/**
142 * _halide_internal_assertion is used to implement our assertion macros
143 * in such a way that the messages output for the assertion are only
144 * evaluated if the assertion's value is false.
145 *
146 * Note that this macro intentionally has no parens internally; in actual
147 * use, the implicit grouping will end up being
148 *
149 * condition ? (void) : (Voidifier() & (ErrorReport << arg1 << arg2 ... << argN))
150 *
151 * This (regrettably) requires a macro to work, but has the highly desirable
152 * effect that all assertion parameters are totally skipped (not ever evaluated)
153 * when the assertion is true.
154 */
155#define _halide_internal_assertion(condition, flags) \
156 /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \
157 (condition) ? (void)0 : ::Halide::Internal::Voidifier() & ::Halide::Internal::ErrorReport(__FILE__, __LINE__, #condition, flags).ref()
158
159#define internal_error Halide::Internal::ErrorReport(__FILE__, __LINE__, nullptr, 0)
160#define user_error Halide::Internal::ErrorReport(__FILE__, __LINE__, nullptr, Halide::Internal::ErrorReport::User)
161#define user_warning Halide::Internal::ErrorReport(__FILE__, __LINE__, nullptr, Halide::Internal::ErrorReport::User | Halide::Internal::ErrorReport::Warning)
162#define halide_runtime_error Halide::Internal::ErrorReport(__FILE__, __LINE__, nullptr, Halide::Internal::ErrorReport::User | Halide::Internal::ErrorReport::Runtime)
163
164#define internal_assert(c) _halide_internal_assertion(c, 0)
165#define user_assert(c) _halide_internal_assertion(c, Halide::Internal::ErrorReport::User)
166
167// The nicely named versions get cleaned up at the end of Halide.h,
168// but user code might want to do halide-style user_asserts (e.g. the
169// Extern macros introduce calls to user_assert), so for that purpose
170// we define an equivalent macro that can be used outside of Halide.h
171#define _halide_user_assert(c) _halide_internal_assertion(c, Halide::Internal::ErrorReport::User)
172
173// N.B. Any function that might throw a user_assert or user_error may
174// not be inlined into the user's code, or the line number will be
175// misattributed to Halide.h. Either make such functions internal to
176// libHalide, or mark them as HALIDE_NO_USER_CODE_INLINE.
177
178// handler suitable for use with std::terminate; it will catch unhandled exceptions
179// and log the `what()` to stderr, then abort. Exposed as a function to minimize
180// the need for external code to need to know the definition of Halide::Error.
182
183} // namespace Internal
184
185} // namespace Halide
186
187#endif
Defines functions for debug logging during code generation.
This file declares the routines used by Halide internally in its runtime.
#define HALIDE_EXPORT_SYMBOL
#define HALIDE_ALWAYS_INLINE
CompileTimeErrorReporter is used at compile time (not runtime) when an error or warning is generated ...
Definition Error.h:76
virtual void warning(const char *msg)=0
virtual void error(const char *msg)=0
virtual ~CompileTimeErrorReporter()=default
HALIDE_ALWAYS_INLINE void operator&(ErrorReport &)
Definition Error.h:137
HALIDE_ALWAYS_INLINE Voidifier()=default
HALIDE_EXPORT_SYMBOL void unhandled_exception_handler()
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
bool exceptions_enabled()
Query whether Halide was compiled with exceptions.
void set_custom_compile_time_error_reporter(CompileTimeErrorReporter *error_reporter)
The default error reporter logs to stderr, then throws an exception (if HALIDE_WITH_EXCEPTIONS) or ca...
An error that occurs while compiling a Halide pipeline that Halide attributes to a user error.
Definition Error.h:56
CompileError(const char *msg)
CompileError(const std::string &msg)
A base class for Halide errors.
Definition Error.h:23
Error(Error &&) noexcept
Error(const std::string &msg)
Error(const char *msg)
Error()=delete
Error & operator=(const Error &)
Error(const Error &)
~ErrorReport() noexcept(false)
When you're done using << on the object, and let it fall out of scope, this errors out,...
ErrorReport(const char *f, int l, const char *cs, int flags)
std::ostringstream msg
Definition Error.h:101
ErrorReport & operator<<(const T &x)
Definition Error.h:112
HALIDE_ALWAYS_INLINE ErrorReport & ref()
Definition Error.h:107
An error that occurs while compiling a Halide pipeline that Halide attributes to an internal compiler...
Definition Error.h:64
InternalError(const std::string &msg)
InternalError(const char *msg)
An error that occurs while running a JIT-compiled Halide pipeline.
Definition Error.h:49
RuntimeError(const char *msg)
RuntimeError(const std::string &msg)