| 1 | /* @title: Assertions */ |
| 2 | #include <compiler.h> |
| 3 | #include <console/panic.h> |
| 4 | |
| 5 | /* |
| 6 | * Notes on kassert naming: |
| 7 | * |
| 8 | * no suffix - always fires, unhookable "the big panic" |
| 9 | * _debug - fires on DEBUG_ASSERT, hookable "panic for debugging" |
| 10 | * _oops - always fires, hookable "small invariant broken" |
| 11 | * |
| 12 | */ |
| 13 | |
| 14 | #define _kassert_pick(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, NAME, ...) \ |
| 15 | NAME |
| 16 | |
| 17 | #define _kassert_1(prefix, x) \ |
| 18 | do { \ |
| 19 | if (unlikely(!(x))) { \ |
| 20 | panic(prefix "Assertion \"" #x "\" failed"); \ |
| 21 | __builtin_unreachable(); \ |
| 22 | } \ |
| 23 | } while (0) |
| 24 | |
| 25 | #define _kassert_n(prefix, x, fmt, ...) \ |
| 26 | do { \ |
| 27 | if (unlikely(!(x))) { \ |
| 28 | panic(prefix "Assertion \"" #x "\" failed with message: " fmt, \ |
| 29 | ##__VA_ARGS__); \ |
| 30 | __builtin_unreachable(); \ |
| 31 | } \ |
| 32 | } while (0) |
| 33 | |
| 34 | #define _kassert_oops_1(prefix, x) \ |
| 35 | do { \ |
| 36 | if (unlikely(!(x))) { \ |
| 37 | panic(prefix "Oops, assertion \"" #x "\" failed"); \ |
| 38 | __builtin_unreachable(); \ |
| 39 | } \ |
| 40 | } while (0) |
| 41 | |
| 42 | #define _kassert_oops_n(prefix, x, fmt, ...) \ |
| 43 | do { \ |
| 44 | if (unlikely(!(x))) { \ |
| 45 | panic(prefix "Oops, assertion \"" #x \ |
| 46 | "\" failed with message: " fmt, \ |
| 47 | ##__VA_ARGS__); \ |
| 48 | __builtin_unreachable(); \ |
| 49 | } \ |
| 50 | } while (0) |
| 51 | |
| 52 | #define _kassert_debug_1(prefix, x) \ |
| 53 | do { \ |
| 54 | if (unlikely(!(x))) { \ |
| 55 | panic(prefix "Debug assertion \"" #x "\" failed"); \ |
| 56 | __builtin_unreachable(); \ |
| 57 | } \ |
| 58 | } while (0) |
| 59 | |
| 60 | #define _kassert_debug_n(prefix, x, fmt, ...) \ |
| 61 | do { \ |
| 62 | if (unlikely(!(x))) { \ |
| 63 | panic(prefix "Debug assertion \"" #x \ |
| 64 | "\" failed with message: " fmt, \ |
| 65 | ##__VA_ARGS__); \ |
| 66 | __builtin_unreachable(); \ |
| 67 | } \ |
| 68 | } while (0) |
| 69 | |
| 70 | #define _kassert_dispatch(name, prefix, ...) \ |
| 71 | _kassert_pick(__VA_ARGS__, name##_n, name##_n, name##_n, name##_n, \ |
| 72 | name##_n, name##_n, name##_n, name##_n, name##_n, name##_n, \ |
| 73 | name##_1)(prefix, __VA_ARGS__) |
| 74 | |
| 75 | #define _kassert_fail(prefix, ...) \ |
| 76 | do { \ |
| 77 | panic(prefix __VA_ARGS__); \ |
| 78 | __builtin_unreachable(); \ |
| 79 | } while (0) |
| 80 | |
| 81 | #define kassert(...) _kassert_dispatch(_kassert, "", __VA_ARGS__) |
| 82 | |
| 83 | #define kassert_unreachable(...) _kassert_fail("unreachable! ", ##__VA_ARGS__) |
| 84 | #define kassert_unimplemented(...) \ |
| 85 | _kassert_fail("unimplemented! ", ##__VA_ARGS__) |
| 86 | #define kassert_todo(...) _kassert_fail("TODO: ", ##__VA_ARGS__) |
| 87 | |
| 88 | #ifdef DEBUG_ASSERT |
| 89 | |
| 90 | #define kassert_debug(...) \ |
| 91 | _kassert_dispatch(_kassert_debug, "DEBUG ", __VA_ARGS__) |
| 92 | |
| 93 | #define kassert_debug_unreachable(...) \ |
| 94 | _kassert_fail("DEBUG unreachable! ", ##__VA_ARGS__) |
| 95 | #define kassert_debug_unimplemented(...) \ |
| 96 | _kassert_fail("DEBUG unimplemented! ", ##__VA_ARGS__) |
| 97 | #define kassert_debug_todo(...) _kassert_fail("DEBUG TODO: ", ##__VA_ARGS__) |
| 98 | |
| 99 | #else |
| 100 | |
| 101 | #define kassert_debug(...) ((void) 0) |
| 102 | #define kassert_debug_unreachable(...) ((void) 0) |
| 103 | #define kassert_debug_unimplemented(...) ((void) 0) |
| 104 | #define kassert_debug_todo(...) ((void) 0) |
| 105 | |
| 106 | #endif |
| 107 | |