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