Merge pull request #6362 from svick/culturedata-regionnames
[platform/upstream/coreclr.git] / src / jit / error.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 /*****************************************************************************/
5
6 #ifndef _ERROR_H_
7 #define _ERROR_H_
8 /*****************************************************************************/
9
10 #include <corjit.h>   // for CORJIT_INTERNALERROR
11 #include <safemath.h> // For FitsIn, used by SafeCvt methods.
12
13 #define FATAL_JIT_EXCEPTION 0x02345678
14 class Compiler;
15
16 struct ErrorTrapParam
17 {
18     int                errc;
19     ICorJitInfo*       jitInfo;
20     EXCEPTION_POINTERS exceptionPointers;
21     ErrorTrapParam()
22     {
23         jitInfo = nullptr;
24     }
25 };
26
27 // Only catch JIT internal errors (will not catch EE generated Errors)
28 extern LONG __JITfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
29
30 #define setErrorTrap(compHnd, ParamType, paramDef, paramRef)                                                           \
31     struct __JITParam : ErrorTrapParam                                                                                 \
32     {                                                                                                                  \
33         ParamType param;                                                                                               \
34     } __JITparam;                                                                                                      \
35     __JITparam.errc    = CORJIT_INTERNALERROR;                                                                         \
36     __JITparam.jitInfo = compHnd;                                                                                      \
37     __JITparam.param   = paramRef;                                                                                     \
38     PAL_TRY(__JITParam*, __JITpParam, &__JITparam)                                                                     \
39     {                                                                                                                  \
40         ParamType paramDef = __JITpParam->param;
41
42 // Only catch JIT internal errors (will not catch EE generated Errors)
43 #define impJitErrorTrap()                                                                                              \
44     }                                                                                                                  \
45     PAL_EXCEPT_FILTER(__JITfilter)                                                                                     \
46     {                                                                                                                  \
47         int __errc = __JITparam.errc;                                                                                  \
48         (void)__errc;
49
50 #define endErrorTrap()                                                                                                 \
51     }                                                                                                                  \
52     PAL_ENDTRY
53
54 #define finallyErrorTrap()                                                                                             \
55     }                                                                                                                  \
56     PAL_FINALLY                                                                                                        \
57     {
58
59 /*****************************************************************************/
60
61 extern void debugError(const char* msg, const char* file, unsigned line);
62 extern void DECLSPEC_NORETURN badCode();
63 extern void                   DECLSPEC_NORETURN
64 badCode3(const char* msg, const char* msg2, int arg, __in_z const char* file, unsigned line);
65 extern void DECLSPEC_NORETURN noWay();
66 extern void DECLSPEC_NORETURN NOMEM();
67 extern void DECLSPEC_NORETURN fatal(int errCode);
68
69 extern void DECLSPEC_NORETURN noWayAssertBody();
70 extern void DECLSPEC_NORETURN noWayAssertBody(const char* cond, const char* file, unsigned line);
71
72 // Conditionally invoke the noway assert body. The conditional predicate is evaluated using a method on the tlsCompiler.
73 // If a noway_assert is hit, we ask the Compiler whether to raise an exception (i.e., conditionally raise exception.)
74 // To have backward compatibility between v4.5 and v4.0, in min-opts we take a shot at codegen rather than rethrow.
75 extern void noWayAssertBodyConditional(
76 #ifdef FEATURE_TRACELOGGING
77     const char* file, unsigned line
78 #endif
79     );
80 extern void noWayAssertBodyConditional(const char* cond, const char* file, unsigned line);
81
82 #if !defined(_TARGET_X86_) || !defined(LEGACY_BACKEND)
83
84 // This guy can return based on Config flag/Debugger
85 extern void notYetImplemented(const char* msg, const char* file, unsigned line);
86 #define NYI(msg) notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
87 #define NYI_IF(cond, msg)                                                                                              \
88     if (cond)                                                                                                          \
89     notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
90
91 #ifdef _TARGET_AMD64_
92
93 #define NYI_AMD64(msg) notYetImplemented("NYI_AMD64: " #msg, __FILE__, __LINE__)
94 #define NYI_X86(msg)                                                                                                   \
95     do                                                                                                                 \
96     {                                                                                                                  \
97     } while (0)
98 #define NYI_ARM(msg)                                                                                                   \
99     do                                                                                                                 \
100     {                                                                                                                  \
101     } while (0)
102 #define NYI_ARM64(msg)                                                                                                 \
103     do                                                                                                                 \
104     {                                                                                                                  \
105     } while (0)
106
107 #elif defined(_TARGET_X86_)
108
109 #define NYI_AMD64(msg)                                                                                                 \
110     do                                                                                                                 \
111     {                                                                                                                  \
112     } while (0)
113 #define NYI_X86(msg) notYetImplemented("NYI_X86: " #msg, __FILE__, __LINE__)
114 #define NYI_ARM(msg)                                                                                                   \
115     do                                                                                                                 \
116     {                                                                                                                  \
117     } while (0)
118 #define NYI_ARM64(msg)                                                                                                 \
119     do                                                                                                                 \
120     {                                                                                                                  \
121     } while (0)
122
123 #elif defined(_TARGET_ARM_)
124
125 #define NYI_AMD64(msg)                                                                                                 \
126     do                                                                                                                 \
127     {                                                                                                                  \
128     } while (0)
129 #define NYI_X86(msg)                                                                                                   \
130     do                                                                                                                 \
131     {                                                                                                                  \
132     } while (0)
133 #define NYI_ARM(msg) notYetImplemented("NYI_ARM: " #msg, __FILE__, __LINE__)
134 #define NYI_ARM64(msg)                                                                                                 \
135     do                                                                                                                 \
136     {                                                                                                                  \
137     } while (0)
138
139 #elif defined(_TARGET_ARM64_)
140
141 #define NYI_AMD64(msg)                                                                                                 \
142     do                                                                                                                 \
143     {                                                                                                                  \
144     } while (0)
145 #define NYI_X86(msg)                                                                                                   \
146     do                                                                                                                 \
147     {                                                                                                                  \
148     } while (0)
149 #define NYI_ARM(msg)                                                                                                   \
150     do                                                                                                                 \
151     {                                                                                                                  \
152     } while (0)
153 #define NYI_ARM64(msg) notYetImplemented("NYI_ARM64: " #msg, __FILE__, __LINE__)
154
155 #else
156
157 #error "Unknown platform, not x86, ARM, or AMD64?"
158
159 #endif
160
161 #else // defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
162
163 #define NYI(msg) assert(!msg)
164 #define NYI_AMD64(msg)                                                                                                 \
165     do                                                                                                                 \
166     {                                                                                                                  \
167     } while (0)
168 #define NYI_ARM(msg)                                                                                                   \
169     do                                                                                                                 \
170     {                                                                                                                  \
171     } while (0)
172 #define NYI_ARM64(msg)                                                                                                 \
173     do                                                                                                                 \
174     {                                                                                                                  \
175     } while (0)
176
177 #endif // _TARGET_X86_
178
179 #if !defined(_TARGET_X86_) && !defined(FEATURE_STACK_FP_X87)
180 #define NYI_FLAT_FP_X87(msg) notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
181 #define NYI_FLAT_FP_X87_NC(msg) notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
182
183 #else
184
185 #define NYI_FLAT_FP_X87(msg)                                                                                           \
186     do                                                                                                                 \
187     {                                                                                                                  \
188     } while (0)
189 #define NYI_FLAT_FP_X87_NC(msg)                                                                                        \
190     do                                                                                                                 \
191     {                                                                                                                  \
192     } while (0)
193
194 #endif // !_TARGET_X86_ && !FEATURE_STACK_FP_X87
195
196 #ifdef DEBUG
197 #define NO_WAY(msg) (debugError(msg, __FILE__, __LINE__), noWay())
198 // Used for fallback stress mode
199 #define NO_WAY_NOASSERT(msg) noWay()
200 #define BADCODE(msg) (debugError(msg, __FILE__, __LINE__), badCode())
201 #define BADCODE3(msg, msg2, arg) badCode3(msg, msg2, arg, __FILE__, __LINE__)
202 // Used for an assert that we want to convert into BADCODE to force minopts, or in minopts to force codegen.
203 #define noway_assert(cond)                                                                                             \
204     do                                                                                                                 \
205     {                                                                                                                  \
206         if (!(cond))                                                                                                   \
207         {                                                                                                              \
208             noWayAssertBodyConditional(#cond, __FILE__, __LINE__);                                                     \
209         }                                                                                                              \
210     } while (0)
211 #define unreached() noWayAssertBody("unreached", __FILE__, __LINE__)
212
213 #else
214
215 #define NO_WAY(msg) noWay()
216 #define BADCODE(msg) badCode()
217 #define BADCODE3(msg, msg2, arg) badCode()
218
219 #ifdef FEATURE_TRACELOGGING
220 #define NOWAY_ASSERT_BODY_ARGUMENTS __FILE__, __LINE__
221 #else
222 #define NOWAY_ASSERT_BODY_ARGUMENTS
223 #endif
224
225 #define noway_assert(cond)                                                                                             \
226     do                                                                                                                 \
227     {                                                                                                                  \
228         if (!(cond))                                                                                                   \
229         {                                                                                                              \
230             noWayAssertBodyConditional(NOWAY_ASSERT_BODY_ARGUMENTS);                                                   \
231         }                                                                                                              \
232     } while (0)
233 #define unreached() noWayAssertBody()
234
235 #endif
236
237 // IMPL_LIMITATION is called when we encounter valid IL that is not
238 // supported by our current implementation because of various
239 // limitations (that could be removed in the future)
240 #define IMPL_LIMITATION(msg) NO_WAY(msg)
241
242 #if defined(_HOST_X86_)
243
244 // While debugging in an Debugger, the "int 3" will cause the program to break
245 // Outside, the exception handler will just filter out the "int 3".
246
247 #define BreakIfDebuggerPresent()                                                                                       \
248     do                                                                                                                 \
249     {                                                                                                                  \
250         __try                                                                                                          \
251         {                                                                                                              \
252             __asm {int 3}                                                                                              \
253         }                                                                                                              \
254         __except (EXCEPTION_EXECUTE_HANDLER)                                                                           \
255         {                                                                                                              \
256         }                                                                                                              \
257     } while (0)
258
259 #else
260 #define BreakIfDebuggerPresent()                                                                                       \
261     do                                                                                                                 \
262     {                                                                                                                  \
263         if (IsDebuggerPresent())                                                                                       \
264             DebugBreak();                                                                                              \
265     } while (0)
266 #endif
267
268 #ifdef DEBUG
269 DWORD getBreakOnBadCode();
270 #endif
271
272 // For narrowing numeric conversions, the following two methods ensure that the
273 // source value fits in the destination type, using either "assert" or
274 // "noway_assert" to validate the conversion.  Obviously, each returns the source value as
275 // the destination type.
276
277 // (There is an argument that these should be macros, to let the preprocessor capture
278 // a more useful file/line for the error message.  But then we have to use comma expressions
279 // so that these can be used in expressions, etc., which is ugly.  So I propose we rely on
280 // getting stack traces in other ways.)
281 template <typename Dst, typename Src>
282 inline Dst SafeCvtAssert(Src val)
283 {
284     assert(FitsIn<Dst>(val));
285     return static_cast<Dst>(val);
286 }
287
288 template <typename Dst, typename Src>
289 inline Dst SafeCvtNowayAssert(Src val)
290 {
291     noway_assert(FitsIn<Dst>(val));
292     return static_cast<Dst>(val);
293 }
294
295 #endif