cpp_support.h (4919B)
1 #ifndef KIT_LANG_CPP_SUPPORT_H 2 #define KIT_LANG_CPP_SUPPORT_H 3 4 /* Shared substrate for the lexer and preprocessor: width-typed integer 5 * aliases, the Compiler/Heap/Writer/Sym/SrcLoc typedefs, the Pool 6 * abstraction over a per-frontend arena, arena allocation macros, and 7 * the panic helpers. Used by lang/cpp/ directly and re-exported by 8 * lang/c/c_support.h for the C frontend. */ 9 10 #include <kit/frontend.h> 11 #include <kit/support/hashmap.h> 12 #include <stdarg.h> 13 #include <stddef.h> 14 #include <stdint.h> 15 #include <string.h> 16 17 typedef int8_t i8; 18 typedef int16_t i16; 19 typedef int32_t i32; 20 typedef int64_t i64; 21 typedef uint8_t u8; 22 typedef uint16_t u16; 23 typedef uint32_t u32; 24 typedef uint64_t u64; 25 26 typedef KitCompiler Compiler; 27 typedef KitHeap Heap; 28 typedef KitWriter Writer; 29 typedef KitSym Sym; 30 typedef KitSrcLoc SrcLoc; 31 typedef u32 BytesId; 32 33 typedef struct Pool { 34 Compiler* c; 35 KitArena* arena; 36 /* A KitHeap facade over `arena`: alloc/realloc route to the arena (realloc 37 * copies into a fresh block), free is a no-op. Lets arena-lifetime hash maps 38 * (KIT_HASHMAP_DEFINE, which is otherwise heap-backed) avoid any teardown — 39 * resize orphans the old table into the arena, bounded by the final size and 40 * reclaimed wholesale at pool teardown. Shared by the parser scope indexes, 41 * the type-system record memo, and the ABI info cache. */ 42 KitHeap arena_heap; 43 void* type_cache; /* opaque slot owned by the C type system; unused by cpp */ 44 void* abi_cache; /* opaque slot owned by the C ABI layer; unused by cpp */ 45 } Pool; 46 47 static inline void* kit_pool_heap_alloc(KitHeap* h, size_t n, size_t align) { 48 return kit_arena_alloc((KitArena*)h->user, n, align); 49 } 50 static inline void* kit_pool_heap_realloc(KitHeap* h, void* old, size_t old_n, 51 size_t new_n, size_t align) { 52 void* q = kit_arena_alloc((KitArena*)h->user, new_n, align); 53 if (q && old && old_n) memcpy(q, old, old_n < new_n ? old_n : new_n); 54 return q; 55 } 56 static inline void kit_pool_heap_free(KitHeap* h, void* p, size_t n) { 57 (void)h; 58 (void)p; 59 (void)n; 60 } 61 62 /* C data model for frontend-visible scalar spelling. kit currently uses LP64 63 * for 64-bit non-Windows targets, LLP64 for 64-bit Windows targets, and ILP32 64 * for 32-bit targets. The distinction is exactly sizeof(long): 8 for LP64, 65 * 4 for LLP64/ILP32 — a resolved data-model fact carried on the spec, so we 66 * read it instead of re-deriving from ptr_size + OS identity. */ 67 static inline int kit_target_uses_lp64(KitTargetSpec t) { 68 return t.long_size == 8; 69 } 70 71 static inline Pool* c_pool_new(Compiler* c) { 72 Heap* h = kit_compiler_context(c)->heap; 73 Pool* p = h ? (Pool*)h->alloc(h, sizeof(*p), _Alignof(Pool)) : NULL; 74 if (!p) return NULL; 75 p->c = c; 76 p->arena = NULL; 77 p->type_cache = NULL; 78 p->abi_cache = NULL; 79 if (kit_arena_new(h, 0, &p->arena) != KIT_OK || !p->arena) { 80 h->free(h, p, sizeof(*p)); 81 return NULL; 82 } 83 p->arena_heap.alloc = kit_pool_heap_alloc; 84 p->arena_heap.realloc = kit_pool_heap_realloc; 85 p->arena_heap.free = kit_pool_heap_free; 86 p->arena_heap.user = p->arena; 87 return p; 88 } 89 90 static inline void c_pool_free(Pool* p) { 91 Heap* h; 92 if (!p) return; 93 h = kit_compiler_context(p->c)->heap; 94 kit_arena_free(p->arena); 95 if (h) h->free(h, p, sizeof(*p)); 96 } 97 98 #define arena_alloc(a, size, align) kit_arena_alloc((a), (size), (align)) 99 #define arena_zalloc(a, size, align) kit_arena_zalloc((a), (size), (align)) 100 #define arena_strdup(a, s, len) kit_arena_strdup((a), (s), (len)) 101 #define arena_new(a, T) kit_arena_new_obj((a), T) 102 #define arena_znew(a, T) kit_arena_znew_obj((a), T) 103 #define arena_array(a, T, n) kit_arena_array((a), T, n) 104 #define arena_zarray(a, T, n) kit_arena_zarray((a), T, n) 105 106 _Noreturn static inline void compiler_panic(Compiler* c, SrcLoc loc, 107 const char* fmt, ...) { 108 va_list ap; 109 va_start(ap, fmt); 110 kit_frontend_vfatal(c, loc, fmt, ap); 111 } 112 113 _Noreturn static inline void compiler_panicv(Compiler* c, SrcLoc loc, 114 const char* fmt, va_list ap) { 115 kit_frontend_vfatal(c, loc, fmt, ap); 116 } 117 118 /* True when the C `long double` type is IEEE-754 binary128 (quad) on this 119 * target rather than an alias of `double`. RISC-V (LP64/LP64D) and 120 * non-Apple/non-Windows aarch64 follow the quad psABI; wasm32 matches 121 * clang/LLVM's wasm convention. x86 (80-bit x87, not modeled), Apple, and 122 * Windows alias long double to double. This is a resolved ABI fact 123 * (long_double_format) computed once in kit_target_new, so we read the 124 * spec field instead of re-deriving an arch/os ladder here. Centralized so 125 * the preprocessor's __LDBL_* / __SIZEOF_LONG_DOUBLE__ macros and the C type 126 * system's long-double -> CG-builtin mapping cannot drift apart. */ 127 static inline int kit_target_long_double_is_binary128(KitTargetSpec t) { 128 return t.long_double_format == KIT_LDBL_BINARY128; 129 } 130 131 #endif