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 /*****************************************************************************/
8 /*****************************************************************************/
10 #include <corjit.h> // for CORJIT_INTERNALERROR
11 #include <safemath.h> // For FitsIn, used by SafeCvt methods.
13 #define FATAL_JIT_EXCEPTION 0x02345678
20 EXCEPTION_POINTERS exceptionPointers;
21 ErrorTrapParam() { jitInfo = NULL; }
24 // Only catch JIT internal errors (will not catch EE generated Errors)
25 extern LONG __JITfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
27 #define setErrorTrap(compHnd, ParamType, paramDef, paramRef) \
28 struct __JITParam : ErrorTrapParam \
32 __JITparam.errc = CORJIT_INTERNALERROR; \
33 __JITparam.jitInfo = compHnd; \
34 __JITparam.param = paramRef; \
35 PAL_TRY(__JITParam *, __JITpParam, &__JITparam) \
37 ParamType paramDef = __JITpParam->param;
39 // Only catch JIT internal errors (will not catch EE generated Errors)
40 #define impJitErrorTrap() \
42 PAL_EXCEPT_FILTER(__JITfilter) \
44 int __errc = __JITparam.errc; (void) __errc;
46 #define endErrorTrap() \
50 #define finallyErrorTrap() \
56 /*****************************************************************************/
58 extern void debugError(const char* msg, const char* file, unsigned line);
59 extern void DECLSPEC_NORETURN badCode();
60 extern void DECLSPEC_NORETURN badCode3(const char* msg, const char* msg2, int arg, __in_z const char* file, unsigned line);
61 extern void DECLSPEC_NORETURN noWay();
62 extern void DECLSPEC_NORETURN NOMEM();
63 extern void DECLSPEC_NORETURN fatal(int errCode);
65 extern void DECLSPEC_NORETURN noWayAssertBody();
66 extern void DECLSPEC_NORETURN noWayAssertBody(const char * cond, const char * file, unsigned line);
68 // Conditionally invoke the noway assert body. The conditional predicate is evaluated using a method on the tlsCompiler.
69 // If a noway_assert is hit, we ask the Compiler whether to raise an exception (i.e., conditionally raise exception.)
70 // To have backward compatibility between v4.5 and v4.0, in min-opts we take a shot at codegen rather than rethrow.
71 extern void noWayAssertBodyConditional(
72 #ifdef FEATURE_TRACELOGGING
73 const char * file, unsigned line
76 extern void noWayAssertBodyConditional(const char * cond, const char * file, unsigned line);
78 #if !defined(_TARGET_X86_) || !defined(LEGACY_BACKEND)
80 // This guy can return based on Config flag/Debugger
81 extern void notYetImplemented(const char * msg, const char * file, unsigned line);
82 #define NYI(msg) notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
83 #define NYI_IF(cond, msg) if (cond) notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
87 #define NYI_AMD64(msg) notYetImplemented("NYI_AMD64: " # msg, __FILE__, __LINE__)
88 #define NYI_X86(msg) do { } while (0)
89 #define NYI_ARM(msg) do { } while (0)
90 #define NYI_ARM64(msg) do { } while (0)
92 #elif defined(_TARGET_X86_)
94 #define NYI_AMD64(msg) do { } while (0)
95 #define NYI_X86(msg) notYetImplemented("NYI_X86: " # msg, __FILE__, __LINE__)
96 #define NYI_ARM(msg) do { } while (0)
97 #define NYI_ARM64(msg) do { } while (0)
99 #elif defined(_TARGET_ARM_)
101 #define NYI_AMD64(msg) do { } while (0)
102 #define NYI_X86(msg) do { } while (0)
103 #define NYI_ARM(msg) notYetImplemented("NYI_ARM: " # msg, __FILE__, __LINE__)
104 #define NYI_ARM64(msg) do { } while (0)
106 #elif defined(_TARGET_ARM64_)
108 #define NYI_AMD64(msg) do { } while (0)
109 #define NYI_X86(msg) do { } while (0)
110 #define NYI_ARM(msg) do { } while (0)
111 #define NYI_ARM64(msg) notYetImplemented("NYI_ARM64: " # msg, __FILE__, __LINE__)
115 #error "Unknown platform, not x86, ARM, or AMD64?"
119 #else // defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
122 #define NYI(msg) assert(!msg)
123 #define NYI_AMD64(msg) do { } while (0)
124 #define NYI_ARM(msg) do { } while (0)
125 #define NYI_ARM64(msg) do { } while (0)
127 #endif // _TARGET_X86_
129 #if !defined(_TARGET_X86_) && !defined(FEATURE_STACK_FP_X87)
130 #define NYI_FLAT_FP_X87(msg) notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
131 #define NYI_FLAT_FP_X87_NC(msg) notYetImplemented("NYI: " #msg, __FILE__, __LINE__)
135 #define NYI_FLAT_FP_X87(msg) do { } while (0)
136 #define NYI_FLAT_FP_X87_NC(msg) do { } while (0)
138 #endif // !_TARGET_X86_ && !FEATURE_STACK_FP_X87
142 #define NO_WAY(msg) (debugError(msg, __FILE__, __LINE__), noWay())
143 // Used for fallback stress mode
144 #define NO_WAY_NOASSERT(msg) noWay()
145 #define BADCODE(msg) (debugError(msg, __FILE__, __LINE__), badCode())
146 #define BADCODE3(msg, msg2, arg) badCode3(msg, msg2, arg, __FILE__, __LINE__)
147 //Used for an assert that we want to convert into BADCODE to force minopts, or in minopts to force codegen.
148 #define noway_assert(cond) do { if (!(cond)) { noWayAssertBodyConditional( # cond , __FILE__, __LINE__); } } while (0)
149 #define unreached() noWayAssertBody("unreached", __FILE__, __LINE__)
153 #define NO_WAY(msg) noWay()
154 #define BADCODE(msg) badCode()
155 #define BADCODE3(msg, msg2, arg) badCode()
157 #ifdef FEATURE_TRACELOGGING
158 #define NOWAY_ASSERT_BODY_ARGUMENTS __FILE__, __LINE__
160 #define NOWAY_ASSERT_BODY_ARGUMENTS
163 #define noway_assert(cond) do { if (!(cond)) { noWayAssertBodyConditional(NOWAY_ASSERT_BODY_ARGUMENTS); } } while (0)
164 #define unreached() noWayAssertBody()
168 // IMPL_LIMITATION is called when we encounter valid IL that is not
169 // supported by our current implementation because of various
170 // limitations (that could be removed in the future)
171 #define IMPL_LIMITATION(msg) NO_WAY(msg)
174 #if defined(_HOST_X86_)
176 // While debugging in an Debugger, the "int 3" will cause the program to break
177 // Outside, the exception handler will just filter out the "int 3".
179 #define BreakIfDebuggerPresent() \
180 do { __try { __asm {int 3} } __except(EXCEPTION_EXECUTE_HANDLER) {} } \
184 #define BreakIfDebuggerPresent() \
185 do { if (IsDebuggerPresent()) DebugBreak(); } \
190 DWORD getBreakOnBadCode();
193 // For narrowing numeric conversions, the following two methods ensure that the
194 // source value fits in the destination type, using either "assert" or
195 // "noway_assert" to validate the conversion. Obviously, each returns the source value as
196 // the destination type.
198 // (There is an argument that these should be macros, to let the preprocessor capture
199 // a more useful file/line for the error message. But then we have to use comma expressions
200 // so that these can be used in expressions, etc., which is ugly. So I propose we rely on
201 // getting stack traces in other ways.)
202 template <typename Dst, typename Src>
203 inline Dst SafeCvtAssert(Src val)
205 assert(FitsIn<Dst>(val));
206 return static_cast<Dst>(val);
209 template <typename Dst, typename Src>
210 inline Dst SafeCvtNowayAssert(Src val)
212 noway_assert(FitsIn<Dst>(val));
213 return static_cast<Dst>(val);