kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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