kit

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

type.c (22941B)


      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 typedef struct CgRecordMemo CgRecordMemo;
     33 struct CgRecordMemo {
     34   CgRecordMemo* next;
     35   const KitCompiler* compiler;
     36   const Type* type;
     37   KitCgTypeId id;
     38 };
     39 
     40 typedef struct PoolTypeCache {
     41   /* Direct slots for void + primitive kinds (TY_VOID..TY_LDOUBLE). */
     42   const Type* prim[NUM_PRIM_KINDS];
     43   /* Linked list of every other type allocated through this pool. */
     44   TypeListNode* derived;
     45   /* Completed record layout ids are compiler-local. */
     46   CgRecordMemo* cg_record_memos;
     47   /* Tag id allocator (1-based; TAG_NONE = 0). */
     48   u32 next_tag;
     49 } PoolTypeCache;
     50 
     51 static PoolTypeCache* cache_get(Pool* p) {
     52   PoolTypeCache* c = (PoolTypeCache*)p->type_cache;
     53   if (c) return c;
     54   c = arena_new(p->arena, PoolTypeCache);
     55   if (!c) return NULL;
     56   memset(c, 0, sizeof *c);
     57   c->next_tag = 1;
     58   p->type_cache = c;
     59   return c;
     60 }
     61 
     62 static Type* alloc_type_node(Pool* p, PoolTypeCache* c) {
     63   TypeListNode* n = arena_new(p->arena, TypeListNode);
     64   if (!n) return NULL;
     65   memset(n, 0, sizeof *n);
     66   n->next = c->derived;
     67   c->derived = n;
     68   return &n->ty;
     69 }
     70 
     71 const Type* type_void(Pool* p) { return type_prim(p, TY_VOID); }
     72 
     73 const Type* type_prim(Pool* p, TypeKind kind) {
     74   PoolTypeCache* c = cache_get(p);
     75   if (!c) return NULL;
     76   if ((unsigned)kind >= NUM_PRIM_KINDS) return NULL;
     77   if (c->prim[kind]) return c->prim[kind];
     78   Type* t = alloc_type_node(p, c);
     79   if (!t) return NULL;
     80   t->kind = (u16)kind;
     81   t->qual = 0;
     82   c->prim[kind] = t;
     83   return t;
     84 }
     85 
     86 const Type* type_ptr(Pool* p, const Type* pointee) {
     87   PoolTypeCache* c = cache_get(p);
     88   if (!c) return NULL;
     89   /* Linear search; small N in practice. */
     90   for (TypeListNode* n = c->derived; n; n = n->next) {
     91     if (n->ty.kind == TY_PTR && n->ty.qual == 0 &&
     92         n->ty.ptr.pointee == pointee) {
     93       return &n->ty;
     94     }
     95   }
     96   Type* t = alloc_type_node(p, c);
     97   if (!t) return NULL;
     98   t->kind = TY_PTR;
     99   t->qual = 0;
    100   t->ptr.pointee = pointee;
    101   return t;
    102 }
    103 
    104 const Type* type_array(Pool* p, const Type* elem, u32 count, int incomplete) {
    105   PoolTypeCache* c = cache_get(p);
    106   if (!c) return NULL;
    107   for (TypeListNode* n = c->derived; n; n = n->next) {
    108     if (n->ty.kind == TY_ARRAY && n->ty.qual == 0 && n->ty.arr.elem == elem &&
    109         n->ty.arr.count == count &&
    110         n->ty.arr.incomplete == (u8)(incomplete ? 1 : 0)) {
    111       return &n->ty;
    112     }
    113   }
    114   Type* t = alloc_type_node(p, c);
    115   if (!t) return NULL;
    116   t->kind = TY_ARRAY;
    117   t->qual = 0;
    118   t->arr.elem = elem;
    119   t->arr.count = count;
    120   t->arr.incomplete = (u8)(incomplete ? 1 : 0);
    121   return t;
    122 }
    123 
    124 static int param_arrays_eq(const Type* const* a, const Type* const* b, u16 n) {
    125   for (u16 i = 0; i < n; ++i)
    126     if (a[i] != b[i]) return 0;
    127   return 1;
    128 }
    129 
    130 const Type* type_func(Pool* p, const Type* ret, const Type** params, u16 n,
    131                       int variadic) {
    132   PoolTypeCache* c = cache_get(p);
    133   if (!c) return NULL;
    134   for (TypeListNode* nd = c->derived; nd; nd = nd->next) {
    135     if (nd->ty.kind == TY_FUNC && nd->ty.qual == 0 && nd->ty.fn.ret == ret &&
    136         nd->ty.fn.nparams == n &&
    137         nd->ty.fn.variadic == (u8)(variadic ? 1 : 0) &&
    138         param_arrays_eq(nd->ty.fn.params, params, n)) {
    139       return &nd->ty;
    140     }
    141   }
    142   Type* t = alloc_type_node(p, c);
    143   if (!t) return NULL;
    144   t->kind = TY_FUNC;
    145   t->qual = 0;
    146   t->fn.ret = ret;
    147   t->fn.nparams = n;
    148   t->fn.variadic = (u8)(variadic ? 1 : 0);
    149   if (n) {
    150     const Type** dst = arena_array(p->arena, const Type*, n);
    151     if (!dst) return NULL;
    152     for (u16 i = 0; i < n; ++i) dst[i] = params[i];
    153     t->fn.params = dst;
    154   } else {
    155     t->fn.params = NULL;
    156   }
    157   return t;
    158 }
    159 
    160 const Type* type_qualified(Pool* p, const Type* base, u16 qual) {
    161   PoolTypeCache* c;
    162   Type tmpl;
    163   Type* t;
    164   if (!base || qual == 0) return base;
    165   c = cache_get(p);
    166   if (!c) return NULL;
    167   /* Build the comparison template once, via assignment (not aggregate
    168    * initialization). Struct assignment copies the full object representation,
    169    * including padding bytes, so the memcmp below is byte-stable against the
    170    * interned nodes (which are likewise produced by `*t = tmpl`). An aggregate
    171    * *initializer* (`Type tmpl = *base;`) is lowered as a field-by-field copy
    172    * that leaves padding unspecified, which would make this memcmp miss and
    173    * intern a duplicate qualified type. See type_unqual for the same idiom. */
    174   tmpl = *base;
    175   tmpl.qual = qual;
    176   for (TypeListNode* n = c->derived; n; n = n->next) {
    177     if (n->ty.kind == base->kind && n->ty.qual == qual &&
    178         memcmp(&n->ty, &tmpl, sizeof(Type)) == 0) {
    179       return &n->ty;
    180     }
    181   }
    182   t = alloc_type_node(p, c);
    183   if (!t) return NULL;
    184   *t = tmpl;
    185   return t;
    186 }
    187 
    188 /* ---- aggregates ---- */
    189 
    190 struct TypeRecordBuilder {
    191   Pool* pool;
    192   TypeKind kind; /* TY_STRUCT or TY_UNION */
    193   TagId tag_id;
    194   Sym tag;
    195   Field* fields;
    196   u32 nfields;
    197   u32 cap;
    198   TypeRecordOpts opts;
    199 };
    200 
    201 TagId type_tag_new(Pool* p, TagDeclKind kind, Sym spelling, SrcLoc loc) {
    202   PoolTypeCache* c = cache_get(p);
    203   if (!c) return TAG_NONE;
    204   (void)kind;
    205   (void)spelling;
    206   (void)loc;
    207   return (TagId)(c->next_tag++);
    208 }
    209 
    210 const TagDecl* type_tag_get(Pool* p, TagId id) {
    211   (void)p;
    212   (void)id;
    213   /* TagDecl table is parser-territory; not modeled in v1. */
    214   return NULL;
    215 }
    216 
    217 TypeRecordBuilder* type_record_begin(Pool* p, TypeKind kind, TagId tag_id,
    218                                      Sym tag) {
    219   TypeRecordOpts opts;
    220   memset(&opts, 0, sizeof opts);
    221   return type_record_begin_ex(p, kind, tag_id, tag, opts);
    222 }
    223 
    224 TypeRecordBuilder* type_record_begin_ex(Pool* p, TypeKind kind, TagId tag_id,
    225                                         Sym tag, TypeRecordOpts opts) {
    226   TypeRecordBuilder* b = arena_new(p->arena, TypeRecordBuilder);
    227   if (!b) return NULL;
    228   memset(b, 0, sizeof *b);
    229   b->pool = p;
    230   b->kind = kind;
    231   b->tag_id = tag_id;
    232   b->tag = tag;
    233   b->opts = opts;
    234   return b;
    235 }
    236 
    237 void type_record_field(TypeRecordBuilder* b, Field f) {
    238   if (b->nfields == b->cap) {
    239     u32 nc = b->cap ? b->cap * 2 : 4;
    240     Field* nf = arena_array(b->pool->arena, Field, nc);
    241     if (!nf) return;
    242     if (b->fields) memcpy(nf, b->fields, sizeof(Field) * b->nfields);
    243     b->fields = nf;
    244     b->cap = nc;
    245   }
    246   b->fields[b->nfields++] = f;
    247 }
    248 
    249 const Type* type_record_end(Pool* p, TypeRecordBuilder* b) {
    250   PoolTypeCache* c = cache_get(p);
    251   if (!c) return NULL;
    252   Type* t = alloc_type_node(p, c);
    253   if (!t) return NULL;
    254   t->kind = (u16)b->kind;
    255   t->qual = 0;
    256   t->rec.tag_id = b->tag_id;
    257   t->rec.tag = b->tag;
    258   t->rec.fields = b->fields;
    259   t->rec.nfields = (u16)b->nfields;
    260   t->rec.incomplete = 0;
    261   t->rec.packed = b->opts.packed;
    262   t->rec.max_align = b->opts.max_align;
    263   t->rec.align_override = b->opts.align_override;
    264   return t;
    265 }
    266 
    267 Type* type_record_forward(Pool* p, TypeKind kind, TagId tag_id, Sym tag) {
    268   PoolTypeCache* c = cache_get(p);
    269   if (!c) return NULL;
    270   Type* t = alloc_type_node(p, c);
    271   if (!t) return NULL;
    272   t->kind = (u16)kind;
    273   t->qual = 0;
    274   t->rec.tag_id = tag_id;
    275   t->rec.tag = tag;
    276   t->rec.fields = NULL;
    277   t->rec.nfields = 0;
    278   t->rec.incomplete = 1;
    279   t->rec.packed = 0;
    280   t->rec.max_align = 0;
    281   t->rec.align_override = 0;
    282   return t;
    283 }
    284 
    285 void type_record_install(Type* forward, const Field* fields, u16 nfields) {
    286   if (!forward) return;
    287   forward->rec.fields = fields;
    288   forward->rec.nfields = nfields;
    289   forward->rec.incomplete = 0;
    290 }
    291 
    292 const Type* type_enum(Pool* p, TagId tag_id, Sym tag, const Type* base) {
    293   PoolTypeCache* c = cache_get(p);
    294   if (!c) return NULL;
    295   Type* t = alloc_type_node(p, c);
    296   if (!t) return NULL;
    297   t->kind = TY_ENUM;
    298   t->qual = 0;
    299   t->enm.tag_id = tag_id;
    300   t->enm.tag = tag;
    301   t->enm.base = base;
    302   return t;
    303 }
    304 
    305 /* ---- predicates / utilities ---- */
    306 
    307 const Type* type_unqual(Pool* p, const Type* t) {
    308   PoolTypeCache* c;
    309   Type tmpl;
    310   Type* nt;
    311   if (!t || t->qual == 0) return t;
    312   if ((unsigned)t->kind < NUM_PRIM_KINDS)
    313     return type_prim(p, (TypeKind)t->kind);
    314   c = cache_get(p);
    315   if (!c) return NULL;
    316   if ((t->kind == TY_STRUCT || t->kind == TY_UNION) &&
    317       t->rec.tag_id != TAG_NONE) {
    318     for (TypeListNode* n = c->derived; n; n = n->next) {
    319       if (n->ty.kind == t->kind && n->ty.qual == 0 &&
    320           n->ty.rec.tag_id == t->rec.tag_id && !n->ty.rec.incomplete) {
    321         return &n->ty;
    322       }
    323     }
    324   }
    325   tmpl = *t;
    326   tmpl.qual = 0;
    327   for (TypeListNode* n = c->derived; n; n = n->next) {
    328     if (memcmp(&n->ty, &tmpl, sizeof(Type)) == 0) return &n->ty;
    329   }
    330   nt = alloc_type_node(p, c);
    331   if (!nt) return NULL;
    332   *nt = tmpl;
    333   return nt;
    334 }
    335 
    336 const Type* type_promoted(Pool* p, const Type* t) {
    337   if (!t) return t;
    338   switch (t->kind) {
    339     case TY_BOOL:
    340     case TY_CHAR:
    341     case TY_SCHAR:
    342     case TY_UCHAR:
    343     case TY_SHORT:
    344     case TY_USHORT:
    345       return type_prim(p, TY_INT);
    346     default:
    347       return t;
    348   }
    349 }
    350 
    351 static int type_compatible_inner(const Type* a, const Type* b, unsigned depth) {
    352   u16 i;
    353   if (depth > 64) return 0;
    354   if (a == b) return 1;
    355   if (!a || !b) return 0;
    356   if (a->qual != b->qual) return 0;
    357   if (a->kind != b->kind) return 0;
    358   switch (a->kind) {
    359     case TY_VOID:
    360     case TY_BOOL:
    361     case TY_CHAR:
    362     case TY_SCHAR:
    363     case TY_UCHAR:
    364     case TY_SHORT:
    365     case TY_USHORT:
    366     case TY_INT:
    367     case TY_UINT:
    368     case TY_LONG:
    369     case TY_ULONG:
    370     case TY_LLONG:
    371     case TY_ULLONG:
    372     case TY_INT128:
    373     case TY_UINT128:
    374     case TY_FLOAT:
    375     case TY_DOUBLE:
    376     case TY_LDOUBLE:
    377       return 1;
    378     case TY_PTR:
    379       return type_compatible_inner(a->ptr.pointee, b->ptr.pointee, depth + 1);
    380     case TY_ARRAY:
    381       if (!type_compatible_inner(a->arr.elem, b->arr.elem, depth + 1)) return 0;
    382       if (a->arr.incomplete || b->arr.incomplete) return 1;
    383       return a->arr.count == b->arr.count;
    384     case TY_FUNC:
    385       if (a->fn.variadic != b->fn.variadic) return 0;
    386       if (a->fn.nparams != b->fn.nparams) return 0;
    387       if (!type_compatible_inner(a->fn.ret, b->fn.ret, depth + 1)) return 0;
    388       for (i = 0; i < a->fn.nparams; ++i) {
    389         if (!type_compatible_inner(a->fn.params[i], b->fn.params[i], depth + 1))
    390           return 0;
    391       }
    392       return 1;
    393     case TY_STRUCT:
    394     case TY_UNION:
    395       return a->rec.tag_id != TAG_NONE && a->rec.tag_id == b->rec.tag_id;
    396     case TY_ENUM:
    397       if (a->enm.tag_id != TAG_NONE || b->enm.tag_id != TAG_NONE)
    398         return a->enm.tag_id == b->enm.tag_id;
    399       return type_compatible_inner(a->enm.base, b->enm.base, depth + 1);
    400     default:
    401       return 0;
    402   }
    403 }
    404 
    405 int type_compatible(const Type* a, const Type* b) {
    406   return type_compatible_inner(a, b, 0);
    407 }
    408 
    409 const Type* type_composite(Pool* p, const Type* a, const Type* b) {
    410   const Type* elem;
    411   const Type** params;
    412   u16 i;
    413   if (!type_compatible(a, b)) return NULL;
    414   if (a == b) return a;
    415   if (!a || !b) return NULL;
    416   switch (a->kind) {
    417     case TY_ARRAY:
    418       elem = type_composite(p, a->arr.elem, b->arr.elem);
    419       if (!elem) elem = a->arr.elem;
    420       if (a->arr.incomplete && !b->arr.incomplete)
    421         return type_array(p, elem, b->arr.count, 0);
    422       if (b->arr.incomplete && !a->arr.incomplete)
    423         return type_array(p, elem, a->arr.count, 0);
    424       return type_array(p, elem, a->arr.count, a->arr.incomplete);
    425     case TY_PTR: {
    426       const Type* pointee = type_composite(p, a->ptr.pointee, b->ptr.pointee);
    427       if (!pointee) pointee = a->ptr.pointee;
    428       /* Preserve the pointer's own qualifiers (e.g. the inner `const` of
    429        * `const char* const*`); type_ptr alone yields an unqualified pointer. */
    430       return type_qualified(p, type_ptr(p, pointee), a->qual);
    431     }
    432     case TY_FUNC:
    433       if (a->fn.nparams == 0) return a;
    434       params = arena_array(p->arena, const Type*, a->fn.nparams);
    435       if (!params) return NULL;
    436       for (i = 0; i < a->fn.nparams; ++i) {
    437         params[i] = type_composite(p, a->fn.params[i], b->fn.params[i]);
    438         if (!params[i]) params[i] = a->fn.params[i];
    439       }
    440       return type_func(p, type_composite(p, a->fn.ret, b->fn.ret), params,
    441                        a->fn.nparams, a->fn.variadic);
    442     default:
    443       return a;
    444   }
    445 }
    446 
    447 /* Single source of truth for per-TypeKind scalar facts. Indexed directly by
    448  * TypeKind (sized to TY_ENUM + 1); the aggregate kinds PTR/ARRAY/FUNC/STRUCT/
    449  * UNION are zero-filled holes. Columns:
    450  *   is_signed  - signed integer (drives sign-extension / signed cg ops)
    451  *   is_int     - integer type (bool/char/.../enum)
    452  *   is_fp      - floating-point type
    453  *   rank       - C integer conversion rank (0 for non-integers)
    454  *   uvariant   - corresponding unsigned TypeKind (TY_UINT for non-integers,
    455  *                matching the historical default)
    456  * Accessors below read this table instead of re-enumerating the kinds. */
    457 typedef struct TypeKindProps {
    458   u8 is_signed;
    459   u8 is_int;
    460   u8 is_fp;
    461   u8 rank;
    462   u8 uvariant; /* TypeKind */
    463 } TypeKindProps;
    464 
    465 static const TypeKindProps kTypeKindProps[TY_ENUM + 1] = {
    466     [TY_VOID] = {0, 0, 0, 0, TY_UINT},
    467     [TY_BOOL] = {0, 1, 0, 1, TY_UINT},
    468     [TY_CHAR] = {1, 1, 0, 2, TY_UINT},
    469     [TY_SCHAR] = {1, 1, 0, 2, TY_UINT},
    470     [TY_UCHAR] = {0, 1, 0, 2, TY_UINT},
    471     [TY_SHORT] = {1, 1, 0, 3, TY_UINT},
    472     [TY_USHORT] = {0, 1, 0, 3, TY_UINT},
    473     [TY_INT] = {1, 1, 0, 4, TY_UINT},
    474     [TY_UINT] = {0, 1, 0, 4, TY_UINT},
    475     [TY_LONG] = {1, 1, 0, 5, TY_ULONG},
    476     [TY_ULONG] = {0, 1, 0, 5, TY_ULONG},
    477     [TY_LLONG] = {1, 1, 0, 6, TY_ULLONG},
    478     [TY_ULLONG] = {0, 1, 0, 6, TY_ULLONG},
    479     [TY_INT128] = {1, 1, 0, 7, TY_UINT128},
    480     [TY_UINT128] = {0, 1, 0, 7, TY_UINT128},
    481     [TY_FLOAT] = {0, 0, 1, 0, TY_UINT},
    482     [TY_DOUBLE] = {0, 0, 1, 0, TY_UINT},
    483     [TY_LDOUBLE] = {0, 0, 1, 0, TY_UINT},
    484     /* PTR/ARRAY/FUNC/STRUCT/UNION: zero-filled holes (uvariant 0 == TY_VOID
    485      * is never read for non-integers; callers map non-int to TY_UINT). */
    486     [TY_ENUM] = {1, 1, 0, 4, TY_UINT},
    487 };
    488 
    489 static const TypeKindProps* type_kind_props(TypeKind k) {
    490   if ((unsigned)k > (unsigned)TY_ENUM) return &kTypeKindProps[TY_VOID];
    491   return &kTypeKindProps[k];
    492 }
    493 
    494 int type_kind_is_int(TypeKind k) { return type_kind_props(k)->is_int; }
    495 int type_kind_is_fp(TypeKind k) { return type_kind_props(k)->is_fp; }
    496 int type_kind_is_signed_integer(TypeKind k) {
    497   return type_kind_props(k)->is_signed;
    498 }
    499 u32 type_kind_int_rank(TypeKind k) { return type_kind_props(k)->rank; }
    500 TypeKind type_kind_unsigned_variant(TypeKind k) {
    501   const TypeKindProps* p = type_kind_props(k);
    502   return p->is_int ? (TypeKind)p->uvariant : TY_UINT;
    503 }
    504 
    505 int type_is_int(const Type* t) {
    506   return t ? type_kind_is_int((TypeKind)t->kind) : 0;
    507 }
    508 
    509 int type_is_arith(const Type* t) {
    510   if (!t) return 0;
    511   return type_kind_is_int((TypeKind)t->kind) ||
    512          type_kind_is_fp((TypeKind)t->kind);
    513 }
    514 
    515 int type_is_ptr(const Type* t) { return t && t->kind == TY_PTR; }
    516 
    517 int type_is_signed_integer(const Type* t) {
    518   return t ? type_kind_is_signed_integer((TypeKind)t->kind) : 0;
    519 }
    520 
    521 static KitCgTypeId type_cg_builtin(KitCompiler* c, TypeKind kind) {
    522   KitCgBuiltinTypes b = kit_cg_builtin_types(c);
    523   KitTargetSpec target = kit_compiler_target_spec(c);
    524   switch (kind) {
    525     case TY_VOID:
    526       return b.id[KIT_CG_BUILTIN_VOID];
    527     case TY_BOOL:
    528       return b.id[KIT_CG_BUILTIN_BOOL];
    529     case TY_CHAR:
    530     case TY_SCHAR:
    531     case TY_UCHAR:
    532       return b.id[KIT_CG_BUILTIN_I8];
    533     case TY_SHORT:
    534     case TY_USHORT:
    535       return b.id[KIT_CG_BUILTIN_I16];
    536     case TY_INT:
    537     case TY_UINT:
    538       return b.id[KIT_CG_BUILTIN_I32];
    539     case TY_LONG:
    540     case TY_ULONG:
    541       return b.id[kit_target_uses_lp64(target) ? KIT_CG_BUILTIN_I64
    542                                                : KIT_CG_BUILTIN_I32];
    543     case TY_LLONG:
    544     case TY_ULLONG:
    545       return b.id[KIT_CG_BUILTIN_I64];
    546     case TY_INT128:
    547     case TY_UINT128:
    548       return b.id[KIT_CG_BUILTIN_I128];
    549     case TY_FLOAT:
    550       return b.id[KIT_CG_BUILTIN_F32];
    551     case TY_DOUBLE:
    552       return b.id[KIT_CG_BUILTIN_F64];
    553     case TY_LDOUBLE:
    554       /* `long double` is IEEE-754 binary128 on targets that follow the quad
    555        * psABI (RISC-V, aarch64-linux, wasm32); elsewhere it aliases `double`.
    556        * See kit_target_long_double_is_binary128. */
    557       if (kit_target_long_double_is_binary128(target))
    558         return b.id[KIT_CG_BUILTIN_F128];
    559       return b.id[KIT_CG_BUILTIN_F64];
    560     default:
    561       break;
    562   }
    563   return KIT_CG_TYPE_NONE;
    564 }
    565 
    566 static int same_record_type(const Type* a, const Type* b) {
    567   if (a == b) return 1;
    568   if (!a || !b) return 0;
    569   if (a->kind != b->kind) return 0;
    570   if (a->kind != TY_STRUCT && a->kind != TY_UNION) return 0;
    571   return a->rec.tag_id != TAG_NONE && a->rec.tag_id == b->rec.tag_id;
    572 }
    573 
    574 typedef enum TypeCgMode {
    575   TYPE_CG_VALUE,
    576   TYPE_CG_RECORD_FIELD,
    577 } TypeCgMode;
    578 
    579 typedef struct TypeCgLower {
    580   KitCompiler* c;
    581   Pool* p;
    582   PoolTypeCache* cache;
    583 } TypeCgLower;
    584 
    585 static KitCgTypeId type_cg_lower(TypeCgLower* l, const Type* t,
    586                                  TypeCgMode mode);
    587 
    588 static KitCgTypeId type_cg_record_memo_get(PoolTypeCache* cache, KitCompiler* c,
    589                                            const Type* t) {
    590   if (!cache) return KIT_CG_TYPE_NONE;
    591   for (CgRecordMemo* m = cache->cg_record_memos; m; m = m->next) {
    592     if (m->compiler == c && (m->type == t || same_record_type(m->type, t))) {
    593       return m->id;
    594     }
    595   }
    596   return KIT_CG_TYPE_NONE;
    597 }
    598 
    599 static void type_cg_record_memo_put(Pool* p, PoolTypeCache* cache,
    600                                     KitCompiler* c, const Type* t,
    601                                     KitCgTypeId id) {
    602   CgRecordMemo* m;
    603   if (!p || !cache || !c || !t || id == KIT_CG_TYPE_NONE) return;
    604   if (t->kind != TY_STRUCT && t->kind != TY_UNION) return;
    605   if (t->rec.incomplete) return;
    606   for (m = cache->cg_record_memos; m; m = m->next) {
    607     if (m->compiler == c && (m->type == t || same_record_type(m->type, t))) {
    608       m->id = id;
    609       return;
    610     }
    611   }
    612   m = arena_new(p->arena, CgRecordMemo);
    613   if (!m) return;
    614   m->compiler = c;
    615   m->type = t;
    616   m->id = id;
    617   m->next = cache->cg_record_memos;
    618   cache->cg_record_memos = m;
    619 }
    620 
    621 static KitCgTypeId type_cg_record_layout(TypeCgLower* l, const Type* t) {
    622   KitCgField* fields = NULL;
    623   KitCgRecordDesc desc;
    624   KitCgTypeId id;
    625   if (!l || !t || (t->kind != TY_STRUCT && t->kind != TY_UNION)) {
    626     return KIT_CG_TYPE_NONE;
    627   }
    628   if (t->rec.incomplete) return type_cg_builtin(l->c, TY_VOID);
    629   id = type_cg_record_memo_get(l->cache, l->c, t);
    630   if (id != KIT_CG_TYPE_NONE) return id;
    631   if (t->rec.nfields) {
    632     fields = arena_zarray(l->p->arena, KitCgField, t->rec.nfields);
    633     if (!fields) return KIT_CG_TYPE_NONE;
    634     for (u32 i = 0; i < t->rec.nfields; ++i) {
    635       fields[i].name = t->rec.fields[i].name;
    636       fields[i].type =
    637           type_cg_lower(l, t->rec.fields[i].type, TYPE_CG_RECORD_FIELD);
    638       fields[i].align_override = t->rec.fields[i].align_override;
    639       fields[i].max_align = t->rec.fields[i].max_align;
    640       if (t->rec.max_align &&
    641           (fields[i].max_align == 0 || t->rec.max_align < fields[i].max_align))
    642         fields[i].max_align = t->rec.max_align;
    643       if (t->rec.fields[i].flags & FIELD_BITFIELD) {
    644         fields[i].flags |= KIT_CG_FIELD_BITFIELD;
    645         fields[i].bit_width = t->rec.fields[i].bitfield_width;
    646         fields[i].bit_signed =
    647             type_is_signed_integer(t->rec.fields[i].type);
    648         if (t->rec.fields[i].flags & FIELD_ZERO_WIDTH) {
    649           fields[i].flags |= KIT_CG_FIELD_ZERO_WIDTH;
    650         }
    651       }
    652       if (t->rec.fields[i].packed && fields[i].align_override == 0) {
    653         fields[i].align_override = 1;
    654       }
    655       if (t->rec.packed && fields[i].align_override == 0) {
    656         fields[i].align_override = 1;
    657       }
    658     }
    659   }
    660   memset(&desc, 0, sizeof desc);
    661   desc.tag = t->rec.tag;
    662   desc.fields = fields;
    663   desc.nfields = t->rec.nfields;
    664   desc.is_union = t->kind == TY_UNION;
    665   desc.align_override = t->rec.align_override;
    666   id = kit_cg_type_record_ex(l->c, &desc);
    667   type_cg_record_memo_put(l->p, l->cache, l->c, t, id);
    668   return id;
    669 }
    670 
    671 static KitCgTypeId type_cg_lower(TypeCgLower* l, const Type* t,
    672                                  TypeCgMode mode) {
    673   KitCgTypeId id;
    674   if (!l || !t) return KIT_CG_TYPE_NONE;
    675   id = type_cg_builtin(l->c, (TypeKind)t->kind);
    676   if (id != KIT_CG_TYPE_NONE) return id;
    677   switch ((TypeKind)t->kind) {
    678     case TY_PTR:
    679       if (mode == TYPE_CG_RECORD_FIELD) {
    680         return kit_cg_type_ptr(l->c, type_cg_builtin(l->c, TY_VOID), 0);
    681       }
    682       return kit_cg_type_ptr(
    683           l->c, type_cg_lower(l, t->ptr.pointee, TYPE_CG_VALUE), 0);
    684     case TY_ARRAY:
    685       return kit_cg_type_array(l->c, type_cg_lower(l, t->arr.elem, mode),
    686                                t->arr.count);
    687     case TY_FUNC: {
    688       KitCgFuncParam* params = NULL;
    689       KitCgFuncSig sig;
    690       memset(&sig, 0, sizeof sig);
    691       if (t->fn.ret->kind != TY_VOID)
    692         sig.result.type = type_cg_lower(l, t->fn.ret, TYPE_CG_VALUE);
    693       sig.nparams = t->fn.nparams;
    694       sig.abi_variadic = t->fn.variadic;
    695       sig.call_conv = KIT_CG_CC_TARGET_C;
    696       if (t->fn.nparams) {
    697         params = arena_zarray(l->p->arena, KitCgFuncParam, t->fn.nparams);
    698         if (!params) return KIT_CG_TYPE_NONE;
    699         for (u32 i = 0; i < t->fn.nparams; ++i) {
    700           params[i].type =
    701               type_cg_lower(l, t->fn.params[i], TYPE_CG_RECORD_FIELD);
    702         }
    703       }
    704       sig.params = params;
    705       return kit_cg_type_func(l->c, sig);
    706     }
    707     case TY_STRUCT:
    708     case TY_UNION:
    709       return type_cg_record_layout(l, t);
    710     case TY_ENUM:
    711       return kit_cg_type_enum(l->c, t->enm.tag,
    712                               type_cg_lower(l, t->enm.base, mode), NULL, 0);
    713     default:
    714       return KIT_CG_TYPE_NONE;
    715   }
    716 }
    717 
    718 KitCgTypeId type_cg_id_in_pool(KitCompiler* c, Pool* p, const Type* t) {
    719   TypeCgLower l;
    720   if (!p) return KIT_CG_TYPE_NONE;
    721   memset(&l, 0, sizeof l);
    722   l.c = c;
    723   l.p = p;
    724   l.cache = cache_get(p);
    725   return type_cg_lower(&l, t, TYPE_CG_VALUE);
    726 }
    727 
    728 KitCgTypeId type_cg_id(KitCompiler* c, const Type* t) {
    729   KitCgTypeId id;
    730   Pool* p = c_pool_new(c);
    731   if (!p) return KIT_CG_TYPE_NONE;
    732   id = type_cg_id_in_pool(c, p, t);
    733   c_pool_free(p);
    734   return id;
    735 }