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 "Introspection.h"
9 #include "runtime/HalideRuntime.h" // for HALIDE_ALWAYS_INLINE
10 
11 namespace Halide {
12 
13 /** Query whether Halide was compiled with exceptions. */
15 
16 /** A base class for Halide errors. */
17 struct Error : public std::runtime_error {
18  // Give each class a non-inlined constructor so that the type
19  // doesn't get separately instantiated in each compilation unit.
20  EXPORT Error(const std::string &msg);
21 };
22 
23 /** An error that occurs while running a JIT-compiled Halide pipeline. */
24 struct RuntimeError : public Error {
25  EXPORT RuntimeError(const std::string &msg);
26 };
27 
28 /** An error that occurs while compiling a Halide pipeline that Halide
29  * attributes to a user error. */
30 struct CompileError : public Error {
31  EXPORT CompileError(const std::string &msg);
32 };
33 
34 /** An error that occurs while compiling a Halide pipeline that Halide
35  * attributes to an internal compiler bug, or to an invalid use of
36  * Halide's internals. */
37 struct InternalError : public Error {
38  EXPORT InternalError(const std::string &msg);
39 };
40 
41 /** CompileTimeErrorReporter is used at compile time (*not* runtime) when
42  * an error or warning is generated by Halide. Note that error() is called
43  * a fatal error has occurred, and returning to Halide may cause a crash;
44  * implementations of CompileTimeErrorReporter::error() should never return.
45  * (Implementations of CompileTimeErrorReporter::warning() may return but
46  * may also abort(), exit(), etc.)
47  */
49 public:
51  virtual void warning(const char* msg) = 0;
52  virtual void error(const char* msg) = 0;
53 };
54 
55 /** The default error reporter logs to stderr, then throws an exception
56  * (if WITH_EXCEPTIONS) or calls abort (if not). This allows customization
57  * of that behavior if a more gentle response to error reporting is desired.
58  * Note that error_reporter is expected to remain valid across all Halide usage;
59  * it is up to the caller to ensure that this is the case (and to do any
60  * cleanup necessary).
61  */
63 
64 namespace Internal {
65 
66 struct ErrorReport {
67  enum {
68  User = 0x0001,
69  Warning = 0x0002,
70  Runtime = 0x0004
71  };
72 
73  std::ostringstream msg;
74  const int flags;
75 
76  EXPORT ErrorReport(const char *f, int l, const char *cs, int flags);
77 
78  // Just a trick used to convert RValue into LValue
79  HALIDE_ALWAYS_INLINE ErrorReport& ref() { return *this; }
80 
81  template<typename T>
82  ErrorReport &operator<<(const T &x) {
83  msg << x;
84  return *this;
85  }
86 
87  /** When you're done using << on the object, and let it fall out of
88  * scope, this errors out, or throws an exception if they are
89  * enabled. This is a little dangerous because the destructor will
90  * also be called if there's an exception in flight due to an
91  * error in one of the arguments passed to operator<<. We handle
92  * this by only actually throwing if there isn't an exception in
93  * flight already.
94  */
95 #if __cplusplus >= 201100 || _MSC_VER >= 1900
96  EXPORT ~ErrorReport() noexcept(false);
97 #else
99 #endif
100 };
101 
102 // This uses operator precedence as a trick to avoid argument evaluation if
103 // an assertion is true: it is intended to be used as part of the
104 // _halide_internal_assertion macro, to coerce the result of the stream
105 // expression to void (to match the condition-is-false case).
106 class Voidifier {
107  public:
109  // This has to be an operator with a precedence lower than << but
110  // higher than ?:
112 };
113 
114 /**
115  * _halide_internal_assertion is used to implement our assertion macros
116  * in such a way that the messages output for the assertion are only
117  * evaluated if the assertion's value is false.
118  *
119  * Note that this macro intentionally has no parens internally; in actual
120  * use, the implicit grouping will end up being
121  *
122  * condition ? (void) : (Voidifier() & (ErrorReport << arg1 << arg2 ... << argN))
123  *
124  * This (regrettably) requires a macro to work, but has the highly desirable
125  * effect that all assertion parameters are totally skipped (not ever evaluated)
126  * when the assertion is true.
127  */
128 #define _halide_internal_assertion(condition, flags) \
129  (condition) \
130  ? (void)0 \
131  : ::Halide::Internal::Voidifier() & \
132  ::Halide::Internal::ErrorReport(__FILE__, __LINE__, #condition, flags).ref()
133 
134 
135 #define internal_error Halide::Internal::ErrorReport(__FILE__, __LINE__, nullptr, 0)
136 #define user_error Halide::Internal::ErrorReport(__FILE__, __LINE__, nullptr, Halide::Internal::ErrorReport::User)
137 #define user_warning Halide::Internal::ErrorReport(__FILE__, __LINE__, nullptr, Halide::Internal::ErrorReport::User | Halide::Internal::ErrorReport::Warning)
138 #define halide_runtime_error Halide::Internal::ErrorReport(__FILE__, __LINE__, nullptr, Halide::Internal::ErrorReport::User | Halide::Internal::ErrorReport::Runtime)
139 
140 #define internal_assert(c) _halide_internal_assertion(c, 0)
141 #define user_assert(c) _halide_internal_assertion(c, Halide::Internal::ErrorReport::User)
142 
143 // The nicely named versions get cleaned up at the end of Halide.h,
144 // but user code might want to do halide-style user_asserts (e.g. the
145 // Extern macros introduce calls to user_assert), so for that purpose
146 // we define an equivalent macro that can be used outside of Halide.h
147 #define _halide_user_assert(c) _halide_internal_assertion(c, Halide::Internal::ErrorReport::User)
148 
149 // N.B. Any function that might throw a user_assert or user_error may
150 // not be inlined into the user's code, or the line number will be
151 // misattributed to Halide.h. Either make such functions internal to
152 // libHalide, or mark them as NO_INLINE.
153 
154 }
155 
156 }
157 
158 #endif
A base class for Halide errors.
Definition: Error.h:17
Defines methods for introspecting in C++.
HALIDE_ALWAYS_INLINE ErrorReport & ref()
Definition: Error.h:79
Defines methods for manipulating and analyzing boolean expressions.
An error that occurs while compiling a Halide pipeline that Halide attributes to a user error...
Definition: Error.h:30
virtual ~CompileTimeErrorReporter()
Definition: Error.h:50
HALIDE_ALWAYS_INLINE Voidifier()
Definition: Error.h:108
Set a custom malloc and free for halide to use.
An error that occurs while compiling a Halide pipeline that Halide attributes to an internal compiler...
Definition: Error.h:37
std::ostringstream msg
Definition: Error.h:73
EXPORT Error(const std::string &msg)
#define HALIDE_ALWAYS_INLINE
Definition: HalideRuntime.h:27
CompileTimeErrorReporter is used at compile time (not runtime) when an error or warning is generated ...
Definition: Error.h:48
Expr operator &(Expr x, Expr y)
Return the bitwise and of two expressions (which need not have the same type).
Definition: IROperator.h:1347
#define EXPORT
Definition: Util.h:30
EXPORT bool exceptions_enabled()
Query whether Halide was compiled with exceptions.
ErrorReport & operator<<(const T &x)
Definition: Error.h:82
EXPORT void set_custom_compile_time_error_reporter(CompileTimeErrorReporter *error_reporter)
The default error reporter logs to stderr, then throws an exception (if WITH_EXCEPTIONS) or calls abo...
Defines functions for debug logging during code generation.
An error that occurs while running a JIT-compiled Halide pipeline.
Definition: Error.h:24