DFG_ASSERT should allow stuffing registers before trapping.
[WebKit-https.git] / Source / WTF / wtf / Assertions.h
1 /*
2  * Copyright (C) 2003, 2006, 2007, 2013 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef WTF_Assertions_h
27 #define WTF_Assertions_h
28
29 #include <wtf/Platform.h>
30
31 /*
32    no namespaces because this file has to be includable from C and Objective-C
33
34    Note, this file uses many GCC extensions, but it should be compatible with
35    C, Objective C, C++, and Objective C++.
36
37    For non-debug builds, everything is disabled by default except for "always
38    on" logging. Defining any of the symbols explicitly prevents this from
39    having any effect.
40 */
41
42 #undef __STDC_FORMAT_MACROS
43 #define __STDC_FORMAT_MACROS
44 #include <inttypes.h>
45 #include <stdarg.h>
46 #include <stdbool.h>
47 #include <stddef.h>
48 #include <wtf/ExportMacros.h>
49
50 #if USE(OS_LOG)
51 #include <os/log.h>
52 #endif
53
54 #ifdef NDEBUG
55 /* Disable ASSERT* macros in release mode. */
56 #define ASSERTIONS_DISABLED_DEFAULT 1
57 #else
58 #define ASSERTIONS_DISABLED_DEFAULT 0
59 #endif
60
61 #ifndef BACKTRACE_DISABLED
62 #define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT
63 #endif
64
65 #ifndef ASSERT_DISABLED
66 #define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
67 #endif
68
69 #ifndef ASSERT_MSG_DISABLED
70 #define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT
71 #endif
72
73 #ifndef ASSERT_ARG_DISABLED
74 #define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
75 #endif
76
77 #ifndef FATAL_DISABLED
78 #define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
79 #endif
80
81 #ifndef ERROR_DISABLED
82 #define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
83 #endif
84
85 #ifndef LOG_DISABLED
86 #define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
87 #endif
88
89 #ifndef RELEASE_LOG_DISABLED
90 #define RELEASE_LOG_DISABLED !(USE(OS_LOG))
91 #endif
92
93 #if COMPILER(GCC_OR_CLANG)
94 #define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__
95 #else
96 #define WTF_PRETTY_FUNCTION __FUNCTION__
97 #endif
98
99 #if COMPILER(MINGW)
100 /* By default MinGW emits warnings when C99 format attributes are used, even if __USE_MINGW_ANSI_STDIO is defined */
101 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(gnu_printf, formatStringArgument, extraArguments)))
102 #elif COMPILER(GCC_OR_CLANG) && !defined(__OBJC__)
103 /* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
104    emits a warning when %@ is used in the format string.  Until <rdar://problem/5195437> is resolved we can't include
105    the attribute when being used from Objective-C code in case it decides to use %@. */
106 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
107 #else
108 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments)
109 #endif
110
111 #if PLATFORM(IOS)
112 /* For a project that uses WTF but has no config.h, we need to explicitly set the export defines here. */
113 #ifndef WTF_EXPORT_PRIVATE
114 #define WTF_EXPORT_PRIVATE
115 #endif
116 #endif // PLATFORM(IOS)
117
118 /* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */
119
120 #ifdef __cplusplus
121 extern "C" {
122 #endif
123
124 /* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter.
125
126    Use CRASH() in response to known, unrecoverable errors like out-of-memory.
127    Macro is enabled in both debug and release mode.
128    To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds.
129
130    Signals are ignored by the crash reporter on OS X so we must do better.
131 */
132 #if COMPILER(GCC_OR_CLANG) || COMPILER(MSVC)
133 #define NO_RETURN_DUE_TO_CRASH NO_RETURN
134 #else
135 #define NO_RETURN_DUE_TO_CRASH
136 #endif
137
138 typedef enum { WTFLogChannelOff, WTFLogChannelOn, WTFLogChannelOnWithAccumulation } WTFLogChannelState;
139
140 typedef struct {
141     WTFLogChannelState state;
142     const char* name;
143 #if !RELEASE_LOG_DISABLED
144     const char* subsystem;
145     __unsafe_unretained os_log_t osLogChannel;
146 #endif
147 } WTFLogChannel;
148
149 #define LOG_CHANNEL(name) JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name)
150 #define LOG_CHANNEL_ADDRESS(name) &LOG_CHANNEL(name),
151 #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
152 #define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel
153
154 #define LOG_CHANNEL_WEBKIT_SUBSYSTEM "com.apple.WebKit"
155
156 #define DECLARE_LOG_CHANNEL(name) \
157     extern WTFLogChannel LOG_CHANNEL(name);
158
159 #if !defined(DEFINE_LOG_CHANNEL)
160 #if RELEASE_LOG_DISABLED
161 #define DEFINE_LOG_CHANNEL(name, subsystem) \
162     WTFLogChannel LOG_CHANNEL(name) = { WTFLogChannelOff, #name };
163 #else
164 #define DEFINE_LOG_CHANNEL(name, subsystem) \
165     WTFLogChannel LOG_CHANNEL(name) = { WTFLogChannelOff, #name, subsystem, OS_LOG_DEFAULT };
166 #endif
167 #endif
168
169 WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
170 WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
171 WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion);
172 WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
173 WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
174 WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
175 WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
176 WTF_EXPORT_PRIVATE void WTFLogAlwaysV(const char* format, va_list);
177 WTF_EXPORT_PRIVATE void WTFLogAlways(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
178 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFLogAlwaysAndCrash(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
179 WTF_EXPORT_PRIVATE WTFLogChannel* WTFLogChannelByName(WTFLogChannel*[], size_t count, const char*);
180 WTF_EXPORT_PRIVATE void WTFInitializeLogChannelStatesFromString(WTFLogChannel*[], size_t count, const char*);
181
182 WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size);
183 WTF_EXPORT_PRIVATE void WTFReportBacktrace();
184 WTF_EXPORT_PRIVATE void WTFPrintBacktrace(void** stack, int size);
185
186 typedef void (*WTFCrashHookFunction)();
187 WTF_EXPORT_PRIVATE void WTFSetCrashHook(WTFCrashHookFunction);
188 WTF_EXPORT_PRIVATE void WTFInstallReportBacktraceOnCrashHook();
189
190 WTF_EXPORT_PRIVATE bool WTFIsDebuggerAttached();
191
192 #if CPU(X86_64) || CPU(X86)
193 #define WTFBreakpointTrap()  __asm__ volatile ("int3")
194 #elif CPU(ARM_THUMB2)
195 #define WTFBreakpointTrap()  __asm__ volatile ("bkpt #0")
196 #elif CPU(ARM64)
197 #define WTFBreakpointTrap()  __asm__ volatile ("brk #0")
198 #else
199 #define WTFBreakpointTrap() WTFCrash() // Not implemented.
200 #endif
201
202 #ifndef CRASH
203
204 #if defined(NDEBUG) && OS(DARWIN)
205 // Crash with a SIGTRAP i.e EXC_BREAKPOINT.
206 // We are not using __builtin_trap because it is only guaranteed to abort, but not necessarily
207 // trigger a SIGTRAP. Instead, we use inline asm to ensure that we trigger the SIGTRAP.
208 #define CRASH() do { \
209     WTFBreakpointTrap(); \
210     __builtin_unreachable(); \
211 } while (0)
212 #else
213 #define CRASH() WTFCrash()
214 #endif
215
216 #endif // !defined(CRASH)
217
218 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrash();
219
220 #ifndef CRASH_WITH_SECURITY_IMPLICATION
221 #define CRASH_WITH_SECURITY_IMPLICATION() WTFCrashWithSecurityImplication()
222 #endif
223
224 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrashWithSecurityImplication();
225
226 #ifdef __cplusplus
227 }
228 #endif
229
230 /* BACKTRACE
231
232   Print a backtrace to the same location as ASSERT messages.
233 */
234
235 #if BACKTRACE_DISABLED
236
237 #define BACKTRACE() ((void)0)
238
239 #else
240
241 #define BACKTRACE() do { \
242     WTFReportBacktrace(); \
243 } while(false)
244
245 #endif
246
247 /* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
248
249   These macros are compiled out of release builds.
250   Expressions inside them are evaluated in debug builds only.
251 */
252
253 #if OS(WINDOWS)
254 /* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
255 #undef ASSERT
256 #endif
257
258 #if ASSERT_DISABLED
259
260 #define ASSERT(assertion) ((void)0)
261 #define ASSERT_AT(assertion, file, line, function) ((void)0)
262 #define ASSERT_NOT_REACHED() ((void)0)
263 #define ASSERT_IMPLIES(condition, assertion) ((void)0)
264 #define NO_RETURN_DUE_TO_ASSERT
265
266 #define ASSERT_UNUSED(variable, assertion) ((void)variable)
267
268 #if ENABLE(SECURITY_ASSERTIONS)
269 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
270     (!(assertion) ? \
271         (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
272          CRASH_WITH_SECURITY_IMPLICATION()) : \
273         (void)0)
274
275 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
276 #else
277 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) ((void)0)
278 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 1
279 #endif
280
281 #else
282
283 #define ASSERT(assertion) do { \
284     if (!(assertion)) { \
285         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
286         CRASH(); \
287     } \
288 } while (0)
289
290 #define ASSERT_AT(assertion, file, line, function) do { \
291     if (!(assertion)) { \
292         WTFReportAssertionFailure(file, line, function, #assertion); \
293         CRASH(); \
294     } \
295 } while (0)
296
297 #define ASSERT_NOT_REACHED() do { \
298     WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
299     CRASH(); \
300 } while (0)
301
302 #define ASSERT_IMPLIES(condition, assertion) do { \
303     if ((condition) && !(assertion)) { \
304         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #condition " => " #assertion); \
305         CRASH(); \
306     } \
307 } while (0)
308
309 #define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
310
311 #define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH
312
313 /* ASSERT_WITH_SECURITY_IMPLICATION
314  
315    Failure of this assertion indicates a possible security vulnerability.
316    Class of vulnerabilities that it tests include bad casts, out of bounds
317    accesses, use-after-frees, etc. Please file a bug using the security
318    template - https://bugs.webkit.org/enter_bug.cgi?product=Security.
319  
320 */
321 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
322     (!(assertion) ? \
323         (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
324          CRASH_WITH_SECURITY_IMPLICATION()) : \
325         (void)0)
326 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
327 #endif
328
329 /* ASSERT_WITH_MESSAGE */
330
331 #if ASSERT_MSG_DISABLED
332 #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
333 #else
334 #define ASSERT_WITH_MESSAGE(assertion, ...) do { \
335     if (!(assertion)) { \
336         WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
337         CRASH(); \
338     } \
339 } while (0)
340 #endif
341
342 /* ASSERT_WITH_MESSAGE_UNUSED */
343
344 #if ASSERT_MSG_DISABLED
345 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable)
346 #else
347 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do { \
348     if (!(assertion)) { \
349         WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
350         CRASH(); \
351     } \
352 } while (0)
353 #endif
354                         
355                         
356 /* ASSERT_ARG */
357
358 #if ASSERT_ARG_DISABLED
359
360 #define ASSERT_ARG(argName, assertion) ((void)0)
361
362 #else
363
364 #define ASSERT_ARG(argName, assertion) do { \
365     if (!(assertion)) { \
366         WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \
367         CRASH(); \
368     } \
369 } while (0)
370
371 #endif
372
373 /* COMPILE_ASSERT */
374 #ifndef COMPILE_ASSERT
375 #if COMPILER_SUPPORTS(C_STATIC_ASSERT)
376 /* Unlike static_assert below, this also works in plain C code. */
377 #define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name)
378 #else
379 #define COMPILE_ASSERT(exp, name) static_assert((exp), #name)
380 #endif
381 #endif
382
383 /* FATAL */
384
385 #if FATAL_DISABLED
386 #define FATAL(...) ((void)0)
387 #else
388 #define FATAL(...) do { \
389     WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
390     CRASH(); \
391 } while (0)
392 #endif
393
394 /* LOG_ERROR */
395
396 #if ERROR_DISABLED
397 #define LOG_ERROR(...) ((void)0)
398 #else
399 #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
400 #endif
401
402 /* LOG */
403
404 #if LOG_DISABLED
405 #define LOG(channel, ...) ((void)0)
406 #else
407 #define LOG(channel, ...) WTFLog(&LOG_CHANNEL(channel), __VA_ARGS__)
408 #endif
409
410 /* LOG_VERBOSE */
411
412 #if LOG_DISABLED
413 #define LOG_VERBOSE(channel, ...) ((void)0)
414 #else
415 #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &LOG_CHANNEL(channel), __VA_ARGS__)
416 #endif
417
418 /* RELEASE_LOG */
419
420 #if RELEASE_LOG_DISABLED
421 #define RELEASE_LOG(      channel, format, ...) ((void)0)
422 #define RELEASE_LOG_ERROR(channel, format, ...) LOG_ERROR(format, ##__VA_ARGS__)
423
424 #define RELEASE_LOG_IF(      isAllowed, channel, format, ...) ((void)0)
425 #define RELEASE_LOG_ERROR_IF(isAllowed, channel, format, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, format, ##__VA_ARGS__); } while (0)
426 #else
427 #define RELEASE_LOG(      channel, format, ...) os_log(      LOG_CHANNEL(channel).osLogChannel, format, ##__VA_ARGS__)
428 #define RELEASE_LOG_ERROR(channel, format, ...) os_log_error(LOG_CHANNEL(channel).osLogChannel, format, ##__VA_ARGS__)
429
430 #define RELEASE_LOG_IF(      isAllowed, channel, format, ...) do { if (isAllowed) RELEASE_LOG(      channel, format, ##__VA_ARGS__); } while (0)
431 #define RELEASE_LOG_ERROR_IF(isAllowed, channel, format, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, format, ##__VA_ARGS__); } while (0)
432 #endif
433
434
435 /* RELEASE_ASSERT */
436
437 #if ASSERT_DISABLED
438 #define RELEASE_ASSERT(assertion) do { \
439     if (UNLIKELY(!(assertion))) \
440         CRASH(); \
441 } while (0)
442 #define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) RELEASE_ASSERT(assertion)
443 #define RELEASE_ASSERT_NOT_REACHED() CRASH()
444 #else
445 #define RELEASE_ASSERT(assertion) ASSERT(assertion)
446 #define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__)
447 #define RELEASE_ASSERT_NOT_REACHED() ASSERT_NOT_REACHED()
448 #endif
449
450 /* UNREACHABLE_FOR_PLATFORM */
451
452 #if COMPILER(CLANG)
453 // This would be a macro except that its use of #pragma works best around
454 // a function. Hence it uses macro naming convention.
455 #pragma clang diagnostic push
456 #pragma clang diagnostic ignored "-Wmissing-noreturn"
457 static inline void UNREACHABLE_FOR_PLATFORM()
458 {
459     // This *MUST* be a release assert. We use it in places where it's better to crash than to keep
460     // going.
461     RELEASE_ASSERT_NOT_REACHED();
462 }
463 #pragma clang diagnostic pop
464 #else
465 #define UNREACHABLE_FOR_PLATFORM() RELEASE_ASSERT_NOT_REACHED()
466 #endif
467
468 #ifndef INLINE_CRASH_WITH_SECURITY_IMPLICATION
469 // This is useful if you are going to stuff data into registers before crashing. Like the CRASH_WITH_INFO functions below...
470 #define INLINE_CRASH_WITH_SECURITY_IMPLICATION() CRASH()
471 #endif
472
473 #ifdef __cplusplus
474
475 #if OS(DARWIN) && (CPU(X64_64) || CPU(ARM64))
476 #if CPU(X86_64)
477 #define STUFF_REGISTER_FOR_CRASH(reg, value) \
478     static_assert(std::is_integral<decltype(value)>::value, "STUFF_REGISTERS_FOR_CRASH expects an integral input"); \
479     __asm__ volatile ("movq %0, %%" reg : : "r" (static_cast<uint64_t>(value)) : reg)
480
481 // This ordering was chosen to be consistant with JSC's JIT asserts. We probably shouldn't change this ordering
482 // since it would make tooling crash reports much harder. If, for whatever reason, we decide to change the ordering
483 // here we should update the abortWithReason functions.
484 #define STUFF_FOR_CRASH_REGISTER1 "r11"
485 #define STUFF_FOR_CRASH_REGISTER2 "r10"
486 #define STUFF_FOR_CRASH_REGISTER3 "r9"
487 #define STUFF_FOR_CRASH_REGISTER4 "r8"
488 #define STUFF_FOR_CRASH_REGISTER5 "r15"
489
490 #elif CPU(ARM64) // CPU(X86_64)
491 #define STUFF_REGISTER_FOR_CRASH(reg, value) \
492     static_assert(std::is_integral<decltype(value)>::value, "STUFF_REGISTERS_FOR_CRASH expects an integral input"); \
493     __asm__ volatile ("mov " reg ", %0" : : "r" (static_cast<uint64_t>(value)) : reg)
494
495 // See comment above on the ordering.
496 #define STUFF_FOR_CRASH_REGISTER1 "x16"
497 #define STUFF_FOR_CRASH_REGISTER2 "x17"
498 #define STUFF_FOR_CRASH_REGISTER3 "x18"
499 #define STUFF_FOR_CRASH_REGISTER4 "x19"
500 #define STUFF_FOR_CRASH_REGISTER5 "x20"
501
502 #endif // CPU(ARM64)
503
504 template<typename Reason, typename A, typename B, typename C, typename D>
505 ALWAYS_INLINE NO_RETURN_DUE_TO_CRASH void CRASH_WITH_INFO(Reason reason, A misc1, B misc2, C misc3, D misc4)
506 {
507     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
508     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
509     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER3, misc2);
510     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER4, misc3);
511     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER5, misc4);
512     INLINE_CRASH_WITH_SECURITY_IMPLICATION();
513 }
514
515 template<typename Reason, typename A, typename B, typename C>
516 ALWAYS_INLINE NO_RETURN_DUE_TO_CRASH void CRASH_WITH_INFO(Reason reason, A misc1, B misc2, C misc3)
517 {
518     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
519     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
520     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER3, misc2);
521     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER4, misc3);
522     INLINE_CRASH_WITH_SECURITY_IMPLICATION();
523 }
524
525 template<typename Reason, typename A, typename B>
526 ALWAYS_INLINE NO_RETURN_DUE_TO_CRASH void CRASH_WITH_INFO(Reason reason, A misc1, B misc2)
527 {
528     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
529     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
530     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER3, misc2);
531     INLINE_CRASH_WITH_SECURITY_IMPLICATION();
532 }
533
534 template<typename Reason, typename A>
535 ALWAYS_INLINE NO_RETURN_DUE_TO_CRASH void CRASH_WITH_INFO(Reason reason, A misc1)
536 {
537     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
538     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER2, misc1);
539     INLINE_CRASH_WITH_SECURITY_IMPLICATION();
540 }
541
542 template<typename Reason>
543 ALWAYS_INLINE NO_RETURN_DUE_TO_CRASH void CRASH_WITH_INFO(Reason reason)
544 {
545     STUFF_REGISTER_FOR_CRASH(STUFF_FOR_CRASH_REGISTER1, reason);
546     INLINE_CRASH_WITH_SECURITY_IMPLICATION();
547 }
548
549 ALWAYS_INLINE NO_RETURN_DUE_TO_CRASH void CRASH_WITH_INFO()
550 {
551     INLINE_CRASH_WITH_SECURITY_IMPLICATION();
552 }
553
554 #else // OS(DARWIN) && (CPU(X64_64) || CPU(ARM64))
555
556 template<typename... Types>
557 ALWAYS_INLINE NO_RETURN_DUE_TO_CRASH void CRASH_WITH_INFO(Types...)
558 {
559     INLINE_CRASH_WITH_SECURITY_IMPLICATION();
560 }
561
562 #endif // OS(DARWIN) && (CPU(X64_64) || CPU(ARM64))
563
564 #endif // __cplusplus
565
566 #endif /* WTF_Assertions_h */