Merge pull request #3535 from hughbe/patch-3
[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() { jitInfo = NULL; }
22 };
23
24 extern  LONG            __EEfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
25         // Only catch JIT internal errors (will not catch EE generated Errors)
26 extern  LONG            __JITfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
27
28 #define                 setErrorTrap(compHnd, ParamType, paramDef, paramRef) \
29     struct __JITParam : ErrorTrapParam                                      \
30     {                                                                       \
31         ParamType param;                                                    \
32     } __JITparam;                                                           \
33     __JITparam.errc = CORJIT_INTERNALERROR;                                 \
34     __JITparam.jitInfo = compHnd;                                           \
35     __JITparam.param = paramRef;                                            \
36     PAL_TRY(__JITParam *, __JITpParam, &__JITparam)                         \
37     {                                                                       \
38         ParamType paramDef = __JITpParam->param;
39
40         // Catch only JitGeneratedErrors
41 #define                 impJitErrorTrap()                                   \
42     }                                                                       \
43     PAL_EXCEPT_FILTER(__JITfilter)                                          \
44     {                                                                       \
45         int __errc = __JITparam.errc; (void) __errc;
46
47         // Catch all errors (including recoverable ones from the EE)
48 #define                 impErrorTrap()                                      \
49     }                                                                       \
50     PAL_EXCEPT_FILTER(__EEfilter)                                           \
51     {                                                                       \
52         __JITparam.jitInfo->HandleException(&__JITparam.exceptionPointers);
53
54 #define                 endErrorTrap()                                      \
55     }                                                                       \
56     PAL_ENDTRY
57
58 #define                 finallyErrorTrap()                                  \
59     }                                                                       \
60     PAL_FINALLY                                                             \
61     {
62
63
64 /*****************************************************************************/
65
66 extern void debugError(const char* msg, const char* file, unsigned line);
67 extern void DECLSPEC_NORETURN badCode();
68 extern void DECLSPEC_NORETURN badCode3(const char* msg, const char* msg2, int arg, __in_z const char* file, unsigned line);
69 extern void DECLSPEC_NORETURN noWay();
70 extern void DECLSPEC_NORETURN NOMEM();
71 extern void DECLSPEC_NORETURN fatal(int errCode);
72
73 extern void DECLSPEC_NORETURN noWayAssertBody();
74 extern void DECLSPEC_NORETURN noWayAssertBody(const char * cond, const char * file, unsigned line);
75
76 // Conditionally invoke the noway assert body. The conditional predicate is evaluated using a method on the tlsCompiler.
77 // If a noway_assert is hit, we ask the Compiler whether to raise an exception (i.e., conditionally raise exception.)
78 // To have backward compatibility between v4.5 and v4.0, in min-opts we take a shot at codegen rather than rethrow.
79 extern void noWayAssertBodyConditional(
80 #ifdef FEATURE_TRACELOGGING
81         const char * file, unsigned line
82 #endif
83 );
84 extern void noWayAssertBodyConditional(const char * cond, const char * file, unsigned line);
85
86 #if !defined(_TARGET_X86_) || !defined(LEGACY_BACKEND)
87
88 // This guy can return based on Config flag/Debugger
89 extern void notYetImplemented(const char * msg, const char * file, unsigned line);
90 #define NYI(msg)                   notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
91 #define NYI_IF(cond, msg)          if (cond) notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
92
93 #ifdef _TARGET_AMD64_
94
95 #define NYI_AMD64(msg)    notYetImplemented("NYI_AMD64: " # msg, __FILE__, __LINE__)
96 #define NYI_X86(msg)      do { } while (0)
97 #define NYI_ARM(msg)      do { } while (0)
98 #define NYI_ARM64(msg)    do { } while (0)
99
100 #elif defined(_TARGET_X86_)
101
102 #define NYI_AMD64(msg)    do { } while (0)
103 #define NYI_X86(msg)      notYetImplemented("NYI_X86: " # msg, __FILE__, __LINE__)
104 #define NYI_ARM(msg)      do { } while (0)
105 #define NYI_ARM64(msg)    do { } while (0)
106
107 #elif defined(_TARGET_ARM_)
108
109 #define NYI_AMD64(msg)    do { } while (0)
110 #define NYI_X86(msg)      do { } while (0)
111 #define NYI_ARM(msg)      notYetImplemented("NYI_ARM: " # msg, __FILE__, __LINE__)
112 #define NYI_ARM64(msg)    do { } while (0)
113
114 #elif defined(_TARGET_ARM64_)
115
116 #define NYI_AMD64(msg)    do { } while (0)
117 #define NYI_X86(msg)      do { } while (0)
118 #define NYI_ARM(msg)      do { } while (0)
119 #define NYI_ARM64(msg)    notYetImplemented("NYI_ARM64: " # msg, __FILE__, __LINE__)
120
121 #else
122
123 #error "Unknown platform, not x86, ARM, or AMD64?"
124
125 #endif
126
127 #else // defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
128
129
130 #define NYI(msg)          assert(!msg)
131 #define NYI_AMD64(msg)    do { } while (0)
132 #define NYI_ARM(msg)      do { } while (0)
133 #define NYI_ARM64(msg)    do { } while (0)
134
135 #endif // _TARGET_X86_
136
137 #if !defined(_TARGET_X86_) && !defined(FEATURE_STACK_FP_X87)
138 #define NYI_FLAT_FP_X87(msg)    notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
139 #define NYI_FLAT_FP_X87_NC(msg) notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
140
141 #else
142
143 #define NYI_FLAT_FP_X87(msg)    do { } while (0)
144 #define NYI_FLAT_FP_X87_NC(msg) do { } while (0)
145
146 #endif // !_TARGET_X86_ && !FEATURE_STACK_FP_X87
147
148
149 #ifdef DEBUG
150 #define NO_WAY(msg) (debugError(msg, __FILE__, __LINE__), noWay())
151 // Used for fallback stress mode
152 #define NO_WAY_NOASSERT(msg) noWay()
153 #define BADCODE(msg) (debugError(msg, __FILE__, __LINE__), badCode())
154 #define BADCODE3(msg, msg2, arg) badCode3(msg, msg2, arg, __FILE__, __LINE__)
155 //Used for an assert that we want to convert into BADCODE to force minopts, or in minopts to force codegen.
156 #define noway_assert(cond) do { if (!(cond)) { noWayAssertBodyConditional( # cond , __FILE__, __LINE__); } } while (0)
157 #define unreached() noWayAssertBody("unreached", __FILE__, __LINE__)
158
159 #else 
160
161 #define NO_WAY(msg) noWay()
162 #define BADCODE(msg) badCode()
163 #define BADCODE3(msg, msg2, arg) badCode()
164
165 #ifdef FEATURE_TRACELOGGING
166 #define NOWAY_ASSERT_BODY_ARGUMENTS __FILE__, __LINE__
167 #else
168 #define NOWAY_ASSERT_BODY_ARGUMENTS
169 #endif
170
171 #define noway_assert(cond) do { if (!(cond)) { noWayAssertBodyConditional(NOWAY_ASSERT_BODY_ARGUMENTS); } } while (0)
172 #define unreached() noWayAssertBody()
173
174 #endif
175
176     // IMPL_LIMITATION is called when we encounter valid IL that is not
177     // supported by our current implementation because of various
178     // limitations (that could be removed in the future)
179 #define IMPL_LIMITATION(msg) NO_WAY(msg)
180
181
182 #if defined(_HOST_X86_)
183
184 // While debugging in an Debugger, the "int 3" will cause the program to break
185 // Outside, the exception handler will just filter out the "int 3".
186
187 #define BreakIfDebuggerPresent()                                            \
188     do { __try { __asm {int 3} } __except(EXCEPTION_EXECUTE_HANDLER) {} }   \
189     while (0)
190
191 #else
192 #define BreakIfDebuggerPresent()                                            \
193     do { if (IsDebuggerPresent()) DebugBreak(); }                           \
194     while (0)
195 #endif
196
197 #ifdef DEBUG
198 DWORD getBreakOnBadCode();
199 #endif
200
201 // For narrowing numeric conversions, the following two methods ensure that the
202 // source value fits in the destination type, using either "assert" or
203 // "noway_assert" to validate the conversion.  Obviously, each returns the source value as
204 // the destination type.
205
206 // (There is an argument that these should be macros, to let the preprocessor capture
207 // a more useful file/line for the error message.  But then we have to use comma expressions
208 // so that these can be used in expressions, etc., which is ugly.  So I propose we rely on
209 // getting stack traces in other ways.)
210 template <typename Dst, typename Src>
211 inline Dst SafeCvtAssert(Src val)
212 {
213     assert(FitsIn<Dst>(val));
214     return static_cast<Dst>(val);
215 }
216
217 template <typename Dst, typename Src>
218 inline Dst SafeCvtNowayAssert(Src val)
219 {
220     noway_assert(FitsIn<Dst>(val));
221     return static_cast<Dst>(val);
222 }
223
224
225 #endif