decl.c (5537B)
1 /* DeclTable โ C declaration semantics above the public CG API. 2 * 3 * Maps DeclId โ Decl record. Allocates a KitCgSym for any non-typedef, 4 * non-auto/register decl with linkage. 5 * 6 * Identifier *lookup* is not handled here โ that lives on the parser's 7 * scope stack so block scopes and shadowing fall out naturally. DeclTable 8 * is just the C-language layer above CG: storage class, linkage, 9 * static-locals, tentative defs, and global initializers. 10 * 11 * v1 surface is intentionally minimal: just enough for the spine corpus 12 * (functions; ints; static locals) plus the hooks DESIGN.md ยง5.3.1 13 * commits to. Tentative-definition coalescing, COMDAT, and aliases are 14 * stubs at the API edge; their full semantics arrive with the multi-TU 15 * corpus. */ 16 17 #include "decl/decl.h" 18 19 #include <string.h> 20 21 struct DeclTable { 22 Compiler* c; 23 Pool* pool; 24 KitCg* cg; 25 Decl* slots; /* index 0 reserved as DECL_NONE */ 26 u32 nslots; 27 u32 cap; 28 }; 29 30 #define DECL_INITIAL_CAP 16u 31 32 static void decls_grow(DeclTable* t, u32 want) { 33 Heap* h = kit_compiler_context(t->c)->heap; 34 u32 cap = t->cap; 35 Decl* nb; 36 if (cap >= want) return; 37 while (cap < want) cap = cap ? cap * 2u : DECL_INITIAL_CAP; 38 nb = (Decl*)h->alloc(h, sizeof(Decl) * cap, _Alignof(Decl)); 39 if (t->slots) { 40 memcpy(nb, t->slots, sizeof(Decl) * t->nslots); 41 h->free(h, t->slots, sizeof(Decl) * t->cap); 42 } 43 t->slots = nb; 44 t->cap = cap; 45 } 46 47 DeclTable* decl_new(Compiler* c, Pool* pool, KitCg* cg) { 48 Heap* h = kit_compiler_context(c)->heap; 49 DeclTable* t = 50 (DeclTable*)h->alloc(h, sizeof(DeclTable), _Alignof(DeclTable)); 51 memset(t, 0, sizeof *t); 52 t->c = c; 53 t->pool = pool; 54 t->cg = cg; 55 decls_grow(t, 1); 56 memset(&t->slots[0], 0, sizeof(Decl)); 57 t->nslots = 1; 58 return t; 59 } 60 61 void decl_free(DeclTable* t) { 62 Heap* h; 63 if (!t) return; 64 h = kit_compiler_context(t->c)->heap; 65 if (t->slots) h->free(h, t->slots, sizeof(Decl) * t->cap); 66 h->free(h, t, sizeof(*t)); 67 } 68 69 static KitCgSymbolAttrs decl_sym_attrs(const Decl* d) { 70 KitCgSymbolAttrs a; 71 memset(&a, 0, sizeof a); 72 a.bind = (d->linkage == DL_EXTERNAL) ? KIT_SB_GLOBAL : KIT_SB_LOCAL; 73 if (d->flags & DF_WEAK) a.bind = KIT_SB_WEAK; 74 a.visibility = (KitCgVisibility)d->visibility; 75 if (d->flags & DF_USED) a.flags |= KIT_CG_SYM_USED; 76 return a; 77 } 78 79 static KitCgInlinePolicy decl_inline_policy(const Decl* d) { 80 if (d->flags & DF_NOINLINE) return KIT_CG_INLINE_NEVER; 81 if (d->flags & DF_ALWAYS_INLINE) return KIT_CG_INLINE_ALWAYS; 82 if (d->flags & DF_INLINE) return KIT_CG_INLINE_HINT; 83 return KIT_CG_INLINE_DEFAULT; 84 } 85 86 /* Build the public CG declaration for an already-validated Decl and emit it. 87 * Returns the resulting KitCgSym. Emission is idempotent for a name that 88 * already has a symbol: kit_cg_decl reuses the existing symbol and only 89 * refreshes attributes (e.g. promoting a strong global to weak). */ 90 static ObjSymId decl_emit_cg_sym(DeclTable* t, const Decl* slot) { 91 KitCgDecl decl; 92 memset(&decl, 0, sizeof decl); 93 decl.kind = (slot->type && slot->type->kind == TY_FUNC) ? KIT_CG_DECL_FUNC 94 : KIT_CG_DECL_OBJECT; 95 decl.display_name = slot->name; 96 decl.linkage_name = kit_cg_c_linkage_name( 97 t->c, slot->asm_name ? slot->asm_name : slot->name); 98 decl.type = type_cg_id_in_pool(t->c, t->pool, slot->type); 99 decl.sym = decl_sym_attrs(slot); 100 if (decl.kind == KIT_CG_DECL_FUNC) { 101 if (slot->flags & DF_NORETURN) decl.as.func.flags |= KIT_CG_FUNC_NORETURN; 102 decl.as.func.inline_policy = decl_inline_policy(slot); 103 decl.as.func.section = slot->section_id; 104 decl.as.func.wasm_import_module = slot->wasm_import_module; 105 decl.as.func.wasm_import_name = slot->wasm_import_name; 106 } else { 107 if (slot->flags & DF_THREAD) decl.as.object.flags |= KIT_CG_OBJ_TLS; 108 decl.as.object.section = slot->section_id; 109 decl.as.object.align = slot->align; 110 } 111 return kit_cg_decl(t->cg, decl); 112 } 113 114 DeclId decl_declare(DeclTable* t, const Decl* in) { 115 DeclId id; 116 Decl* slot; 117 decls_grow(t, t->nslots + 1); 118 id = (DeclId)t->nslots++; 119 slot = &t->slots[id]; 120 *slot = *in; 121 slot->id = id; 122 if (slot->obj_sym == OBJ_SYM_NONE && slot->name && 123 slot->storage != DS_TYPEDEF && slot->storage != DS_AUTO && 124 slot->storage != DS_REGISTER) { 125 if (slot->flags & DF_WEAK) { 126 if (slot->linkage != DL_EXTERNAL) 127 compiler_panic(t->c, slot->loc, 128 "weak attribute requires external linkage"); 129 } 130 slot->obj_sym = decl_emit_cg_sym(t, slot); 131 } 132 return id; 133 } 134 135 void decl_apply_redecl_flags(DeclTable* t, DeclId id, u32 new_flags) { 136 Decl* slot; 137 if (id == DECL_NONE || id >= t->nslots) return; 138 slot = &t->slots[id]; 139 /* C lets the `weak` attribute appear on any declaration; if a later 140 * redeclaration or the definition introduces it, the already-emitted symbol 141 * must become weak too. Other redeclaration-merge flags don't affect the 142 * emitted symbol, so weak is all we re-apply here. */ 143 if (!(new_flags & DF_WEAK) || (slot->flags & DF_WEAK)) return; 144 if (slot->linkage != DL_EXTERNAL) 145 compiler_panic(t->c, slot->loc, "weak attribute requires external linkage"); 146 slot->flags |= DF_WEAK; 147 if (slot->obj_sym != OBJ_SYM_NONE) decl_emit_cg_sym(t, slot); 148 } 149 150 const Decl* decl_get(const DeclTable* t, DeclId id) { 151 if (!t || id == DECL_NONE || id >= t->nslots) return NULL; 152 return &t->slots[id]; 153 } 154 155 ObjSymId decl_obj_sym(const DeclTable* t, DeclId id) { 156 const Decl* d = decl_get(t, id); 157 return d ? d->obj_sym : OBJ_SYM_NONE; 158 }