Halide
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 
10 namespace Halide {
11 
12 /** Query whether Halide was compiled with exceptions. */
13 bool exceptions_enabled();
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 &);
32  Error &operator=(const Error &);
33  Error(Error &&) noexcept;
34  Error &operator=(Error &&) noexcept;
35 
36  virtual ~Error();
37 
38  virtual const char *what() const noexcept;
39 
40 private:
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  */
77 public:
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 
92 namespace Internal {
93 
94 struct ErrorReport {
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).
132 class Voidifier {
133 public:
134  HALIDE_ALWAYS_INLINE Voidifier() = default;
135  // This has to be an operator with a precedence lower than << but
136  // higher than ?:
138  }
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
Halide::CompileError
An error that occurs while compiling a Halide pipeline that Halide attributes to a user error.
Definition: Error.h:56
Halide::Internal::Voidifier
Definition: Error.h:132
Halide::set_custom_compile_time_error_reporter
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...
Halide::Internal::ErrorReport::~ErrorReport
~ErrorReport() noexcept(false)
When you're done using << on the object, and let it fall out of scope, this errors out,...
Halide::Error
A base class for Halide errors.
Definition: Error.h:23
Halide::Internal::ErrorReport::flags
const int flags
Definition: Error.h:102
Debug.h
Halide::Internal::ErrorReport::Warning
@ Warning
Definition: Error.h:97
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AbstractGenerator.h:19
Halide::LinkageType::Internal
@ Internal
Not visible externally, similar to 'static' linkage in C.
Halide::Internal::ErrorReport::ErrorReport
ErrorReport(const char *f, int l, const char *cs, int flags)
Halide::InternalError
An error that occurs while compiling a Halide pipeline that Halide attributes to an internal compiler...
Definition: Error.h:64
HALIDE_ALWAYS_INLINE
#define HALIDE_ALWAYS_INLINE
Definition: HalideRuntime.h:40
Halide::exceptions_enabled
bool exceptions_enabled()
Query whether Halide was compiled with exceptions.
Halide::Internal::ErrorReport::ref
HALIDE_ALWAYS_INLINE ErrorReport & ref()
Definition: Error.h:107
Halide::Internal::ErrorReport::User
@ User
Definition: Error.h:96
Halide::Internal::Voidifier::operator&
HALIDE_ALWAYS_INLINE void operator&(ErrorReport &)
Definition: Error.h:137
Halide::Internal::ErrorReport
Definition: Error.h:94
Halide::CompileTimeErrorReporter::~CompileTimeErrorReporter
virtual ~CompileTimeErrorReporter()=default
HALIDE_EXPORT_SYMBOL
#define HALIDE_EXPORT_SYMBOL
Definition: HalideRuntime.h:74
Halide::RuntimeError
An error that occurs while running a JIT-compiled Halide pipeline.
Definition: Error.h:49
Halide::Internal::ErrorReport::msg
std::ostringstream msg
Definition: Error.h:101
HalideRuntime.h
Halide::CompileTimeErrorReporter
CompileTimeErrorReporter is used at compile time (not runtime) when an error or warning is generated ...
Definition: Error.h:76
Halide::Internal::unhandled_exception_handler
HALIDE_EXPORT_SYMBOL void unhandled_exception_handler()
Halide::Internal::ErrorReport::Runtime
@ Runtime
Definition: Error.h:98
Halide::CompileTimeErrorReporter::error
virtual void error(const char *msg)=0
Halide::CompileTimeErrorReporter::warning
virtual void warning(const char *msg)=0
Halide::Internal::ErrorReport::operator<<
ErrorReport & operator<<(const T &x)
Definition: Error.h:112