core.c (5787B)
1 /* Compiler lifecycle, panic, and cleanup-stack machinery. */ 2 3 #include "core/core.h" 4 5 #include <stdarg.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #include "abi/abi.h" 10 #include "api/lang_registry.h" 11 #include "core/arena.h" 12 #include "core/diag.h" 13 #include "core/heap.h" 14 #include "core/pool.h" 15 16 #if defined(__GNUC__) || defined(__clang__) || defined(__kit__) 17 __attribute__((weak)) 18 #endif 19 void kit_debug_printf(const char* fmt, ...) { 20 (void)fmt; 21 } 22 23 #if defined(__GNUC__) || defined(__clang__) || defined(__kit__) 24 __attribute__((weak)) 25 #endif 26 const char* kit_debug_getenv(const char* name) { 27 (void)name; 28 return NULL; 29 } 30 31 /* Weak fallbacks for the tracing seam (kit/trace.h). libkit holds no trace 32 * state, so the library-side gate is always closed and the sink is a no-op; 33 * hosted binaries (driver/env) override both with the KIT_TRACE-driven 34 * implementation. */ 35 #if defined(__GNUC__) || defined(__clang__) || defined(__kit__) 36 __attribute__((weak)) 37 #endif 38 int kit_trace_enabled(const char* module, int level) { 39 (void)module; 40 (void)level; 41 return 0; 42 } 43 44 #if defined(__GNUC__) || defined(__clang__) || defined(__kit__) 45 __attribute__((weak)) 46 #endif 47 void kit_trace_emit(const char* module, int level, const char* file, int line, 48 const char* fmt, ...) { 49 (void)module; 50 (void)level; 51 (void)file; 52 (void)line; 53 (void)fmt; 54 } 55 56 /* Weak fallback for the <assert.h> failure hook (rt/include/assert.h). kit's 57 * own code uses compiler_panic, not C assert(), but vendored code compiled into 58 * libkit (the lz4 codecs) references __kit_assert_fail in non-NDEBUG builds. 59 * A hidden weak trap lets every libkit.a consumer -- the kit binary, the 60 * test harnesses that link the archive directly, a standalone embedder -- 61 * resolve it without pulling in the runtime. Hidden (the -fvisibility=hidden 62 * default, NOT visibility-default) keeps it off libkit's public export 63 * surface that scripts/lib_reloc_defined_prefixes.py guards. The freestanding 64 * runtime ships its own weak __kit_assert_fail (rt/lib/assert) for programs 65 * that link it. The contract is _Noreturn, so trap rather than return. */ 66 #if defined(__GNUC__) || defined(__clang__) || defined(__kit__) 67 __attribute__((weak)) 68 #endif 69 void __kit_assert_fail(const char* expr, const char* file, int line, 70 const char* func) { 71 (void)expr; 72 (void)file; 73 (void)line; 74 (void)func; 75 __builtin_trap(); 76 for (;;) { 77 } 78 } 79 80 SourceManager* source_new(Compiler*); 81 void source_free(SourceManager*); 82 83 struct CompilerCleanup { 84 void (*fn)(void*); 85 void* arg; 86 CompilerCleanup* prev; 87 }; 88 89 KitStatus compiler_init(Compiler* c, const KitTarget* target, 90 const KitContext* ctx) { 91 Heap* h = ctx->heap; 92 93 if (!c || !target || !ctx || !h) return KIT_INVALID; 94 memset(c, 0, sizeof(*c)); 95 c->ctx = ctx; 96 c->target_ref = target; 97 c->target = target->spec; 98 99 c->global = (Pool*)h->alloc(h, sizeof(Pool), _Alignof(Pool)); 100 if (!c->global) goto nomem; 101 pool_init(c->global, h); 102 103 c->tu = (Arena*)h->alloc(h, sizeof(Arena), _Alignof(Arena)); 104 if (!c->tu) goto nomem; 105 arena_init(c->tu, h, 0); 106 107 c->scratch = (Arena*)h->alloc(h, sizeof(Arena), _Alignof(Arena)); 108 if (!c->scratch) goto nomem; 109 arena_init(c->scratch, h, 0); 110 111 c->sources = source_new(c); 112 if (!c->sources) goto nomem; 113 114 c->abi = abi_new(c); 115 if (!c->abi) goto nomem; 116 117 c->cleanup = NULL; 118 119 lang_registry_init(c); 120 return KIT_OK; 121 122 nomem: 123 compiler_fini(c); 124 return KIT_NOMEM; 125 } 126 127 void compiler_fini(Compiler* c) { 128 Heap* h = c->ctx->heap; 129 130 compiler_run_cleanups(c); 131 132 if (c->cg_api_free) { 133 c->cg_api_free(c); 134 c->cg_api_free = NULL; 135 } 136 137 if (c->abi) { 138 abi_free(c->abi); 139 c->abi = NULL; 140 } 141 if (c->sources) source_free(c->sources); 142 if (c->scratch) { 143 arena_fini(c->scratch); 144 h->free(h, c->scratch, sizeof(Arena)); 145 } 146 if (c->tu) { 147 arena_fini(c->tu); 148 h->free(h, c->tu, sizeof(Arena)); 149 } 150 if (c->global) { 151 pool_fini(c->global); 152 h->free(h, c->global, sizeof(Pool)); 153 } 154 c->global = NULL; 155 c->tu = c->scratch = NULL; 156 c->sources = NULL; 157 } 158 159 CompilerCleanup* compiler_defer(Compiler* c, void (*fn)(void*), void* arg) { 160 CompilerCleanup* node; 161 node = (CompilerCleanup*)arena_alloc(c->scratch, sizeof(*node), 162 _Alignof(CompilerCleanup)); 163 if (!node) return NULL; 164 node->fn = fn; 165 node->arg = arg; 166 node->prev = c->cleanup; 167 c->cleanup = node; 168 return node; 169 } 170 171 void compiler_undefer(Compiler* c, CompilerCleanup* node) { 172 CompilerCleanup** link = &c->cleanup; 173 while (*link) { 174 if (*link == node) { 175 *link = node->prev; 176 return; 177 } 178 link = &(*link)->prev; 179 } 180 } 181 182 void compiler_run_cleanups(Compiler* c) { 183 while (c->cleanup) { 184 CompilerCleanup* node = c->cleanup; 185 c->cleanup = node->prev; 186 node->fn(node->arg); 187 } 188 } 189 190 void compiler_panic_push(Compiler* c, PanicFrame* frame) { 191 frame->prev = c->panic_frame; 192 c->panic_frame = frame; 193 } 194 195 void compiler_panic_pop(Compiler* c, PanicFrame* frame) { 196 PanicFrame** link; 197 if (!c || !frame) return; 198 if (c->panic_frame == frame) { 199 c->panic_frame = frame->prev; 200 frame->prev = NULL; 201 return; 202 } 203 link = &c->panic_frame; 204 while (*link) { 205 if (*link == frame) { 206 *link = frame->prev; 207 frame->prev = NULL; 208 return; 209 } 210 link = &(*link)->prev; 211 } 212 } 213 214 void compiler_panic(Compiler* c, SrcLoc loc, const char* fmt, ...) { 215 va_list ap; 216 va_start(ap, fmt); 217 compiler_panicv(c, loc, fmt, ap); 218 va_end(ap); 219 } 220 221 void compiler_panicv(Compiler* c, SrcLoc loc, const char* fmt, va_list ap) { 222 if (c->ctx && c->ctx->diag && c->ctx->diag->emit) { 223 c->ctx->diag->emit(c->ctx->diag, KIT_DIAG_FATAL, loc, fmt, ap); 224 } 225 if (c->panic_frame) longjmp(c->panic_frame->env, 1); 226 longjmp(c->panic, 1); 227 }