type.c (40739B)
1 /* C type construction. 2 * 3 * Types are interned per-Pool: a single `type_void(pool)` returns the same 4 * Type* on every call against the same pool, and structurally-equal calls 5 * to type_prim/type_ptr/type_func collapse to the same Type*. The cache is 6 * a small open structure stored through Pool.type_cache (opaque to other 7 * consumers). 8 * 9 * Storage: every Type and every supporting array (TY_FUNC param vectors, 10 * TY_STRUCT field arrays) is allocated from the Pool's arena, so pointers 11 * are stable for the Pool's lifetime. 12 * 13 * v1 covers what the cg test harness drives: 14 * void / scalars / pointer / function / struct / union 15 * Other constructors (array, qualified, enum) and predicates have minimal 16 * implementations sufficient for the cg test surface; they will grow with 17 * the parser. */ 18 19 #include "type/type.h" 20 21 #include <stdint.h> 22 #include <string.h> 23 24 #define NUM_PRIM_KINDS ((unsigned)TY_LDOUBLE + 1u) 25 26 typedef struct TypeListNode TypeListNode; 27 struct TypeListNode { 28 TypeListNode* next; 29 Type ty; 30 }; 31 32 static u32 type_fnv_ptr(u32 h, const void* q) { 33 u64 u = (u64)(uintptr_t)q; 34 h = (h ^ (u32)u) * 16777619u; 35 h = (h ^ (u32)(u >> 32)) * 16777619u; 36 return h; 37 } 38 39 /* Structural hash + equality over a (non-tagged) derived type's identity 40 * fields. These hash-cons TY_PTR / TY_ARRAY / TY_FUNC and qualified variants of 41 * non-tagged types: two independently built `int*` Types hash and compare equal 42 * and so collapse to one canonical node. They compare fields, never raw bytes, 43 * so a structural node's union tail and padding may stay uninitialized. */ 44 static u32 type_struct_hash(const Type* t) { 45 u32 h = 2166136261u; 46 h = (h ^ (u32)t->kind) * 16777619u; 47 h = (h ^ (u32)t->qual) * 16777619u; 48 switch (t->kind) { 49 case TY_PTR: 50 h = type_fnv_ptr(h, t->ptr.pointee); 51 break; 52 case TY_ARRAY: 53 h = type_fnv_ptr(h, t->arr.elem); 54 h = (h ^ t->arr.count) * 16777619u; 55 h = (h ^ (u32)t->arr.incomplete) * 16777619u; 56 break; 57 case TY_FUNC: { 58 u16 i; 59 h = type_fnv_ptr(h, t->fn.ret); 60 h = (h ^ (u32)t->fn.nparams) * 16777619u; 61 h = (h ^ (u32)t->fn.variadic) * 16777619u; 62 for (i = 0; i < t->fn.nparams; ++i) h = type_fnv_ptr(h, t->fn.params[i]); 63 break; 64 } 65 default: /* qualified primitive: kind + qual is the whole key */ 66 break; 67 } 68 return h; 69 } 70 71 static int type_struct_eq(const Type* a, const Type* b) { 72 if (a->kind != b->kind || a->qual != b->qual) return 0; 73 switch (a->kind) { 74 case TY_PTR: 75 return a->ptr.pointee == b->ptr.pointee; 76 case TY_ARRAY: 77 return a->arr.elem == b->arr.elem && a->arr.count == b->arr.count && 78 a->arr.incomplete == b->arr.incomplete; 79 case TY_FUNC: { 80 u16 i; 81 if (a->fn.ret != b->fn.ret || a->fn.nparams != b->fn.nparams || 82 a->fn.variadic != b->fn.variadic) 83 return 0; 84 for (i = 0; i < a->fn.nparams; ++i) 85 if (a->fn.params[i] != b->fn.params[i]) return 0; 86 return 1; 87 } 88 default: /* qualified primitive: kind + qual already matched */ 89 return 1; 90 } 91 } 92 93 /* Structural intern SET: the canonical Type* IS the stored element and 94 * membership is decided structurally (type_struct_eq) — which a scalar 95 * key->value map cannot express, hence KIT_HASHSET_DEFINE. Interns 96 * ptr/array/func + qualified non-tagged types; tagged types are interned by 97 * declaration identity on `derived` and never enter this set. Replaces the 98 * former O(types) linear scan of one flat derived list (which made each 99 * derivation O(types) → type construction O(types^2)). */ 100 KIT_HASHSET_DEFINE(TypeInternSet, const Type*, type_struct_hash, 101 type_struct_eq); 102 103 /* Completed record layout id, keyed by record identity. A record's identity is 104 * its tag id (same_record_type is tag-id equality), so a plain u32->id map 105 * captures it; the Pool is 1:1 with a compiler so no compiler key is needed. 106 * Replaces the former per-lookup list scan (O(records^2) for record-heavy TUs). 107 * Tag id 0 (TAG_NONE) never names a stored record, so it is safe as the empty 108 * key sentinel. */ 109 KIT_HASHMAP_DEFINE(CgRecordMap, u32, KitCgTypeId, kit_hash_u32); 110 111 static inline u32 type_ptr_hash(const Type* t) { 112 return kit_hash_u64((uint64_t)(uintptr_t)t); 113 } 114 115 /* Canonical-unqualified Type* memo, keyed by the qualified Type*. Collapses the 116 * O(derived) linear scan type_unqual runs for a complete tagged type (the hot 117 * const-record path) to one lookup. Only stable answers are inserted (a 118 * complete record's unqualified node never changes); incomplete/enum results 119 * are left uncached because they can still change as a forward record 120 * completes. */ 121 KIT_HASHMAP_DEFINE(CgUnqualMemo, const Type*, const Type*, type_ptr_hash); 122 123 typedef struct PoolTypeCache { 124 /* Direct slots for void + primitive kinds (TY_VOID..TY_LDOUBLE). */ 125 const Type* prim[NUM_PRIM_KINDS]; 126 /* Structurally-interned ptr/array/func + qualified non-tagged types. */ 127 TypeInternSet structural; 128 /* Identity-interned tagged types (struct/union/enum, qualified or not) and 129 * the throwaway record-builder results: a list, scanned only by the (rare) 130 * tag-based type_qualified / type_unqual paths and never per derivation. */ 131 TypeListNode* derived; 132 /* Completed record layout ids, keyed by tag id. */ 133 CgRecordMap cg_records; 134 /* Records whose CG completion is currently in flight, keyed by tag id -> 135 * decl id. Self-/mutually-recursive records reach themselves through a 136 * pointer field mid-completion; this lets type_cg_record_layout hand back the 137 * still-incomplete decl id (a pointer to an incomplete record is legal) 138 * instead of recursing into a second completion of the same record. */ 139 CgRecordMap cg_records_completing; 140 /* Canonical-unqualified node per qualified Type* (stable answers only). */ 141 CgUnqualMemo unqual; 142 /* Tag id allocator (1-based; TAG_NONE = 0). */ 143 u32 next_tag; 144 } PoolTypeCache; 145 146 static PoolTypeCache* cache_get(Pool* p) { 147 PoolTypeCache* c = (PoolTypeCache*)p->type_cache; 148 if (c) return c; 149 c = arena_new(p->arena, PoolTypeCache); 150 if (!c) return NULL; 151 memset(c, 0, sizeof *c); 152 c->next_tag = 1; 153 /* Both tables run on the pool's arena-heap facade: a resize orphans the old 154 * array into the arena (reclaimed wholesale at teardown), so no fini hook is 155 * needed. Lazy (cap 0): the first insert allocates. */ 156 TypeInternSet_init_cap(&c->structural, &p->arena_heap, 0); 157 CgRecordMap_init_cap(&c->cg_records, &p->arena_heap, 0); 158 CgRecordMap_init_cap(&c->cg_records_completing, &p->arena_heap, 0); 159 CgUnqualMemo_init_cap(&c->unqual, &p->arena_heap, 0); 160 p->type_cache = c; 161 return c; 162 } 163 164 static Type* alloc_type_node(Pool* p, PoolTypeCache* c) { 165 TypeListNode* n = arena_new(p->arena, TypeListNode); 166 if (!n) return NULL; 167 memset(n, 0, sizeof *n); 168 n->next = c->derived; 169 c->derived = n; 170 return &n->ty; 171 } 172 173 /* Bare structural-type node: arena-allocated, NOT linked into `derived`, NOT 174 * zeroed. Each constructor writes exactly the fields its kind reads; the 175 * structural set compares those fields (not raw bytes), so the union tail and 176 * padding may stay uninitialized. */ 177 static Type* alloc_struct_type(Pool* p) { 178 Type* t = arena_new(p->arena, Type); 179 /* cg_id is read before structural fields, so initialize it even though the 180 * union tail is intentionally left undefined (see the header). Qualified / 181 * unqual paths that do `*t = *base` inherit the cache, which is correct since 182 * lowering ignores qualifiers today. */ 183 if (t) t->cg_id = KIT_CG_TYPE_NONE; 184 return t; 185 } 186 187 const Type* type_void(Pool* p) { return type_prim(p, TY_VOID); } 188 189 const Type* type_prim(Pool* p, TypeKind kind) { 190 PoolTypeCache* c = cache_get(p); 191 if (!c) return NULL; 192 if ((unsigned)kind >= NUM_PRIM_KINDS) return NULL; 193 if (c->prim[kind]) return c->prim[kind]; 194 Type* t = alloc_type_node(p, c); 195 if (!t) return NULL; 196 t->kind = (u16)kind; 197 t->qual = 0; 198 c->prim[kind] = t; 199 return t; 200 } 201 202 const Type* type_ptr(Pool* p, const Type* pointee) { 203 PoolTypeCache* c = cache_get(p); 204 Type probe; 205 const Type* found; 206 Type* t; 207 if (!c) return NULL; 208 probe.kind = TY_PTR; 209 probe.qual = 0; 210 probe.ptr.pointee = pointee; 211 found = TypeInternSet_find(&c->structural, &probe); 212 if (found) return found; 213 t = alloc_struct_type(p); 214 if (!t) return NULL; 215 t->kind = TY_PTR; 216 t->qual = 0; 217 t->ptr.pointee = pointee; 218 TypeInternSet_add(&c->structural, t); 219 return t; 220 } 221 222 const Type* type_array(Pool* p, const Type* elem, u32 count, int incomplete) { 223 PoolTypeCache* c = cache_get(p); 224 Type probe; 225 const Type* found; 226 Type* t; 227 if (!c) return NULL; 228 probe.kind = TY_ARRAY; 229 probe.qual = 0; 230 probe.arr.elem = elem; 231 probe.arr.count = count; 232 probe.arr.incomplete = (u8)(incomplete ? 1 : 0); 233 found = TypeInternSet_find(&c->structural, &probe); 234 if (found) return found; 235 t = alloc_struct_type(p); 236 if (!t) return NULL; 237 t->kind = TY_ARRAY; 238 t->qual = 0; 239 t->arr.elem = elem; 240 t->arr.count = count; 241 t->arr.incomplete = (u8)(incomplete ? 1 : 0); 242 TypeInternSet_add(&c->structural, t); 243 return t; 244 } 245 246 const Type* type_func(Pool* p, const Type* ret, const Type** params, u16 n, 247 int variadic) { 248 PoolTypeCache* c = cache_get(p); 249 Type probe; 250 const Type* found; 251 Type* t; 252 if (!c) return NULL; 253 /* Borrow the caller's params array for the lookup; type_struct_eq compares it 254 * element-wise. Only on a miss do we allocate a persistent copy. */ 255 probe.kind = TY_FUNC; 256 probe.qual = 0; 257 probe.fn.ret = ret; 258 probe.fn.params = params; 259 probe.fn.nparams = n; 260 probe.fn.variadic = (u8)(variadic ? 1 : 0); 261 found = TypeInternSet_find(&c->structural, &probe); 262 if (found) return found; 263 t = alloc_struct_type(p); 264 if (!t) return NULL; 265 t->kind = TY_FUNC; 266 t->qual = 0; 267 t->fn.ret = ret; 268 t->fn.nparams = n; 269 t->fn.variadic = (u8)(variadic ? 1 : 0); 270 if (n) { 271 const Type** dst = arena_array(p->arena, const Type*, n); 272 if (!dst) return NULL; 273 for (u16 i = 0; i < n; ++i) dst[i] = params[i]; 274 t->fn.params = dst; 275 } else { 276 t->fn.params = NULL; 277 } 278 TypeInternSet_add(&c->structural, t); 279 return t; 280 } 281 282 /* Semantic identity of a tagged type for interning: kind + qual + the rec/enm 283 * identity payload. Replaces a memcmp over sizeof(Type) — which worked only 284 * because every tagged node carries zeroed padding (alloc_type_node memsets and 285 * struct assignment propagates it), a latent footgun that also forced the 286 * lowered-id cache off the node onto a side map. `incomplete` is part of the 287 * key (unlike type_compatible) because the qualified-snapshot model keeps an 288 * incomplete and a later-completed `const struct S` as distinct nodes. `n` is 289 * an interned node; `base` + the wanted `qual` describe the target (the payload 290 * is base's). */ 291 static int type_tagged_eq(const Type* n, const Type* base, u16 qual) { 292 if (n->kind != base->kind || n->qual != qual) return 0; 293 switch ((TypeKind)base->kind) { 294 case TY_STRUCT: 295 case TY_UNION: 296 return n->rec.tag_id == base->rec.tag_id && n->rec.tag == base->rec.tag && 297 n->rec.fields == base->rec.fields && 298 n->rec.nfields == base->rec.nfields && 299 n->rec.incomplete == base->rec.incomplete && 300 n->rec.packed == base->rec.packed && 301 n->rec.max_align == base->rec.max_align && 302 n->rec.align_override == base->rec.align_override; 303 case TY_ENUM: 304 return n->enm.tag_id == base->enm.tag_id && n->enm.tag == base->enm.tag && 305 n->enm.base == base->enm.base; 306 default: 307 return 0; 308 } 309 } 310 311 const Type* type_qualified(Pool* p, const Type* base, u16 qual) { 312 PoolTypeCache* c; 313 Type* t; 314 if (!base || qual == 0) return base; 315 c = cache_get(p); 316 if (!c) return NULL; 317 if (base->kind == TY_STRUCT || base->kind == TY_UNION || 318 base->kind == TY_ENUM) { 319 /* Tagged types are identity-interned on `derived` by semantic payload 320 * (type_tagged_eq), not a raw-byte compare. */ 321 for (TypeListNode* n = c->derived; n; n = n->next) { 322 if (type_tagged_eq(&n->ty, base, qual)) return &n->ty; 323 } 324 t = alloc_type_node(p, c); 325 if (!t) return NULL; 326 *t = *base; 327 t->qual = qual; 328 return t; 329 } 330 /* Non-tagged: structurally interned (qualified prim / ptr / array / func). */ 331 { 332 Type probe = *base; 333 const Type* found; 334 probe.qual = qual; 335 found = TypeInternSet_find(&c->structural, &probe); 336 if (found) return found; 337 t = alloc_struct_type(p); 338 if (!t) return NULL; 339 *t = *base; 340 t->qual = qual; 341 TypeInternSet_add(&c->structural, t); 342 return t; 343 } 344 } 345 346 /* ---- aggregates ---- */ 347 348 struct TypeRecordBuilder { 349 Pool* pool; 350 TypeKind kind; /* TY_STRUCT or TY_UNION */ 351 TagId tag_id; 352 Sym tag; 353 Field* fields; 354 u32 nfields; 355 u32 cap; 356 TypeRecordOpts opts; 357 }; 358 359 TagId type_tag_new(Pool* p, TagDeclKind kind, Sym spelling, SrcLoc loc) { 360 PoolTypeCache* c = cache_get(p); 361 if (!c) return TAG_NONE; 362 (void)kind; 363 (void)spelling; 364 (void)loc; 365 return (TagId)(c->next_tag++); 366 } 367 368 TypeRecordBuilder* type_record_begin(Pool* p, TypeKind kind, TagId tag_id, 369 Sym tag) { 370 TypeRecordOpts opts; 371 memset(&opts, 0, sizeof opts); 372 return type_record_begin_ex(p, kind, tag_id, tag, opts); 373 } 374 375 TypeRecordBuilder* type_record_begin_ex(Pool* p, TypeKind kind, TagId tag_id, 376 Sym tag, TypeRecordOpts opts) { 377 TypeRecordBuilder* b = arena_new(p->arena, TypeRecordBuilder); 378 if (!b) return NULL; 379 memset(b, 0, sizeof *b); 380 b->pool = p; 381 b->kind = kind; 382 b->tag_id = tag_id; 383 b->tag = tag; 384 b->opts = opts; 385 return b; 386 } 387 388 void type_record_field(TypeRecordBuilder* b, Field f) { 389 if (b->nfields == b->cap) { 390 u32 nc = b->cap ? b->cap * 2 : 4; 391 Field* nf = arena_array(b->pool->arena, Field, nc); 392 if (!nf) return; 393 if (b->fields) memcpy(nf, b->fields, sizeof(Field) * b->nfields); 394 b->fields = nf; 395 b->cap = nc; 396 } 397 b->fields[b->nfields++] = f; 398 } 399 400 const Type* type_record_end(Pool* p, TypeRecordBuilder* b) { 401 PoolTypeCache* c = cache_get(p); 402 if (!c) return NULL; 403 Type* t = alloc_type_node(p, c); 404 if (!t) return NULL; 405 t->kind = (u16)b->kind; 406 t->qual = 0; 407 t->rec.tag_id = b->tag_id; 408 t->rec.tag = b->tag; 409 t->rec.fields = b->fields; 410 t->rec.nfields = (u16)b->nfields; 411 t->rec.incomplete = 0; 412 t->rec.packed = b->opts.packed; 413 t->rec.max_align = b->opts.max_align; 414 t->rec.align_override = b->opts.align_override; 415 return t; 416 } 417 418 Type* type_record_forward(Pool* p, TypeKind kind, TagId tag_id, Sym tag) { 419 PoolTypeCache* c = cache_get(p); 420 if (!c) return NULL; 421 Type* t = alloc_type_node(p, c); 422 if (!t) return NULL; 423 t->kind = (u16)kind; 424 t->qual = 0; 425 t->rec.tag_id = tag_id; 426 t->rec.tag = tag; 427 t->rec.fields = NULL; 428 t->rec.nfields = 0; 429 t->rec.incomplete = 1; 430 t->rec.packed = 0; 431 t->rec.max_align = 0; 432 t->rec.align_override = 0; 433 return t; 434 } 435 436 void type_record_install(Type* forward, const Field* fields, u16 nfields) { 437 if (!forward) return; 438 forward->rec.fields = fields; 439 forward->rec.nfields = nfields; 440 forward->rec.incomplete = 0; 441 } 442 443 const Type* type_enum(Pool* p, TagId tag_id, Sym tag, const Type* base) { 444 PoolTypeCache* c = cache_get(p); 445 if (!c) return NULL; 446 Type* t = alloc_type_node(p, c); 447 if (!t) return NULL; 448 t->kind = TY_ENUM; 449 t->qual = 0; 450 t->enm.tag_id = tag_id; 451 t->enm.tag = tag; 452 t->enm.base = base; 453 return t; 454 } 455 456 /* ---- predicates / utilities ---- */ 457 458 const Type* type_unqual(Pool* p, const Type* t) { 459 PoolTypeCache* c; 460 Type* nt; 461 if (!t || t->qual == 0) return t; 462 if ((unsigned)t->kind < NUM_PRIM_KINDS) 463 return type_prim(p, (TypeKind)t->kind); 464 c = cache_get(p); 465 if (!c) return NULL; 466 if (t->kind == TY_STRUCT || t->kind == TY_UNION || t->kind == TY_ENUM) { 467 /* Tagged types are identity-interned on `derived`. */ 468 if ((t->kind == TY_STRUCT || t->kind == TY_UNION) && 469 t->rec.tag_id != TAG_NONE) { 470 /* The only memoized case: a complete record's unqualified node is fixed 471 * for the pool's lifetime, so this O(derived) scan can be skipped after 472 * the first hit. The memo holds only struct/union entries, so it is 473 * consulted here rather than taxing the (single-hash) non-tagged path. */ 474 const Type* const* hit = CgUnqualMemo_get(&c->unqual, t); 475 if (hit) return *hit; 476 for (TypeListNode* n = c->derived; n; n = n->next) { 477 if (n->ty.kind == t->kind && n->ty.qual == 0 && 478 n->ty.rec.tag_id == t->rec.tag_id && !n->ty.rec.incomplete) { 479 /* The incomplete/enum fall-throughs below stay uncached — their 480 * result can still change as a forward record completes. */ 481 CgUnqualMemo_set(&c->unqual, t, &n->ty); 482 return &n->ty; 483 } 484 } 485 } 486 for (TypeListNode* n = c->derived; n; n = n->next) { 487 if (type_tagged_eq(&n->ty, t, 0)) return &n->ty; 488 } 489 nt = alloc_type_node(p, c); 490 if (!nt) return NULL; 491 *nt = *t; 492 nt->qual = 0; 493 return nt; 494 } 495 /* Non-tagged: structurally interned (qualified prim is handled above as a 496 * prim; here that leaves ptr / array / func). */ 497 { 498 Type probe = *t; 499 const Type* found; 500 probe.qual = 0; 501 found = TypeInternSet_find(&c->structural, &probe); 502 if (found) return found; 503 nt = alloc_struct_type(p); 504 if (!nt) return NULL; 505 *nt = *t; 506 nt->qual = 0; 507 TypeInternSet_add(&c->structural, nt); 508 return nt; 509 } 510 } 511 512 const Type* type_promoted(Pool* p, const Type* t) { 513 if (!t) return t; 514 switch (t->kind) { 515 case TY_BOOL: 516 case TY_CHAR: 517 case TY_SCHAR: 518 case TY_UCHAR: 519 case TY_SHORT: 520 case TY_USHORT: 521 return type_prim(p, TY_INT); 522 default: 523 return t; 524 } 525 } 526 527 static int type_compatible_inner(const Type* a, const Type* b, unsigned depth) { 528 u16 i; 529 if (depth > 64) return 0; 530 if (a == b) return 1; 531 if (!a || !b) return 0; 532 if (a->qual != b->qual) return 0; 533 if (a->kind != b->kind) return 0; 534 switch (a->kind) { 535 case TY_VOID: 536 case TY_BOOL: 537 case TY_CHAR: 538 case TY_SCHAR: 539 case TY_UCHAR: 540 case TY_SHORT: 541 case TY_USHORT: 542 case TY_INT: 543 case TY_UINT: 544 case TY_LONG: 545 case TY_ULONG: 546 case TY_LLONG: 547 case TY_ULLONG: 548 case TY_INT128: 549 case TY_UINT128: 550 case TY_FLOAT: 551 case TY_DOUBLE: 552 case TY_LDOUBLE: 553 return 1; 554 case TY_PTR: 555 return type_compatible_inner(a->ptr.pointee, b->ptr.pointee, depth + 1); 556 case TY_ARRAY: 557 if (!type_compatible_inner(a->arr.elem, b->arr.elem, depth + 1)) return 0; 558 if (a->arr.incomplete || b->arr.incomplete) return 1; 559 return a->arr.count == b->arr.count; 560 case TY_FUNC: 561 if (a->fn.variadic != b->fn.variadic) return 0; 562 if (a->fn.nparams != b->fn.nparams) return 0; 563 if (!type_compatible_inner(a->fn.ret, b->fn.ret, depth + 1)) return 0; 564 for (i = 0; i < a->fn.nparams; ++i) { 565 if (!type_compatible_inner(a->fn.params[i], b->fn.params[i], depth + 1)) 566 return 0; 567 } 568 return 1; 569 case TY_STRUCT: 570 case TY_UNION: 571 return a->rec.tag_id != TAG_NONE && a->rec.tag_id == b->rec.tag_id; 572 case TY_ENUM: 573 if (a->enm.tag_id != TAG_NONE || b->enm.tag_id != TAG_NONE) 574 return a->enm.tag_id == b->enm.tag_id; 575 return type_compatible_inner(a->enm.base, b->enm.base, depth + 1); 576 default: 577 return 0; 578 } 579 } 580 581 int type_compatible(const Type* a, const Type* b) { 582 return type_compatible_inner(a, b, 0); 583 } 584 585 const Type* type_composite(Pool* p, const Type* a, const Type* b) { 586 const Type* elem; 587 const Type** params; 588 u16 i; 589 if (!type_compatible(a, b)) return NULL; 590 if (a == b) return a; 591 if (!a || !b) return NULL; 592 switch (a->kind) { 593 case TY_ARRAY: 594 elem = type_composite(p, a->arr.elem, b->arr.elem); 595 if (!elem) elem = a->arr.elem; 596 if (a->arr.incomplete && !b->arr.incomplete) 597 return type_array(p, elem, b->arr.count, 0); 598 if (b->arr.incomplete && !a->arr.incomplete) 599 return type_array(p, elem, a->arr.count, 0); 600 return type_array(p, elem, a->arr.count, a->arr.incomplete); 601 case TY_PTR: { 602 const Type* pointee = type_composite(p, a->ptr.pointee, b->ptr.pointee); 603 if (!pointee) pointee = a->ptr.pointee; 604 /* Preserve the pointer's own qualifiers (e.g. the inner `const` of 605 * `const char* const*`); type_ptr alone yields an unqualified pointer. */ 606 return type_qualified(p, type_ptr(p, pointee), a->qual); 607 } 608 case TY_FUNC: 609 if (a->fn.nparams == 0) return a; 610 params = arena_array(p->arena, const Type*, a->fn.nparams); 611 if (!params) return NULL; 612 for (i = 0; i < a->fn.nparams; ++i) { 613 params[i] = type_composite(p, a->fn.params[i], b->fn.params[i]); 614 if (!params[i]) params[i] = a->fn.params[i]; 615 } 616 return type_func(p, type_composite(p, a->fn.ret, b->fn.ret), params, 617 a->fn.nparams, a->fn.variadic); 618 default: 619 return a; 620 } 621 } 622 623 /* Single source of truth for per-TypeKind scalar facts. Indexed directly by 624 * TypeKind (sized to TY_ENUM + 1); the aggregate kinds PTR/ARRAY/FUNC/STRUCT/ 625 * UNION are zero-filled holes. Columns: 626 * is_signed - signed integer (drives sign-extension / signed cg ops) 627 * is_int - integer type (bool/char/.../enum) 628 * is_fp - floating-point type 629 * rank - C integer conversion rank (0 for non-integers) 630 * uvariant - corresponding unsigned TypeKind (TY_UINT for non-integers, 631 * matching the historical default) 632 * Accessors below read this table instead of re-enumerating the kinds. */ 633 typedef struct TypeKindProps { 634 u8 is_signed; 635 u8 is_int; 636 u8 is_fp; 637 u8 rank; 638 u8 uvariant; /* TypeKind */ 639 } TypeKindProps; 640 641 static const TypeKindProps kTypeKindProps[TY_ENUM + 1] = { 642 [TY_VOID] = {0, 0, 0, 0, TY_UINT}, 643 [TY_BOOL] = {0, 1, 0, 1, TY_UINT}, 644 [TY_CHAR] = {1, 1, 0, 2, TY_UINT}, 645 [TY_SCHAR] = {1, 1, 0, 2, TY_UINT}, 646 [TY_UCHAR] = {0, 1, 0, 2, TY_UINT}, 647 [TY_SHORT] = {1, 1, 0, 3, TY_UINT}, 648 [TY_USHORT] = {0, 1, 0, 3, TY_UINT}, 649 [TY_INT] = {1, 1, 0, 4, TY_UINT}, 650 [TY_UINT] = {0, 1, 0, 4, TY_UINT}, 651 [TY_LONG] = {1, 1, 0, 5, TY_ULONG}, 652 [TY_ULONG] = {0, 1, 0, 5, TY_ULONG}, 653 [TY_LLONG] = {1, 1, 0, 6, TY_ULLONG}, 654 [TY_ULLONG] = {0, 1, 0, 6, TY_ULLONG}, 655 [TY_INT128] = {1, 1, 0, 7, TY_UINT128}, 656 [TY_UINT128] = {0, 1, 0, 7, TY_UINT128}, 657 [TY_FLOAT] = {0, 0, 1, 0, TY_UINT}, 658 [TY_DOUBLE] = {0, 0, 1, 0, TY_UINT}, 659 [TY_LDOUBLE] = {0, 0, 1, 0, TY_UINT}, 660 /* PTR/ARRAY/FUNC/STRUCT/UNION: zero-filled holes (uvariant 0 == TY_VOID 661 * is never read for non-integers; callers map non-int to TY_UINT). */ 662 [TY_ENUM] = {1, 1, 0, 4, TY_UINT}, 663 }; 664 665 static const TypeKindProps* type_kind_props(TypeKind k) { 666 if ((unsigned)k > (unsigned)TY_ENUM) return &kTypeKindProps[TY_VOID]; 667 return &kTypeKindProps[k]; 668 } 669 670 int type_kind_is_int(TypeKind k) { return type_kind_props(k)->is_int; } 671 int type_kind_is_fp(TypeKind k) { return type_kind_props(k)->is_fp; } 672 int type_kind_is_signed_integer(TypeKind k) { 673 return type_kind_props(k)->is_signed; 674 } 675 u32 type_kind_int_rank(TypeKind k) { return type_kind_props(k)->rank; } 676 TypeKind type_kind_unsigned_variant(TypeKind k) { 677 const TypeKindProps* p = type_kind_props(k); 678 return p->is_int ? (TypeKind)p->uvariant : TY_UINT; 679 } 680 681 int type_is_int(const Type* t) { 682 return t ? type_kind_is_int((TypeKind)t->kind) : 0; 683 } 684 685 int type_is_arith(const Type* t) { 686 if (!t) return 0; 687 return type_kind_is_int((TypeKind)t->kind) || 688 type_kind_is_fp((TypeKind)t->kind); 689 } 690 691 int type_is_ptr(const Type* t) { return t && t->kind == TY_PTR; } 692 693 int type_is_signed_integer(const Type* t) { 694 return t ? type_kind_is_signed_integer((TypeKind)t->kind) : 0; 695 } 696 697 static KitCgTypeId type_cg_builtin(KitCompiler* c, TypeKind kind) { 698 /* Hot path: one builtin id per query, no whole-table copy. The target spec 699 * (a by-value struct) is only consulted for the two data-model-dependent 700 * widths, so it is fetched lazily inside those cases rather than per call. */ 701 switch (kind) { 702 case TY_VOID: 703 return kit_cg_type_builtin(c, KIT_CG_BUILTIN_VOID); 704 case TY_BOOL: 705 return kit_cg_type_builtin(c, KIT_CG_BUILTIN_BOOL); 706 case TY_CHAR: 707 case TY_SCHAR: 708 case TY_UCHAR: 709 return kit_cg_type_builtin(c, KIT_CG_BUILTIN_I8); 710 case TY_SHORT: 711 case TY_USHORT: 712 return kit_cg_type_builtin(c, KIT_CG_BUILTIN_I16); 713 case TY_INT: 714 case TY_UINT: 715 return kit_cg_type_builtin(c, KIT_CG_BUILTIN_I32); 716 case TY_LONG: 717 case TY_ULONG: 718 return kit_cg_type_builtin( 719 c, kit_target_uses_lp64(kit_compiler_target_spec(c)) 720 ? KIT_CG_BUILTIN_I64 721 : KIT_CG_BUILTIN_I32); 722 case TY_LLONG: 723 case TY_ULLONG: 724 return kit_cg_type_builtin(c, KIT_CG_BUILTIN_I64); 725 case TY_INT128: 726 case TY_UINT128: 727 return kit_cg_type_builtin(c, KIT_CG_BUILTIN_I128); 728 case TY_FLOAT: 729 return kit_cg_type_builtin(c, KIT_CG_BUILTIN_F32); 730 case TY_DOUBLE: 731 return kit_cg_type_builtin(c, KIT_CG_BUILTIN_F64); 732 case TY_LDOUBLE: 733 /* `long double` is IEEE-754 binary128 on targets that follow the quad 734 * psABI (RISC-V, aarch64-linux, wasm32); elsewhere it aliases `double`. 735 * See kit_target_long_double_is_binary128. */ 736 return kit_cg_type_builtin( 737 c, kit_target_long_double_is_binary128(kit_compiler_target_spec(c)) 738 ? KIT_CG_BUILTIN_F128 739 : KIT_CG_BUILTIN_F64); 740 default: 741 break; 742 } 743 return KIT_CG_TYPE_NONE; 744 } 745 746 /* Source spelling + debug encoding per integer/char TypeKind. CG integer 747 * storage is width-only; this table drives the separate debug channel so C 748 * signedness and spelling reach DWARF without changing the operational type id. 749 * Kinds with a NULL name use the debug producer's default derivation. */ 750 typedef struct ScalarDbgSpec { 751 const char* name; 752 u8 enc; /* KitCgDebugEncoding */ 753 } ScalarDbgSpec; 754 755 static const ScalarDbgSpec kScalarDbg[TY_ENUM + 1] = { 756 [TY_CHAR] = {"char", KIT_CG_DEBUG_ENC_SIGNED_CHAR}, 757 [TY_SCHAR] = {"signed char", KIT_CG_DEBUG_ENC_SIGNED_CHAR}, 758 [TY_UCHAR] = {"unsigned char", KIT_CG_DEBUG_ENC_UNSIGNED_CHAR}, 759 [TY_SHORT] = {"short", KIT_CG_DEBUG_ENC_SIGNED}, 760 [TY_USHORT] = {"unsigned short", KIT_CG_DEBUG_ENC_UNSIGNED}, 761 [TY_INT] = {"int", KIT_CG_DEBUG_ENC_SIGNED}, 762 [TY_UINT] = {"unsigned int", KIT_CG_DEBUG_ENC_UNSIGNED}, 763 [TY_LONG] = {"long", KIT_CG_DEBUG_ENC_SIGNED}, 764 [TY_ULONG] = {"unsigned long", KIT_CG_DEBUG_ENC_UNSIGNED}, 765 [TY_LLONG] = {"long long", KIT_CG_DEBUG_ENC_SIGNED}, 766 [TY_ULLONG] = {"unsigned long long", KIT_CG_DEBUG_ENC_UNSIGNED}, 767 [TY_INT128] = {"__int128", KIT_CG_DEBUG_ENC_SIGNED}, 768 [TY_UINT128] = {"unsigned __int128", KIT_CG_DEBUG_ENC_UNSIGNED}, 769 }; 770 771 /* Lower a scalar TypeKind to its operational CG type id: a bare storage builtin 772 * for scalar kinds, or NONE for non-scalar kinds (caller falls through to the 773 * structural lowering). Pure function of (kind, target), like type_cg_builtin. 774 */ 775 static KitCgTypeId type_cg_scalar(KitCompiler* c, TypeKind kind) { 776 return type_cg_builtin(c, kind); 777 } 778 779 typedef enum TypeCgMode { 780 TYPE_CG_VALUE, 781 } TypeCgMode; 782 783 typedef struct TypeCgLower { 784 KitCompiler* c; 785 Pool* p; 786 PoolTypeCache* cache; 787 /* Raised whenever lowering passes through a still-incomplete record; scoped 788 * per subtree by type_cg_lower so a node is memoized only when its whole 789 * lowering was incomplete-free (and thus stable for the pool's lifetime). */ 790 int saw_incomplete; 791 } TypeCgLower; 792 793 static KitCgTypeId type_cg_lower(TypeCgLower* l, const Type* t, 794 TypeCgMode mode); 795 796 /* Record identity is its tag id (records are never structurally interned), so 797 * the memo is a plain tag-id -> layout-id map. Only ever called with STRUCT/ 798 * UNION types, so t->rec is live; complete records always carry a non-zero tag, 799 * so tag 0 is free to serve as the map's empty-key sentinel. */ 800 static KitCgTypeId type_cg_record_memo_get(PoolTypeCache* cache, KitCompiler* c, 801 const Type* t) { 802 const KitCgTypeId* hit; 803 (void)c; 804 if (!cache) return KIT_CG_TYPE_NONE; 805 hit = CgRecordMap_get(&cache->cg_records, t->rec.tag_id); 806 return hit ? *hit : KIT_CG_TYPE_NONE; 807 } 808 809 static void type_cg_record_memo_put(Pool* p, PoolTypeCache* cache, 810 KitCompiler* c, const Type* t, 811 KitCgTypeId id) { 812 (void)p; 813 (void)c; 814 if (!cache || !t || id == KIT_CG_TYPE_NONE) return; 815 if (t->kind != TY_STRUCT && t->kind != TY_UNION) return; 816 if (t->rec.tag_id == TAG_NONE) return; 817 CgRecordMap_set(&cache->cg_records, t->rec.tag_id, id); 818 } 819 820 static KitCgTypeId type_cg_record_decl_id(TypeCgLower* l, const Type* t) { 821 KitCgTypeId id; 822 if (!l || !t || (t->kind != TY_STRUCT && t->kind != TY_UNION)) { 823 return KIT_CG_TYPE_NONE; 824 } 825 id = type_cg_record_memo_get(l->cache, l->c, t); 826 if (id != KIT_CG_TYPE_NONE) return id; 827 id = kit_cg_type_record_decl(l->c, t->rec.tag, t->kind == TY_UNION); 828 type_cg_record_memo_put(l->p, l->cache, l->c, t, id); 829 return id; 830 } 831 832 static KitCgTypeId type_cg_record_layout(TypeCgLower* l, const Type* t) { 833 KitCgFieldDesc* fields = NULL; 834 KitCgRecordDesc desc; 835 KitCgTypeId id; 836 int tracked = 0; 837 if (!l || !t || (t->kind != TY_STRUCT && t->kind != TY_UNION)) { 838 return KIT_CG_TYPE_NONE; 839 } 840 id = type_cg_record_decl_id(l, t); 841 if (id == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 842 if (t->rec.incomplete) { 843 l->saw_incomplete = 1; 844 return id; 845 } 846 if (kit_cg_type_is_complete(l->c, id)) return id; 847 /* Cycle safety net. Recursion *through a pointer* is already broken in the 848 * TY_PTR case (the pointee takes the decl id, never re-entering here), so the 849 * valid self-/mutual-reference shapes never reach this guard. What can still 850 * re-enter mid-completion is a by-value path back to an in-flight record -- 851 * e.g. the invalid `struct N { struct N arr[10]; }`, where the array forces 852 * its incomplete element to lay out. Hand back the still-incomplete decl id 853 * (the array then fails the sized-element check, surfacing a clean error) 854 * rather than recursing into a second completion and overflowing the stack. 855 * Track every in-flight record so mutual by-value cycles are covered too. 856 * Anonymous records carry no tag but cannot name themselves, so they never 857 * reach this guard. */ 858 if (t->rec.tag_id != TAG_NONE) { 859 if (CgRecordMap_get(&l->cache->cg_records_completing, t->rec.tag_id)) { 860 l->saw_incomplete = 1; 861 return id; 862 } 863 CgRecordMap_set(&l->cache->cg_records_completing, t->rec.tag_id, id); 864 tracked = 1; 865 } 866 if (t->rec.nfields) { 867 fields = arena_zarray(l->p->arena, KitCgFieldDesc, t->rec.nfields); 868 if (!fields) { 869 id = KIT_CG_TYPE_NONE; 870 goto done; 871 } 872 for (u32 i = 0; i < t->rec.nfields; ++i) { 873 fields[i].name = t->rec.fields[i].name; 874 fields[i].type = type_cg_lower(l, t->rec.fields[i].type, TYPE_CG_VALUE); 875 fields[i].align_override = t->rec.fields[i].align_override; 876 fields[i].max_align = t->rec.fields[i].max_align; 877 if (t->rec.max_align && 878 (fields[i].max_align == 0 || t->rec.max_align < fields[i].max_align)) 879 fields[i].max_align = t->rec.max_align; 880 if (t->rec.fields[i].flags & FIELD_BITFIELD) { 881 fields[i].flags |= KIT_CG_FIELD_BITFIELD; 882 /* A zero-width bit-field is carried to CG as bit_width 0 (the layout 883 * barrier); CG keys off BITFIELD && bit_width==0, no separate flag. */ 884 fields[i].bit_width = t->rec.fields[i].bitfield_width; 885 fields[i].bit_signed = type_is_signed_integer(t->rec.fields[i].type); 886 } 887 if (t->rec.fields[i].packed && fields[i].align_override == 0) { 888 fields[i].align_override = 1; 889 } 890 if (t->rec.packed && fields[i].align_override == 0) { 891 fields[i].align_override = 1; 892 } 893 } 894 } 895 memset(&desc, 0, sizeof desc); 896 desc.tag = t->rec.tag; 897 desc.fields = fields; 898 desc.nfields = t->rec.nfields; 899 desc.is_union = t->kind == TY_UNION; 900 desc.align_override = t->rec.align_override; 901 if (kit_cg_type_record_complete(l->c, id, &desc) != KIT_OK) 902 id = KIT_CG_TYPE_NONE; 903 done: 904 /* Clear the in-flight marker so a later, independent lowering of the same tag 905 * (now CG-complete) takes the fast is_complete path rather than this guard. 906 */ 907 if (tracked) CgRecordMap_del(&l->cache->cg_records_completing, t->rec.tag_id); 908 return id; 909 } 910 911 static KitCgTypeId type_cg_lower(TypeCgLower* l, const Type* t, 912 TypeCgMode mode) { 913 KitCgTypeId id; 914 int cacheable; 915 int outer_incomplete; 916 if (!l || !t) return KIT_CG_TYPE_NONE; 917 /* Check the cache BEFORE the builtin switch: a cached cg_id (whether a 918 * builtin id stamped below or a non-builtin lowering) always equals what the 919 * switch would recompute, so this hoist only short-circuits already-lowered 920 * types -- byte-identical, but skips the recompute. */ 921 cacheable = (mode == TYPE_CG_VALUE); 922 if (cacheable && t->cg_id != KIT_CG_TYPE_NONE) 923 return t->cg_id; /* cached => was incomplete-free => still stable */ 924 id = type_cg_scalar(l->c, (TypeKind)t->kind); 925 if (id != KIT_CG_TYPE_NONE) { 926 /* type_cg_scalar is a pure function of t->kind (and the fixed target), so 927 * a scalar id is mode-independent and incomplete-free: stamp it on the 928 * node so the next VALUE-mode crossing short-circuits above. Scalar ids are 929 * never 0, so they can't alias the NONE sentinel. */ 930 if (cacheable) ((Type*)t)->cg_id = id; 931 return id; 932 } 933 /* Scope saw_incomplete to this subtree so the post-recursion check reflects 934 * only whether *this* node's lowering touched an incomplete record. */ 935 outer_incomplete = l->saw_incomplete; 936 l->saw_incomplete = 0; 937 switch ((TypeKind)t->kind) { 938 case TY_PTR: { 939 /* A pointer needs only its pointee's nominal identity, never its layout, 940 * so a record/union pointee lowers to its (possibly incomplete) decl id 941 * instead of being completed here. This is what makes a forward-declared 942 * record used only through pointers legal without ever completing it, and 943 * it breaks self-/mutual-reference cycles (struct N { struct N* next; }, 944 * A<->B) at the pointer rather than recursing into completion. A record 945 * is completed only when something needs its layout -- a by-value local, 946 * field, param/result, array element, sizeof, or member access -- all of 947 * which lower the record itself, not a pointer to it. */ 948 const Type* pointee = t->ptr.pointee; 949 KitCgTypeId pid; 950 if (pointee->kind == TY_STRUCT || pointee->kind == TY_UNION) { 951 pid = type_cg_record_decl_id(l, pointee); 952 if (pid != KIT_CG_TYPE_NONE && !kit_cg_type_is_complete(l->c, pid)) 953 l->saw_incomplete = 1; 954 } else { 955 pid = type_cg_lower(l, pointee, TYPE_CG_VALUE); 956 } 957 id = pid == KIT_CG_TYPE_NONE ? KIT_CG_TYPE_NONE 958 : kit_cg_type_ptr(l->c, pid, 0); 959 break; 960 } 961 case TY_ARRAY: 962 id = kit_cg_type_array(l->c, type_cg_lower(l, t->arr.elem, mode), 963 t->arr.count); 964 break; 965 case TY_FUNC: { 966 KitCgFuncParam* params = NULL; 967 KitCgFuncSig sig; 968 memset(&sig, 0, sizeof sig); 969 sig.result.type = type_cg_lower(l, t->fn.ret, TYPE_CG_VALUE); 970 sig.nparams = t->fn.nparams; 971 sig.abi_variadic = t->fn.variadic; 972 sig.call_conv = KIT_CG_CC_TARGET_C; 973 if (t->fn.nparams) { 974 params = arena_zarray(l->p->arena, KitCgFuncParam, t->fn.nparams); 975 if (!params) { 976 id = KIT_CG_TYPE_NONE; 977 break; 978 } 979 for (u32 i = 0; i < t->fn.nparams; ++i) { 980 params[i].type = type_cg_lower(l, t->fn.params[i], TYPE_CG_VALUE); 981 } 982 } 983 sig.params = params; 984 id = kit_cg_type_func(l->c, sig); 985 break; 986 } 987 case TY_STRUCT: 988 case TY_UNION: 989 id = type_cg_record_layout(l, t); 990 break; 991 case TY_ENUM: { 992 KitCgTypeId ebase = type_cg_lower(l, t->enm.base, mode); 993 KitCgEnumValue* evs = NULL; 994 u32 nv = t->enm.nconsts; 995 if (nv) { 996 evs = arena_array(l->p->arena, KitCgEnumValue, nv); 997 if (!evs) { 998 nv = 0; 999 } else { 1000 for (u32 i = 0; i < nv; ++i) { 1001 evs[i].name = t->enm.consts[i].name; 1002 evs[i].value = (u64)t->enm.consts[i].value; 1003 } 1004 } 1005 } 1006 id = kit_cg_type_enum(l->c, t->enm.tag, ebase, evs, nv); 1007 break; 1008 } 1009 default: 1010 id = KIT_CG_TYPE_NONE; 1011 break; 1012 } 1013 if (cacheable && id != KIT_CG_TYPE_NONE && !l->saw_incomplete) { 1014 /* The node is the canonical interned type and we own its storage (arena); 1015 * the const is only the public contract. Stashing the stable lowering here 1016 * is exactly what dropping the memcmp interning bought us. */ 1017 ((Type*)t)->cg_id = id; 1018 } 1019 /* Propagate this subtree's incompleteness to the enclosing lowering. */ 1020 l->saw_incomplete |= outer_incomplete; 1021 return id; 1022 } 1023 1024 KitCgTypeId type_cg_id_in_pool(KitCompiler* c, Pool* p, const Type* t) { 1025 TypeCgLower l; 1026 if (!p) return KIT_CG_TYPE_NONE; 1027 /* TypeCgLower has exactly these four fields; explicit init writes the same 1028 * values the memset+assignments did, skipping a per-crossing struct clear. */ 1029 l.c = c; 1030 l.p = p; 1031 l.cache = cache_get(p); 1032 l.saw_incomplete = 0; 1033 return type_cg_lower(&l, t, TYPE_CG_VALUE); 1034 } 1035 1036 typedef struct TypeCgDebugLower { 1037 KitCg* cg; 1038 KitCompiler* c; 1039 Pool* p; 1040 PoolTypeCache* cache; 1041 } TypeCgDebugLower; 1042 1043 static KitCgDebugType type_cg_debug_scalar(TypeCgDebugLower* l, TypeKind kind) { 1044 KitCgTypeId storage = type_cg_builtin(l->c, kind); 1045 const ScalarDbgSpec* s; 1046 uint32_t bytes; 1047 if (storage == KIT_CG_TYPE_NONE) return KIT_CG_DEBUG_TYPE_NONE; 1048 if ((unsigned)kind > (unsigned)TY_ENUM) { 1049 return kit_cg_debug_of_type(l->cg, storage); 1050 } 1051 s = &kScalarDbg[kind]; 1052 if (!s->name) return kit_cg_debug_of_type(l->cg, storage); 1053 bytes = (uint32_t)kit_cg_type_size(l->c, storage); 1054 if (!bytes) bytes = 1; 1055 return kit_cg_debug_base(l->cg, kit_sym_intern(l->c, kit_slice_cstr(s->name)), 1056 (KitCgDebugEncoding)s->enc, bytes); 1057 } 1058 1059 static KitCgDebugType type_cg_debug_record_decl(TypeCgDebugLower* l, 1060 const Type* t) { 1061 TypeCgLower op; 1062 KitCgTypeId id; 1063 op.c = l->c; 1064 op.p = l->p; 1065 op.cache = l->cache; 1066 op.saw_incomplete = 0; 1067 id = type_cg_record_decl_id(&op, t); 1068 return kit_cg_debug_of_type(l->cg, id); 1069 } 1070 1071 static KitCgDebugType type_cg_debug_lower(TypeCgDebugLower* l, const Type* t) { 1072 KitCgDebugType id; 1073 if (!l || !t) return KIT_CG_DEBUG_TYPE_NONE; 1074 1075 id = type_cg_debug_scalar(l, (TypeKind)t->kind); 1076 if (id != KIT_CG_DEBUG_TYPE_NONE) return id; 1077 1078 switch ((TypeKind)t->kind) { 1079 case TY_PTR: { 1080 const Type* pointee = t->ptr.pointee; 1081 KitCgDebugType pd; 1082 if (pointee->kind == TY_STRUCT || pointee->kind == TY_UNION) { 1083 pd = type_cg_debug_record_decl(l, pointee); 1084 } else { 1085 pd = type_cg_debug_lower(l, pointee); 1086 } 1087 id = kit_cg_debug_ptr(l->cg, pd); 1088 break; 1089 } 1090 case TY_ARRAY: 1091 id = kit_cg_debug_array(l->cg, type_cg_debug_lower(l, t->arr.elem), 1092 t->arr.incomplete ? 0u : t->arr.count); 1093 break; 1094 case TY_FUNC: { 1095 KitCgDebugType* params = NULL; 1096 KitCgDebugType ret = type_cg_debug_lower(l, t->fn.ret); 1097 if (t->fn.nparams) { 1098 params = arena_zarray(l->p->arena, KitCgDebugType, t->fn.nparams); 1099 if (!params) { 1100 id = KIT_CG_DEBUG_TYPE_NONE; 1101 break; 1102 } 1103 for (u32 i = 0; i < t->fn.nparams; ++i) { 1104 params[i] = type_cg_debug_lower(l, t->fn.params[i]); 1105 } 1106 } 1107 id = kit_cg_debug_func(l->cg, ret, params, t->fn.nparams, t->fn.variadic); 1108 break; 1109 } 1110 case TY_STRUCT: 1111 case TY_UNION: { 1112 KitCgTypeId op_id = type_cg_id_in_pool(l->c, l->p, t); 1113 id = kit_cg_debug_of_type(l->cg, op_id); 1114 break; 1115 } 1116 case TY_ENUM: { 1117 KitCgTypeId op_id = type_cg_id_in_pool(l->c, l->p, t); 1118 KitCgDebugType base = type_cg_debug_lower(l, t->enm.base); 1119 id = kit_cg_debug_enum(l->cg, op_id, base); 1120 break; 1121 } 1122 default: 1123 id = KIT_CG_DEBUG_TYPE_NONE; 1124 break; 1125 } 1126 1127 return id; 1128 } 1129 1130 KitCgDebugType type_cg_debug_in_pool(KitCg* cg, KitCompiler* c, Pool* p, 1131 const Type* t) { 1132 TypeCgDebugLower l; 1133 if (!cg || !p) return KIT_CG_DEBUG_TYPE_NONE; 1134 l.cg = cg; 1135 l.c = c; 1136 l.p = p; 1137 l.cache = cache_get(p); 1138 return type_cg_debug_lower(&l, t); 1139 }