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;
27 // Only catch JIT internal errors (will not catch EE generated Errors)
28 extern LONG __JITfilter(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
30 #define setErrorTrap(compHnd, ParamType, paramDef, paramRef) \
31 struct __JITParam : ErrorTrapParam \
35 __JITparam.errc = CORJIT_INTERNALERROR; \
36 __JITparam.jitInfo = compHnd; \
37 __JITparam.param = paramRef; \
38 PAL_TRY(__JITParam*, __JITpParam, &__JITparam) \
40 ParamType paramDef = __JITpParam->param;
42 // Only catch JIT internal errors (will not catch EE generated Errors)
43 #define impJitErrorTrap() \
45 PAL_EXCEPT_FILTER(__JITfilter) \
47 int __errc = __JITparam.errc; \
50 #define endErrorTrap() \
54 #define finallyErrorTrap() \
59 /*****************************************************************************/
63 extern void debugError(const char* msg, const char* file, unsigned line);
64 extern void DECLSPEC_NORETURN badCode();
65 extern void DECLSPEC_NORETURN badCode3(const char* msg, const char* msg2, int arg, __in_z const char* file, unsigned line);
66 extern void DECLSPEC_NORETURN noWay();
67 extern void DECLSPEC_NORETURN NOMEM();
68 extern void DECLSPEC_NORETURN fatal(int errCode);
70 extern void DECLSPEC_NORETURN noWayAssertBody();
71 extern void DECLSPEC_NORETURN noWayAssertBody(const char* cond, const char* file, unsigned line);
73 // Conditionally invoke the noway assert body. The conditional predicate is evaluated using a method on the tlsCompiler.
74 // If a noway_assert is hit, we ask the Compiler whether to raise an exception (i.e., conditionally raise exception.)
75 // To have backward compatibility between v4.5 and v4.0, in min-opts we take a shot at codegen rather than rethrow.
76 extern void noWayAssertBodyConditional(
77 #ifdef FEATURE_TRACELOGGING
78 const char* file, unsigned line
81 extern void noWayAssertBodyConditional(const char* cond, const char* file, unsigned line);
84 #define NO_WAY(msg) (debugError(msg, __FILE__, __LINE__), noWay())
85 // Used for fallback stress mode
86 #define NO_WAY_NOASSERT(msg) noWay()
87 #define BADCODE(msg) (debugError(msg, __FILE__, __LINE__), badCode())
88 #define BADCODE3(msg, msg2, arg) badCode3(msg, msg2, arg, __FILE__, __LINE__)
89 // Used for an assert that we want to convert into BADCODE to force minopts, or in minopts to force codegen.
90 #define noway_assert(cond) \
95 noWayAssertBodyConditional(#cond, __FILE__, __LINE__); \
98 #define unreached() noWayAssertBody("unreached", __FILE__, __LINE__)
100 #define NOWAY_MSG(msg) noWayAssertBodyConditional(msg, __FILE__, __LINE__)
104 #define NO_WAY(msg) noWay()
105 #define BADCODE(msg) badCode()
106 #define BADCODE3(msg, msg2, arg) badCode()
108 #ifdef FEATURE_TRACELOGGING
109 #define NOWAY_ASSERT_BODY_ARGUMENTS __FILE__, __LINE__
111 #define NOWAY_ASSERT_BODY_ARGUMENTS
114 #define noway_assert(cond) \
119 noWayAssertBodyConditional(NOWAY_ASSERT_BODY_ARGUMENTS); \
122 #define unreached() noWayAssertBody()
124 #define NOWAY_MSG(msg) noWayAssertBodyConditional(NOWAY_ASSERT_BODY_ARGUMENTS)
128 // IMPL_LIMITATION is called when we encounter valid IL that is not
129 // supported by our current implementation because of various
130 // limitations (that could be removed in the future)
131 #define IMPL_LIMITATION(msg) NO_WAY(msg)
133 #if !defined(_TARGET_X86_) || !defined(LEGACY_BACKEND)
137 // This guy can return based on Config flag/Debugger
138 extern void notYetImplemented(const char* msg, const char* file, unsigned line);
139 #define NYIRAW(msg) notYetImplemented(msg, __FILE__, __LINE__)
141 #else // !defined(ALT_JIT)
143 #define NYIRAW(msg) NOWAY_MSG(msg)
145 #endif // !defined(ALT_JIT)
147 #define NYI(msg) NYIRAW("NYI: " msg)
148 #define NYI_IF(cond, msg) if (cond) NYIRAW("NYI: " msg)
150 #ifdef _TARGET_AMD64_
152 #define NYI_AMD64(msg) NYIRAW("NYI_AMD64: " msg)
153 #define NYI_X86(msg) do { } while (0)
154 #define NYI_ARM(msg) do { } while (0)
155 #define NYI_ARM64(msg) do { } while (0)
157 #elif defined(_TARGET_X86_)
159 #define NYI_AMD64(msg) do { } while (0)
160 #define NYI_X86(msg) NYIRAW("NYI_X86: " msg)
161 #define NYI_ARM(msg) do { } while (0)
162 #define NYI_ARM64(msg) do { } while (0)
164 #elif defined(_TARGET_ARM_)
166 #define NYI_AMD64(msg) do { } while (0)
167 #define NYI_X86(msg) do { } while (0)
168 #define NYI_ARM(msg) NYIRAW("NYI_ARM: " msg)
169 #define NYI_ARM64(msg) do { } while (0)
171 #elif defined(_TARGET_ARM64_)
173 #define NYI_AMD64(msg) do { } while (0)
174 #define NYI_X86(msg) do { } while (0)
175 #define NYI_ARM(msg) do { } while (0)
176 #define NYI_ARM64(msg) NYIRAW("NYI_ARM64: " msg)
180 #error "Unknown platform, not x86, ARM, or AMD64?"
184 #else // NYI not available; make it an assert.
186 #define NYI(msg) assert(!msg)
187 #define NYI_AMD64(msg) do { } while (0)
188 #define NYI_ARM(msg) do { } while (0)
189 #define NYI_ARM64(msg) do { } while (0)
191 #endif // NYI not available
193 #if !defined(_TARGET_X86_) && !defined(FEATURE_STACK_FP_X87)
195 #define NYI_FLAT_FP_X87(msg) NYI(msg)
196 #define NYI_FLAT_FP_X87_NC(msg) NYI(msg)
200 #define NYI_FLAT_FP_X87(msg) do { } while (0)
201 #define NYI_FLAT_FP_X87_NC(msg) do { } while (0)
203 #endif // !_TARGET_X86_ && !FEATURE_STACK_FP_X87
207 #if defined(_HOST_X86_) && !defined(FEATURE_PAL)
209 // While debugging in an Debugger, the "int 3" will cause the program to break
210 // Outside, the exception handler will just filter out the "int 3".
212 #define BreakIfDebuggerPresent() \
219 __except (EXCEPTION_EXECUTE_HANDLER) \
225 #define BreakIfDebuggerPresent() \
228 if (IsDebuggerPresent()) \
234 DWORD getBreakOnBadCode();
237 // For narrowing numeric conversions, the following two methods ensure that the
238 // source value fits in the destination type, using either "assert" or
239 // "noway_assert" to validate the conversion. Obviously, each returns the source value as
240 // the destination type.
242 // (There is an argument that these should be macros, to let the preprocessor capture
243 // a more useful file/line for the error message. But then we have to use comma expressions
244 // so that these can be used in expressions, etc., which is ugly. So I propose we rely on
245 // getting stack traces in other ways.)
246 template <typename Dst, typename Src>
247 inline Dst SafeCvtAssert(Src val)
249 assert(FitsIn<Dst>(val));
250 return static_cast<Dst>(val);
253 template <typename Dst, typename Src>
254 inline Dst SafeCvtNowayAssert(Src val)
256 noway_assert(FitsIn<Dst>(val));
257 return static_cast<Dst>(val);