xref: /aosp_15_r20/external/executorch/runtime/core/error.h (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 /**
10  * @file
11  * ExecuTorch Error declarations.
12  */
13 
14 #pragma once
15 
16 #include <stdint.h>
17 
18 #include <executorch/runtime/platform/log.h>
19 
20 namespace executorch {
21 namespace runtime {
22 
23 // Alias error code integral type to minimal platform width (32-bits for now).
24 typedef uint32_t error_code_t;
25 
26 /**
27  * ExecuTorch Error type.
28  */
29 enum class Error : error_code_t {
30   /*
31    * System errors.
32    */
33 
34   /// Status indicating a successful operation.
35   Ok = 0x00,
36 
37   /// An internal error occurred.
38   Internal = 0x01,
39 
40   /// Status indicating the executor is in an invalid state for a target
41   /// operation
42   InvalidState = 0x2,
43 
44   /// Status indicating there are no more steps of execution to run
45   EndOfMethod = 0x03,
46 
47   /*
48    * Logical errors.
49    */
50 
51   /// Operation is not supported in the current context.
52   NotSupported = 0x10,
53 
54   /// Operation is not yet implemented.
55   NotImplemented = 0x11,
56 
57   /// User provided an invalid argument.
58   InvalidArgument = 0x12,
59 
60   /// Object is an invalid type for the operation.
61   InvalidType = 0x13,
62 
63   /// Operator(s) missing in the operator registry.
64   OperatorMissing = 0x14,
65 
66   /*
67    * Resource errors.
68    */
69 
70   /// Requested resource could not be found.
71   NotFound = 0x20,
72 
73   /// Could not allocate the requested memory.
74   MemoryAllocationFailed = 0x21,
75 
76   /// Could not access a resource.
77   AccessFailed = 0x22,
78 
79   /// Error caused by the contents of a program.
80   InvalidProgram = 0x23,
81 
82   /*
83    * Delegate errors.
84    */
85 
86   /// Init stage: Backend receives an incompatible delegate version.
87   DelegateInvalidCompatibility = 0x30,
88   /// Init stage: Backend fails to allocate memory.
89   DelegateMemoryAllocationFailed = 0x31,
90   /// Execute stage: The handle is invalid.
91   DelegateInvalidHandle = 0x32,
92 
93 };
94 
95 } // namespace runtime
96 } // namespace executorch
97 
98 namespace torch {
99 namespace executor {
100 // TODO(T197294990): Remove these deprecated aliases once all users have moved
101 // to the new `::executorch` namespaces.
102 using ::executorch::runtime::Error;
103 using ::executorch::runtime::error_code_t;
104 } // namespace executor
105 } // namespace torch
106 
107 /**
108  * If cond__ is false, log the specified message and return the specified Error
109  * from the current function, which must be of return type
110  * executorch::runtime::Error.
111  *
112  * @param[in] cond__ The condition to be checked, asserted as true.
113  * @param[in] error__ Error enum value to return without the `Error::` prefix,
114  * like `InvalidArgument`.
115  * @param[in] message__ Format string for the log error message.
116  * @param[in] ... Optional additional arguments for the format string.
117  */
118 #define ET_CHECK_OR_RETURN_ERROR(cond__, error__, message__, ...) \
119   {                                                               \
120     if (!(cond__)) {                                              \
121       ET_LOG(Error, message__, ##__VA_ARGS__);                    \
122       return ::executorch::runtime::Error::error__;               \
123     }                                                             \
124   }
125 
126 /**
127  * If error__ is not Error::Ok, optionally log a message and return the error
128  * from the current function, which must be of return type
129  * executorch::runtime::Error.
130  *
131  * @param[in] error__ Error enum value asserted to be Error::Ok.
132  * @param[in] ... Optional format string for the log error message and its
133  * arguments.
134  */
135 #define ET_CHECK_OK_OR_RETURN_ERROR(error__, ...) \
136   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR(error__, ##__VA_ARGS__)
137 
138 // Internal only: Use ET_CHECK_OK_OR_RETURN_ERROR() instead.
139 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR(...) \
140   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_SELECT(    \
141       __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) \
142   (__VA_ARGS__)
143 
144 /**
145  * Internal only: Use ET_CHECK_OK_OR_RETURN_ERROR() instead.
146  * This macro selects the correct version of
147  * ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR based on the number of arguments passed.
148  * It uses a trick with the preprocessor to count the number of arguments and
149  * then selects the appropriate macro.
150  *
151  * The macro expansion uses __VA_ARGS__ to accept any number of arguments and
152  * then appends them to ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_, followed by the
153  * count of arguments. The count is determined by the macro
154  * ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_SELECT which takes the arguments and
155  * passes them along with a sequence of numbers (2, 1). The preprocessor then
156  * matches this sequence to the correct number of arguments provided.
157  *
158  * If two arguments are passed, ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_2 is
159  * selected, suitable for cases where an error code and a custom message are
160  * provided. If only one argument is passed,
161  * ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_1 is selected, which is used for cases
162  * with just an error code.
163  *
164  * Usage:
165  * ET_CHECK_OK_OR_RETURN_ERROR(error_code); // Calls v1
166  * ET_CHECK_OK_OR_RETURN_ERROR(error_code, "Error message", ...); // Calls v2
167  */
168 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_SELECT( \
169     _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) \
170   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_##N
171 
172 // Internal only: Use ET_CHECK_OK_OR_RETURN_ERROR() instead.
173 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_1(error__)   \
174   do {                                                    \
175     const auto et_error__ = (error__);                    \
176     if (et_error__ != ::executorch::runtime::Error::Ok) { \
177       return et_error__;                                  \
178     }                                                     \
179   } while (0)
180 
181 // Internal only: Use ET_CHECK_OK_OR_RETURN_ERROR() instead.
182 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_2(error__, message__, ...) \
183   do {                                                                  \
184     const auto et_error__ = (error__);                                  \
185     if (et_error__ != ::executorch::runtime::Error::Ok) {               \
186       ET_LOG(Error, message__, ##__VA_ARGS__);                          \
187       return et_error__;                                                \
188     }                                                                   \
189   } while (0)
190 
191 // Internal only: Use ET_CHECK_OK_OR_RETURN_ERROR() instead.
192 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_3 \
193   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_2
194 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_4 \
195   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_2
196 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_5 \
197   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_2
198 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_6 \
199   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_2
200 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_7 \
201   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_2
202 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_8 \
203   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_2
204 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_9 \
205   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_2
206 #define ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_10 \
207   ET_INTERNAL_CHECK_OK_OR_RETURN_ERROR_2
208