1 #pragma once 2 #include <c10/util/Exception.h> 3 4 namespace c10 { 5 class TORCH_API BackendRuntimeException : public c10::Error { 6 public: 7 // Use debug_handle to throw exception BackendRuntimeException(SourceLocation loc,std::string msg,int64_t debug_handle)8 BackendRuntimeException( 9 SourceLocation loc, 10 std::string msg, 11 int64_t debug_handle) 12 : c10::Error(loc, msg) { 13 debug_handles.push_back(debug_handle); 14 } 15 // If rethrowing, can push another debug_handle 16 // This is useful in couple of scenarios. 17 // 1. A submodule is lowered and lite interperter has CallMethod 18 // to lowered module's method. In this case lowered module will throw with 19 // a handle, plus there will be another debug handle corresponding 20 // to the CallMethod node in lite interpreter. Both together give complete 21 // trace. This function allows lite interpreter to rethrow with debug 22 // handle it has for CallMethod. 23 // 2. Another scenarios is when lite interperter can make function calls or 24 // the lowered backend also has function call ability. Thus we have 25 // multiple function frames. Now we need a stack of handles to symbolicate 26 // entire stack trace. pushDebugHandle(int64_t debug_handle)27 void pushDebugHandle(int64_t debug_handle) { 28 debug_handles.push_back(debug_handle); 29 } getDebugHandles()30 const std::vector<int64_t>& getDebugHandles() { 31 return debug_handles; 32 } 33 34 private: 35 // Stores stack of debug handles. 36 std::vector<int64_t> debug_handles; 37 }; 38 39 } // namespace c10 40 #define TORCH_DELEGATED_BACKEND_THROW(cond, msg, debug_handle) \ 41 if (C10_UNLIKELY_OR_CONST(!(cond))) { \ 42 throw ::c10::BackendRuntimeException( \ 43 {__func__, __FILE__, static_cast<uint32_t>(__LINE__)}, \ 44 msg, \ 45 debug_handle); \ 46 } 47 48 #define TORCH_DELEGATED_BACKEND_RETHROW(e, debug_handle) \ 49 do { \ 50 e.pushDebugHandle(debug_handle); \ 51 throw; \ 52 } while (false) 53 54 #define DEBUG_HANDLE_UNKNOWN -1 55