PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Error.h

https://github.com/josephsieh/Halide
C Header | 169 lines | 102 code | 26 blank | 41 comment | 15 complexity | 0f24ba4af3a59a334e62328ce7c228c7 MD5 | raw file
  1. #ifndef HALIDE_ERROR_H
  2. #define HALIDE_ERROR_H
  3. #include <string>
  4. #include <sstream>
  5. #include <stdexcept>
  6. #include "Debug.h"
  7. #include "Introspection.h"
  8. namespace Halide {
  9. /** Query whether Halide was compiled with exceptions. */
  10. EXPORT bool exceptions_enabled();
  11. /** A base class for Halide errors. */
  12. struct Error : public std::runtime_error {
  13. // Give each class a non-inlined constructor so that the type
  14. // doesn't get separately instantiated in each compilation unit.
  15. EXPORT Error(const std::string &msg);
  16. };
  17. /** An error that occurs while running a JIT-compiled Halide pipeline. */
  18. struct RuntimeError : public Error {
  19. EXPORT RuntimeError(const std::string &msg);
  20. };
  21. /** An error that occurs while compiling a Halide pipeline that Halide
  22. * attributes to a user error. */
  23. struct CompileError : public Error {
  24. EXPORT CompileError(const std::string &msg);
  25. };
  26. /** An error that occurs while compiling a Halide pipeline that Halide
  27. * attributes to an internal compiler bug, or to an invalid use of
  28. * Halide's internals. */
  29. struct InternalError : public Error {
  30. EXPORT InternalError(const std::string &msg);
  31. };
  32. /** CompileTimeErrorReporter is used at compile time (*not* runtime) when
  33. * an error or warning is generated by Halide. Note that error() is called
  34. * a fatal error has occurred, and returning to Halide may cause a crash;
  35. * implementations of CompileTimeErrorReporter::error() should never return.
  36. * (Implementations of CompileTimeErrorReporter::warning() may return but
  37. * may also abort(), exit(), etc.)
  38. */
  39. class CompileTimeErrorReporter {
  40. public:
  41. virtual ~CompileTimeErrorReporter() {}
  42. virtual void warning(const char* msg) = 0;
  43. virtual void error(const char* msg) = 0;
  44. };
  45. /** The default error reporter logs to stderr, then throws an exception
  46. * (if WITH_EXCEPTIONS) or calls abort (if not). This allows customization
  47. * of that behavior if a more gentle response to error reporting is desired.
  48. * Note that error_reporter is expected to remain valid across all Halide usage;
  49. * it is up to the caller to ensure that this is the case (and to do any
  50. * cleanup necessary).
  51. */
  52. EXPORT void set_custom_compile_time_error_reporter(CompileTimeErrorReporter* error_reporter);
  53. namespace Internal {
  54. struct ErrorReport {
  55. std::ostringstream *msg;
  56. const char *file;
  57. const char *condition_string;
  58. int line;
  59. bool condition;
  60. bool user;
  61. bool warning;
  62. bool runtime;
  63. ErrorReport(const char *f, int l, const char *cs, bool c, bool u, bool w, bool r) :
  64. msg(NULL), file(f), condition_string(cs), line(l), condition(c), user(u), warning(w), runtime(r) {
  65. if (condition) return;
  66. msg = new std::ostringstream;
  67. const std::string &source_loc = Introspection::get_source_location();
  68. if (user) {
  69. // Only mention where inside of libHalide the error tripped if we have debug level > 0
  70. debug(1) << "User error triggered at " << f << ":" << l << "\n";
  71. if (condition_string) {
  72. debug(1) << "Condition failed: " << condition_string << "\n";
  73. }
  74. if (warning) {
  75. (*msg) << "Warning";
  76. } else {
  77. (*msg) << "Error";
  78. }
  79. if (source_loc.empty()) {
  80. (*msg) << ":\n";
  81. } else {
  82. (*msg) << " at " << source_loc << ":\n";
  83. }
  84. } else {
  85. (*msg) << "Internal ";
  86. if (warning) {
  87. (*msg) << "warning";
  88. } else {
  89. (*msg) << "error";
  90. }
  91. (*msg) << " at " << f << ":" << l;
  92. if (!source_loc.empty()) {
  93. (*msg) << " triggered by user code at " << source_loc << ":\n";
  94. } else {
  95. (*msg) << "\n";
  96. }
  97. if (condition_string) {
  98. (*msg) << "Condition failed: " << condition_string << "\n";
  99. }
  100. }
  101. }
  102. template<typename T>
  103. ErrorReport &operator<<(T x) {
  104. if (condition) return *this;
  105. (*msg) << x;
  106. return *this;
  107. }
  108. /** When you're done using << on the object, and let it fall out of
  109. * scope, this errors out, or throws an exception if they are
  110. * enabled. This is a little dangerous because the destructor will
  111. * also be called if there's an exception in flight due to an
  112. * error in one of the arguments passed to operator<<. We handle
  113. * this by only actually throwing if there isn't an exception in
  114. * flight already.
  115. */
  116. #if __cplusplus >= 201100
  117. ~ErrorReport() noexcept(false) {
  118. #else
  119. ~ErrorReport() {
  120. #endif
  121. if (condition) return;
  122. explode();
  123. }
  124. EXPORT void explode();
  125. };
  126. #define internal_error Halide::Internal::ErrorReport(__FILE__, __LINE__, NULL, false, false, false, false)
  127. #define internal_assert(c) Halide::Internal::ErrorReport(__FILE__, __LINE__, #c, c, false, false, false)
  128. #define user_error Halide::Internal::ErrorReport(__FILE__, __LINE__, NULL, false, true, false, false)
  129. #define user_assert(c) Halide::Internal::ErrorReport(__FILE__, __LINE__, #c, c, true, false, false)
  130. #define user_warning Halide::Internal::ErrorReport(__FILE__, __LINE__, NULL, false, true, true, false)
  131. #define halide_runtime_error Halide::Internal::ErrorReport(__FILE__, __LINE__, NULL, false, true, false, true)
  132. // The nicely named versions get cleaned up at the end of Halide.h,
  133. // but user code might want to do halide-style user_asserts (e.g. the
  134. // Extern macros introduce calls to user_assert), so for that purpose
  135. // we define an equivalent macro that can be used outside of Halide.h
  136. #define _halide_user_assert(c) Halide::Internal::ErrorReport(__FILE__, __LINE__, #c, c, true, false, false)
  137. // N.B. Any function that might throw a user_assert or user_error may
  138. // not be inlined into the user's code, or the line number will be
  139. // misattributed to Halide.h. Either make such functions internal to
  140. // libHalide, or mark them as NO_INLINE.
  141. }
  142. }
  143. #endif