kit

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

types.c (33668B)


      1 #include <string.h>
      2 
      3 #include "internal.h"
      4 
      5 static ToyType* toy_type_slot(ToyParser* p, ToyTypeId id) {
      6   if (id == TOY_TYPE_NONE || id > p->module->type_table.ntypes) return NULL;
      7   return &p->module->type_table.types[id - 1u];
      8 }
      9 
     10 static ToyTypeId toy_type_find(ToyParser* p, const ToyType* key) {
     11   size_t i;
     12   for (i = 0; i < p->module->type_table.ntypes; ++i) {
     13     ToyType* ty = &p->module->type_table.types[i];
     14     if (ty->kind == key->kind && ty->cg == key->cg && ty->name == key->name &&
     15         ty->base == key->base && ty->elem == key->elem &&
     16         ty->pointee == key->pointee && ty->ret == key->ret &&
     17         ty->count == key->count && ty->address_space == key->address_space &&
     18         ty->quals == key->quals && ty->nparams == key->nparams &&
     19         ty->variadic == key->variadic) {
     20       size_t j;
     21       for (j = 0; j < key->nparams; ++j) {
     22         if (ty->params[j] != key->params[j]) break;
     23       }
     24       if (j == key->nparams) return (ToyTypeId)(i + 1u);
     25     }
     26   }
     27   return TOY_TYPE_NONE;
     28 }
     29 
     30 static ToyTypeId toy_type_add(ToyParser* p, const ToyType* type) {
     31   ToyTypeId existing = toy_type_find(p, type);
     32   if (existing != TOY_TYPE_NONE) return existing;
     33   if (!toy_parser_reserve(p, (void**)&p->module->type_table.types,
     34                           &p->module->type_table.cap_types,
     35                           p->module->type_table.ntypes + 1u,
     36                           sizeof *p->module->type_table.types, "toy types")) {
     37     return TOY_TYPE_NONE;
     38   }
     39   p->module->type_table.types[p->module->type_table.ntypes] = *type;
     40   p->module->type_table.ntypes++;
     41   return (ToyTypeId)p->module->type_table.ntypes;
     42 }
     43 
     44 static ToyTypeId toy_type_register(ToyParser* p, ToyTypeKind kind,
     45                                    KitCgTypeId cg, KitSym name,
     46                                    ToyTypeId base) {
     47   ToyType type;
     48   memset(&type, 0, sizeof type);
     49   type.kind = kind;
     50   type.cg = cg;
     51   type.name = name;
     52   type.base = base;
     53   return toy_type_add(p, &type);
     54 }
     55 
     56 static ToyTypeId toy_type_register_array(ToyParser* p, KitCgTypeId cg,
     57                                          ToyTypeId elem, uint64_t count) {
     58   ToyType type;
     59   memset(&type, 0, sizeof type);
     60   type.kind = TOY_TYPE_ARRAY;
     61   type.cg = cg;
     62   type.elem = elem;
     63   type.count = count;
     64   return toy_type_add(p, &type);
     65 }
     66 
     67 static KitCgTypeId toy_type_finish(ToyParser* p, KitCgTypeId cg,
     68                                    ToyTypeId toy_type) {
     69   p->last_type = toy_type;
     70   return cg;
     71 }
     72 
     73 KitCgTypeId toy_parse_type(ToyParser* p) {
     74   if (p->cur.kind == TOK_IDENT &&
     75       ((p->cur.text_len == 5 && memcmp(p->cur.text, "const", 5) == 0) ||
     76        (p->cur.text_len == 8 && memcmp(p->cur.text, "volatile", 8) == 0) ||
     77        (p->cur.text_len == 8 && memcmp(p->cur.text, "restrict", 8) == 0))) {
     78     int is_restrict =
     79         p->cur.text_len == 8 && memcmp(p->cur.text, "restrict", 8) == 0;
     80     uint32_t qual = is_restrict              ? TOY_TYPE_QUAL_RESTRICT
     81                     : (p->cur.text_len == 5) ? TOY_TYPE_QUAL_CONST
     82                                              : TOY_TYPE_QUAL_VOLATILE;
     83     KitCgTypeId qualified_ty;
     84     toy_parser_advance(p);
     85     qualified_ty = toy_parse_type(p);
     86     if (is_restrict &&
     87         kit_cg_type_kind(p->c, qualified_ty) != KIT_CG_TYPE_PTR) {
     88       toy_error(p, p->cur.loc, "restrict requires pointer type");
     89       return KIT_CG_TYPE_NONE;
     90     }
     91     return toy_type_finish(
     92         p, qualified_ty,
     93         toy_type_register_qualified(p, qualified_ty, qualified_ty, qual));
     94   }
     95   if (toy_parser_match(p, TOK_FN)) {
     96     KitCgTypeId* param_types = NULL;
     97     KitCgFuncParam* sig_params = NULL;
     98     KitCgFuncSig sig;
     99     KitCgTypeId ret_type;
    100     ToyTypeId ret_toy_type;
    101     KitCgTypeId result = KIT_CG_TYPE_NONE;
    102     size_t nparams = 0;
    103     size_t cap_param_types = 0;
    104     ToyTypeId* param_toy_types = NULL;
    105     size_t cap_param_toy_types = 0;
    106     size_t cap_sig_params = 0;
    107     int variadic = 0;
    108     size_t i;
    109 
    110     if (!toy_parser_expect(p, TOK_LPAREN)) {
    111       toy_error(p, p->cur.loc, "expected '(' after function type");
    112       goto fn_done;
    113     }
    114     if (p->cur.kind != TOK_RPAREN) {
    115       for (;;) {
    116         if (p->cur.kind == TOK_DOTDOTDOT) {
    117           variadic = 1;
    118           toy_parser_advance(p);
    119           break;
    120         }
    121         if (!toy_parser_reserve(p, (void**)&param_types, &cap_param_types,
    122                                 nparams + 1u, sizeof *param_types,
    123                                 "function type parameters") ||
    124             !toy_parser_reserve(
    125                 p, (void**)&param_toy_types, &cap_param_toy_types, nparams + 1u,
    126                 sizeof *param_toy_types, "function type source parameters") ||
    127             !toy_parser_reserve(p, (void**)&sig_params, &cap_sig_params,
    128                                 nparams + 1u, sizeof *sig_params,
    129                                 "function type signature parameters")) {
    130           goto fn_done;
    131         }
    132         param_types[nparams] = toy_parse_type(p);
    133         if (param_types[nparams] == KIT_CG_TYPE_NONE) goto fn_done;
    134         param_toy_types[nparams] = p->last_type;
    135         nparams++;
    136         if (p->cur.kind == TOK_COMMA) {
    137           toy_parser_advance(p);
    138           if (p->cur.kind == TOK_DOTDOTDOT) {
    139             variadic = 1;
    140             toy_parser_advance(p);
    141             break;
    142           }
    143         } else {
    144           break;
    145         }
    146       }
    147     }
    148     if (!toy_parser_expect(p, TOK_RPAREN)) {
    149       toy_error(p, p->cur.loc, "expected ')' after function type parameters");
    150       goto fn_done;
    151     }
    152     if (!toy_parser_expect(p, TOK_COLON)) {
    153       toy_error(p, p->cur.loc, "expected ':' before function return type");
    154       goto fn_done;
    155     }
    156     ret_type = toy_parse_type(p);
    157     if (ret_type == KIT_CG_TYPE_NONE) goto fn_done;
    158     ret_toy_type = p->last_type;
    159 
    160     for (i = 0; i < nparams; i++) sig_params[i].type = param_types[i];
    161     memset(&sig, 0, sizeof sig);
    162     sig.result.type = ret_type;
    163     sig.params = sig_params;
    164     sig.nparams = (uint32_t)nparams;
    165     sig.call_conv = KIT_CG_CC_TARGET_C;
    166     sig.abi_variadic = variadic;
    167     {
    168       KitCgTypeId fn_ty = kit_cg_type_func(p->c, sig);
    169       result = toy_type_finish(
    170           p, fn_ty,
    171           toy_type_register_func(p, fn_ty, ret_toy_type, param_toy_types,
    172                                  nparams, variadic));
    173     }
    174   fn_done:
    175     toy_parser_free_mem(p, param_types, cap_param_types * sizeof *param_types);
    176     toy_parser_free_mem(p, param_toy_types,
    177                         cap_param_toy_types * sizeof *param_toy_types);
    178     toy_parser_free_mem(p, sig_params, cap_sig_params * sizeof *sig_params);
    179     return result;
    180   }
    181   if (toy_parser_match(p, TOK_LBRACKET)) {
    182     uint64_t count;
    183     KitCgTypeId elem;
    184     ToyTypeId elem_toy_type;
    185     if (toy_parser_match(p, TOK_RBRACKET)) {
    186       ToyTypeId slice_toy_type;
    187       elem = toy_parse_type(p);
    188       if (elem == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE;
    189       elem_toy_type = p->last_type;
    190       slice_toy_type = toy_type_register_slice(p, elem, elem_toy_type);
    191       return toy_type_finish(p, toy_type_cg(p, slice_toy_type), slice_toy_type);
    192     }
    193     if (p->cur.kind != TOK_NUMBER || p->cur.is_float || p->cur.int_value < 0) {
    194       toy_error(p, p->cur.loc, "expected array count");
    195       return KIT_CG_TYPE_NONE;
    196     }
    197     count = (uint64_t)p->cur.int_value;
    198     toy_parser_advance(p);
    199     if (!toy_parser_expect(p, TOK_RBRACKET)) {
    200       toy_error(p, p->cur.loc, "expected ']' after array count");
    201       return KIT_CG_TYPE_NONE;
    202     }
    203     elem = toy_parse_type(p);
    204     if (elem == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE;
    205     elem_toy_type = p->last_type;
    206     {
    207       KitCgTypeId array_ty = kit_cg_type_array(p->c, elem, count);
    208       return toy_type_finish(
    209           p, array_ty,
    210           toy_type_register_array(p, array_ty, elem_toy_type, count));
    211     }
    212   }
    213   if (toy_parser_match(p, TOK_RECORD)) {
    214     KitCgFieldDesc* fields = NULL;
    215     size_t nfields = 0;
    216     size_t cap_fields = 0;
    217     int packed = 0;
    218     uint32_t record_align = 0;
    219     KitCgTypeId result = KIT_CG_TYPE_NONE;
    220     if (!toy_parse_record_attr_list(p, &packed, &record_align))
    221       return KIT_CG_TYPE_NONE;
    222     if (!toy_parser_expect(p, TOK_LBRACE)) {
    223       toy_error(p, p->cur.loc, "expected '{' after record type");
    224       goto record_done;
    225     }
    226     while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) {
    227       if (!toy_parser_reserve(p, (void**)&fields, &cap_fields, nfields + 1u,
    228                               sizeof *fields, "record type fields")) {
    229         goto record_done;
    230       }
    231       if (p->cur.kind != TOK_IDENT) {
    232         toy_error(p, p->cur.loc, "expected record field name");
    233         goto record_done;
    234       }
    235       fields[nfields].name = toy_tok_sym(p, p->cur);
    236       toy_parser_advance(p);
    237       if (!toy_parse_field_attr_list(p, &fields[nfields])) goto record_done;
    238       if (!toy_parser_expect(p, TOK_COLON)) {
    239         toy_error(p, p->cur.loc, "expected ':' after record field name");
    240         goto record_done;
    241       }
    242       fields[nfields].type = toy_parse_type(p);
    243       if (fields[nfields].type == KIT_CG_TYPE_NONE) goto record_done;
    244       nfields++;
    245       if (!toy_parser_match(p, TOK_COMMA)) break;
    246     }
    247     if (!toy_parser_expect(p, TOK_RBRACE)) {
    248       toy_error(p, p->cur.loc, "expected '}' after record type");
    249       goto record_done;
    250     }
    251     if (packed) {
    252       size_t i;
    253       for (i = 0; i < nfields; ++i) {
    254         if (!fields[i].align_override) fields[i].align_override = 1;
    255       }
    256     }
    257     {
    258       KitCgTypeId record_ty =
    259           toy_cg_record_type(p, 0, fields, (uint32_t)nfields, 0, record_align);
    260       result = toy_type_finish(p, record_ty, toy_type_from_cg(p, record_ty));
    261     }
    262   record_done:
    263     toy_parser_free_mem(p, fields, cap_fields * sizeof *fields);
    264     return result;
    265   }
    266   if (p->cur.kind == TOK_INT) {
    267     toy_error(p, p->cur.loc,
    268               "legacy int type is unsupported; use an explicit scalar type");
    269     return KIT_CG_TYPE_NONE;
    270   }
    271   if (p->cur.kind == TOK_IDENT) {
    272     KitCgTypeId ty = KIT_CG_TYPE_NONE;
    273     if (p->cur.text_len == 4 && memcmp(p->cur.text, "void", 4) == 0)
    274       ty = toy_builtin_type(p, KIT_CG_BUILTIN_VOID);
    275     else if (p->cur.text_len == 4 && memcmp(p->cur.text, "bool", 4) == 0)
    276       ty = toy_builtin_type(p, KIT_CG_BUILTIN_BOOL);
    277     else if (p->cur.text_len == 2 && p->cur.text[0] == 'i' &&
    278              p->cur.text[1] == '8')
    279       ty = toy_builtin_type(p, KIT_CG_BUILTIN_I8);
    280     else if (p->cur.text_len == 2 && p->cur.text[0] == 'u' &&
    281              p->cur.text[1] == '8')
    282       ty = toy_builtin_type(p, KIT_CG_BUILTIN_I8);
    283     else if (p->cur.text_len == 3 && p->cur.text[0] == 'i' &&
    284              p->cur.text[1] == '1' && p->cur.text[2] == '6')
    285       ty = toy_builtin_type(p, KIT_CG_BUILTIN_I16);
    286     else if (p->cur.text_len == 3 && p->cur.text[0] == 'u' &&
    287              p->cur.text[1] == '1' && p->cur.text[2] == '6')
    288       ty = toy_builtin_type(p, KIT_CG_BUILTIN_I16);
    289     else if (p->cur.text_len == 3 && p->cur.text[0] == 'i' &&
    290              p->cur.text[1] == '3' && p->cur.text[2] == '2')
    291       ty = toy_builtin_type(p, KIT_CG_BUILTIN_I32);
    292     else if (p->cur.text_len == 3 && p->cur.text[0] == 'u' &&
    293              p->cur.text[1] == '3' && p->cur.text[2] == '2')
    294       ty = toy_builtin_type(p, KIT_CG_BUILTIN_I32);
    295     else if (p->cur.text_len == 3 && p->cur.text[0] == 'i' &&
    296              p->cur.text[1] == '6' && p->cur.text[2] == '4')
    297       ty = toy_builtin_type(p, KIT_CG_BUILTIN_I64);
    298     else if (p->cur.text_len == 3 && p->cur.text[0] == 'u' &&
    299              p->cur.text[1] == '6' && p->cur.text[2] == '4')
    300       ty = toy_builtin_type(p, KIT_CG_BUILTIN_I64);
    301     else if (p->cur.text_len == 4 && p->cur.text[0] == 'i' &&
    302              p->cur.text[1] == '1' && p->cur.text[2] == '2' &&
    303              p->cur.text[3] == '8')
    304       ty = toy_builtin_type(p, KIT_CG_BUILTIN_I128);
    305     else if (p->cur.text_len == 4 && p->cur.text[0] == 'u' &&
    306              p->cur.text[1] == '1' && p->cur.text[2] == '2' &&
    307              p->cur.text[3] == '8')
    308       ty = toy_builtin_type(p, KIT_CG_BUILTIN_I128);
    309     else if (p->cur.text_len == 5 && memcmp(p->cur.text, "isize", 5) == 0)
    310       ty = p->size_type;
    311     else if (p->cur.text_len == 5 && memcmp(p->cur.text, "usize", 5) == 0)
    312       ty = p->size_type;
    313     else if (p->cur.text_len == 3 && memcmp(p->cur.text, "f32", 3) == 0)
    314       ty = toy_builtin_type(p, KIT_CG_BUILTIN_F32);
    315     else if (p->cur.text_len == 3 && memcmp(p->cur.text, "f64", 3) == 0)
    316       ty = toy_builtin_type(p, KIT_CG_BUILTIN_F64);
    317     else if (p->cur.text_len == 7 && memcmp(p->cur.text, "va_list", 7) == 0)
    318       ty = p->va_list_type;
    319     else {
    320       ToyNamedType* named = toy_find_named_type(p, toy_tok_sym(p, p->cur));
    321       if (named) {
    322         if (named->type == KIT_CG_TYPE_NONE ||
    323             ((named->kind == TOY_NAMED_RECORD ||
    324               named->kind == TOY_NAMED_TUPLE) &&
    325              !kit_cg_type_is_complete(p->c, named->type))) {
    326           toy_error(p, p->cur.loc, "incomplete record type requires pointer");
    327           return KIT_CG_TYPE_NONE;
    328         }
    329         ty = named->type;
    330       }
    331     }
    332     if (ty != KIT_CG_TYPE_NONE) {
    333       ToyTypeId toy_type = toy_type_from_cg(p, ty);
    334       ToyNamedType* named = (p->cur.kind == TOK_IDENT)
    335                                 ? toy_find_named_type(p, toy_tok_sym(p, p->cur))
    336                                 : NULL;
    337       if (named && named->type == ty && named->toy_type != TOY_TYPE_NONE)
    338         toy_type = named->toy_type;
    339       toy_parser_advance(p);
    340       return toy_type_finish(p, ty, toy_type);
    341     }
    342   }
    343   if (toy_parser_match(p, TOK_STAR)) {
    344     uint32_t address_space = 0;
    345     ToyNamedType* incomplete_pointee = NULL;
    346     if (p->cur.kind == TOK_IDENT && p->cur.text_len == 9 &&
    347         memcmp(p->cur.text, "addrspace", 9) == 0) {
    348       int64_t as_value;
    349       toy_parser_advance(p);
    350       if (!toy_parser_expect(p, TOK_LPAREN) ||
    351           !toy_parse_number_arg(p, &as_value) ||
    352           !toy_parser_expect(p, TOK_RPAREN) || as_value < 0) {
    353         toy_error(p, p->cur.loc, "invalid address space");
    354         return KIT_CG_TYPE_NONE;
    355       }
    356       address_space = (uint32_t)as_value;
    357     }
    358     if (p->cur.kind == TOK_IDENT) {
    359       incomplete_pointee = toy_find_named_type(p, toy_tok_sym(p, p->cur));
    360       if (incomplete_pointee &&
    361           (incomplete_pointee->kind == TOY_NAMED_RECORD ||
    362            incomplete_pointee->kind == TOY_NAMED_TUPLE) &&
    363           incomplete_pointee->type != KIT_CG_TYPE_NONE &&
    364           !kit_cg_type_is_complete(p->c, incomplete_pointee->type)) {
    365         KitCgTypeId ptr_ty;
    366         toy_parser_advance(p);
    367         ptr_ty = kit_cg_type_ptr(p->c, incomplete_pointee->type, address_space);
    368         return toy_type_finish(
    369             p, ptr_ty,
    370             toy_type_register_ptr(p, ptr_ty, incomplete_pointee->toy_type,
    371                                   address_space));
    372       }
    373     }
    374     {
    375       KitCgTypeId pointee = toy_parse_type(p);
    376       ToyTypeId pointee_toy_type;
    377       if (pointee == KIT_CG_TYPE_NONE) {
    378         toy_error(p, p->cur.loc, "expected type after '*'");
    379         return KIT_CG_TYPE_NONE;
    380       }
    381       pointee_toy_type = p->last_type;
    382       {
    383         KitCgTypeId ptr_ty = kit_cg_type_ptr(p->c, pointee, address_space);
    384         return toy_type_finish(
    385             p, ptr_ty,
    386             toy_type_register_ptr(p, ptr_ty, pointee_toy_type, address_space));
    387       }
    388     }
    389   }
    390   toy_error(p, p->cur.loc, "expected type");
    391   return KIT_CG_TYPE_NONE;
    392 }
    393 
    394 int toy_type_is_intlike(ToyParser* p, KitCgTypeId ty) {
    395   KitCgTypeKind k = kit_cg_type_kind(p->c, ty);
    396   return k == KIT_CG_TYPE_INT || k == KIT_CG_TYPE_BOOL || k == KIT_CG_TYPE_ENUM;
    397 }
    398 
    399 int toy_type_is_float(ToyParser* p, KitCgTypeId ty) {
    400   return kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_FLOAT;
    401 }
    402 
    403 int toy_type_is_ptr(ToyParser* p, KitCgTypeId ty) {
    404   return kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_PTR;
    405 }
    406 
    407 uint32_t toy_type_int_width(ToyParser* p, KitCgTypeId ty) {
    408   if (kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_BOOL) return 1;
    409   return kit_cg_type_int_width(p->c, ty);
    410 }
    411 
    412 KitCgTypeId toy_ptr_pointee_func_type(ToyParser* p, KitCgTypeId ptr_ty) {
    413   KitCgTypeId fn_ty;
    414   if (kit_cg_type_kind(p->c, ptr_ty) != KIT_CG_TYPE_PTR)
    415     return KIT_CG_TYPE_NONE;
    416   fn_ty = kit_cg_type_ptr_pointee(p->c, ptr_ty);
    417   if (kit_cg_type_kind(p->c, fn_ty) != KIT_CG_TYPE_FUNC)
    418     return KIT_CG_TYPE_NONE;
    419   return fn_ty;
    420 }
    421 
    422 void toy_type_register_builtins(ToyParser* p) {
    423   size_t i;
    424   for (i = 0; i < KIT_CG_BUILTIN_COUNT; ++i)
    425     (void)toy_type_from_cg(p, toy_builtin_type(p, (KitCgBuiltinType)i));
    426   (void)toy_type_from_cg(p, p->int_ptr_type);
    427 }
    428 
    429 const ToyType* toy_type_get(ToyParser* p, ToyTypeId id) {
    430   return toy_type_slot(p, id);
    431 }
    432 
    433 KitCgTypeId toy_type_cg(ToyParser* p, ToyTypeId id) {
    434   const ToyType* type = toy_type_get(p, id);
    435   return type ? type->cg : KIT_CG_TYPE_NONE;
    436 }
    437 
    438 ToyTypeId toy_type_from_cg(ToyParser* p, KitCgTypeId cg) {
    439   ToyType type;
    440   KitCgTypeKind kind;
    441   size_t i;
    442   if (cg == KIT_CG_TYPE_NONE) return TOY_TYPE_NONE;
    443   for (i = 0; i < p->module->type_table.ntypes; ++i) {
    444     ToyType* existing = &p->module->type_table.types[i];
    445     if (existing->cg == cg && (existing->kind == TOY_TYPE_NOMINAL_RECORD ||
    446                                existing->kind == TOY_TYPE_TUPLE_RECORD ||
    447                                existing->kind == TOY_TYPE_ENUM)) {
    448       return (ToyTypeId)(i + 1u);
    449     }
    450     if (existing->cg == cg && existing->name == 0 &&
    451         (existing->kind == TOY_TYPE_BUILTIN ||
    452          existing->kind == TOY_TYPE_ARRAY || existing->kind == TOY_TYPE_PTR ||
    453          existing->kind == TOY_TYPE_FUNC ||
    454          existing->kind == TOY_TYPE_ANON_RECORD)) {
    455       return (ToyTypeId)(i + 1u);
    456     }
    457   }
    458 
    459   memset(&type, 0, sizeof type);
    460   type.cg = cg;
    461   kind = kit_cg_type_kind(p->c, cg);
    462   switch (kind) {
    463     case KIT_CG_TYPE_VOID:
    464     case KIT_CG_TYPE_BOOL:
    465     case KIT_CG_TYPE_INT:
    466     case KIT_CG_TYPE_FLOAT:
    467     case KIT_CG_TYPE_VARARG_STATE:
    468       type.kind = TOY_TYPE_BUILTIN;
    469       break;
    470     case KIT_CG_TYPE_PTR:
    471       type.kind = TOY_TYPE_PTR;
    472       type.pointee = toy_type_from_cg(p, kit_cg_type_ptr_pointee(p->c, cg));
    473       type.address_space = kit_cg_type_ptr_address_space(p->c, cg);
    474       break;
    475     case KIT_CG_TYPE_ARRAY:
    476       type.kind = TOY_TYPE_ARRAY;
    477       type.elem = toy_type_from_cg(p, kit_cg_type_array_elem(p->c, cg));
    478       type.count = kit_cg_type_array_count(p->c, cg);
    479       break;
    480     case KIT_CG_TYPE_FUNC:
    481       type.kind = TOY_TYPE_FUNC;
    482       type.ret = toy_type_from_cg(p, toy_cg_func_ret(p, cg));
    483       type.count = kit_cg_type_func_nparams(p->c, cg);
    484       break;
    485     case KIT_CG_TYPE_RECORD:
    486       type.kind = TOY_TYPE_ANON_RECORD;
    487       type.count = kit_cg_type_record_nfields(p->c, cg);
    488       break;
    489     case KIT_CG_TYPE_ENUM:
    490       type.kind = TOY_TYPE_ENUM;
    491       break;
    492   }
    493   return toy_type_add(p, &type);
    494 }
    495 
    496 ToyTypeId toy_type_register_alias(ToyParser* p, KitSym name, KitCgTypeId cg,
    497                                   KitCgTypeId base) {
    498   ToyType type;
    499   memset(&type, 0, sizeof type);
    500   type.kind = TOY_TYPE_ALIAS;
    501   type.cg = cg;
    502   type.name = name;
    503   type.base = toy_type_from_cg(p, base);
    504   return toy_type_add(p, &type);
    505 }
    506 
    507 ToyTypeId toy_type_register_named_record(ToyParser* p, KitSym name,
    508                                          KitCgTypeId cg, int is_tuple) {
    509   ToyTypeKind kind = is_tuple ? TOY_TYPE_TUPLE_RECORD : TOY_TYPE_NOMINAL_RECORD;
    510   size_t i;
    511   for (i = 0; i < p->module->type_table.ntypes; ++i) {
    512     ToyType* type = &p->module->type_table.types[i];
    513     if (type->kind == kind && type->name == name) {
    514       if (type->cg == KIT_CG_TYPE_NONE && cg != KIT_CG_TYPE_NONE) {
    515         if (!toy_txn_record_type(p, i)) return TOY_TYPE_NONE;
    516         type->cg = cg;
    517       }
    518       return (ToyTypeId)(i + 1u);
    519     }
    520   }
    521   return toy_type_register(p, kind, cg, name, TOY_TYPE_NONE);
    522 }
    523 
    524 ToyTypeId toy_type_register_enum(ToyParser* p, KitSym name, KitCgTypeId cg,
    525                                  KitCgTypeId base) {
    526   ToyType type;
    527   memset(&type, 0, sizeof type);
    528   type.kind = TOY_TYPE_ENUM;
    529   type.cg = cg;
    530   type.name = name;
    531   type.base = toy_type_from_cg(p, base);
    532   return toy_type_add(p, &type);
    533 }
    534 
    535 ToyTypeId toy_type_register_qualified(ToyParser* p, KitCgTypeId cg,
    536                                       KitCgTypeId base, uint32_t quals) {
    537   ToyType type;
    538   memset(&type, 0, sizeof type);
    539   type.kind = TOY_TYPE_QUALIFIED;
    540   type.cg = cg;
    541   type.base = toy_type_from_cg(p, base);
    542   type.quals = quals;
    543   return toy_type_add(p, &type);
    544 }
    545 
    546 ToyTypeId toy_type_register_ptr(ToyParser* p, KitCgTypeId cg, ToyTypeId pointee,
    547                                 uint32_t address_space) {
    548   ToyType type;
    549   memset(&type, 0, sizeof type);
    550   type.kind = TOY_TYPE_PTR;
    551   type.cg = cg;
    552   type.pointee = pointee;
    553   type.address_space = address_space;
    554   return toy_type_add(p, &type);
    555 }
    556 
    557 ToyTypeId toy_type_register_slice(ToyParser* p, KitCgTypeId elem_cg,
    558                                   ToyTypeId elem) {
    559   KitCgFieldDesc fields[2];
    560   KitCgTypeId ptr_ty;
    561   ToyType type;
    562   size_t i;
    563   if (elem == TOY_TYPE_NONE || elem_cg == KIT_CG_TYPE_NONE)
    564     return TOY_TYPE_NONE;
    565   for (i = 0; i < p->module->type_table.ntypes; ++i) {
    566     ToyType* existing = &p->module->type_table.types[i];
    567     if (existing->kind == TOY_TYPE_SLICE && existing->elem == elem)
    568       return (ToyTypeId)(i + 1u);
    569   }
    570   ptr_ty = kit_cg_type_ptr(p->c, elem_cg, 0);
    571   memset(fields, 0, sizeof fields);
    572   fields[0].name = kit_sym_intern(p->c, KIT_SLICE_LIT("ptr"));
    573   fields[0].type = ptr_ty;
    574   fields[1].name = kit_sym_intern(p->c, KIT_SLICE_LIT("len"));
    575   fields[1].type = p->size_type;
    576   memset(&type, 0, sizeof type);
    577   type.kind = TOY_TYPE_SLICE;
    578   type.cg = toy_cg_record_type(p, 0, fields, 2, 0, 0);
    579   type.elem = elem;
    580   return toy_type_add(p, &type);
    581 }
    582 
    583 ToyTypeId toy_type_register_func(ToyParser* p, KitCgTypeId cg, ToyTypeId ret,
    584                                  const ToyTypeId* params, size_t nparams,
    585                                  int variadic) {
    586   ToyType type;
    587   ToyTypeId id;
    588   memset(&type, 0, sizeof type);
    589   type.kind = TOY_TYPE_FUNC;
    590   type.cg = cg;
    591   type.ret = ret;
    592   type.count = nparams;
    593   type.nparams = nparams;
    594   type.variadic = variadic;
    595   if (nparams) {
    596     type.params = (ToyTypeId*)toy_parser_zalloc(p, nparams, sizeof *type.params,
    597                                                 "function type parameters");
    598     if (!type.params) return TOY_TYPE_NONE;
    599     memcpy(type.params, params, nparams * sizeof *type.params);
    600   }
    601   id = toy_type_add(p, &type);
    602   if (id == TOY_TYPE_NONE ||
    603       p->module->type_table.types[id - 1u].params != type.params)
    604     toy_parser_free_mem(p, type.params, nparams * sizeof *type.params);
    605   return id;
    606 }
    607 
    608 KitCgTypeId toy_type_resolved_cg(ToyParser* p, ToyTypeId id) {
    609   const ToyType* type = toy_type_get(p, id);
    610   if (!type) return KIT_CG_TYPE_NONE;
    611   if (type->kind == TOY_TYPE_ALIAS || type->kind == TOY_TYPE_QUALIFIED)
    612     return toy_type_resolved_cg(p, type->base);
    613   if (type->kind == TOY_TYPE_PTR && type->pointee != TOY_TYPE_NONE) {
    614     KitCgTypeId pointee = toy_type_resolved_cg(p, type->pointee);
    615     if (pointee != KIT_CG_TYPE_NONE)
    616       return kit_cg_type_ptr(p->c, pointee, type->address_space);
    617   }
    618   return type->cg;
    619 }
    620 
    621 ToyTypeId toy_type_pointee(ToyParser* p, ToyTypeId id) {
    622   const ToyType* type = toy_type_get(p, id);
    623   if (!type) return TOY_TYPE_NONE;
    624   if (type->kind == TOY_TYPE_ALIAS || type->kind == TOY_TYPE_QUALIFIED)
    625     return toy_type_pointee(p, type->base);
    626   return type->kind == TOY_TYPE_PTR ? type->pointee : TOY_TYPE_NONE;
    627 }
    628 
    629 ToyTypeId toy_type_array_elem(ToyParser* p, ToyTypeId id) {
    630   const ToyType* type = toy_type_get(p, id);
    631   if (!type) return TOY_TYPE_NONE;
    632   if (type->kind == TOY_TYPE_ALIAS || type->kind == TOY_TYPE_QUALIFIED)
    633     return toy_type_array_elem(p, type->base);
    634   return type->kind == TOY_TYPE_ARRAY ? type->elem : TOY_TYPE_NONE;
    635 }
    636 
    637 ToyTypeId toy_type_slice_elem(ToyParser* p, ToyTypeId id) {
    638   const ToyType* type = toy_type_get(p, id);
    639   if (!type) return TOY_TYPE_NONE;
    640   if (type->kind == TOY_TYPE_ALIAS || type->kind == TOY_TYPE_QUALIFIED)
    641     return toy_type_slice_elem(p, type->base);
    642   return type->kind == TOY_TYPE_SLICE ? type->elem : TOY_TYPE_NONE;
    643 }
    644 
    645 int toy_type_is_slice(ToyParser* p, ToyTypeId id) {
    646   const ToyType* type = toy_type_get(p, id);
    647   if (!type) return 0;
    648   if (type->kind == TOY_TYPE_ALIAS || type->kind == TOY_TYPE_QUALIFIED)
    649     return toy_type_is_slice(p, type->base);
    650   return type->kind == TOY_TYPE_SLICE;
    651 }
    652 
    653 static int toy_anon_record_types_match(ToyParser* p, KitCgTypeId expected,
    654                                        KitCgTypeId actual) {
    655   uint32_t i;
    656   const KitCgRecordLayout* el;
    657   const KitCgRecordLayout* al;
    658   if (kit_cg_type_kind(p->c, expected) != KIT_CG_TYPE_RECORD ||
    659       kit_cg_type_kind(p->c, actual) != KIT_CG_TYPE_RECORD) {
    660     return 0;
    661   }
    662   el = kit_cg_type_record_layout(p->c, expected);
    663   al = kit_cg_type_record_layout(p->c, actual);
    664   if (!el || !al) return 0;
    665   if (el->nfields != al->nfields) return 0;
    666   for (i = 0; i < el->nfields; ++i) {
    667     if (el->fields[i].name != al->fields[i].name) return 0;
    668     if (el->fields[i].type != al->fields[i].type) return 0;
    669   }
    670   return 1;
    671 }
    672 
    673 static int toy_type_accepts_storage_type(ToyParser* p, ToyTypeId expected,
    674                                          ToyTypeId actual) {
    675   const ToyType* exp = toy_type_get(p, expected);
    676   const ToyType* act = toy_type_get(p, actual);
    677   KitCgTypeId exp_cg, act_cg;
    678   if (!exp || !act) return 0;
    679   if (expected == actual) return 1;
    680   if (exp->kind == TOY_TYPE_ALIAS || exp->kind == TOY_TYPE_QUALIFIED)
    681     return toy_type_accepts_storage_type(p, exp->base, actual);
    682   if (act->kind == TOY_TYPE_ALIAS || act->kind == TOY_TYPE_QUALIFIED)
    683     return toy_type_accepts_storage_type(p, expected, act->base);
    684   if (exp->kind == TOY_TYPE_PTR && act->kind == TOY_TYPE_PTR) {
    685     if (exp->address_space != act->address_space) return 0;
    686     if (exp->pointee == TOY_TYPE_NONE || act->pointee == TOY_TYPE_NONE)
    687       return exp->cg == act->cg;
    688     return toy_type_accepts_storage_type(p, exp->pointee, act->pointee);
    689   }
    690   if (exp->kind == TOY_TYPE_ARRAY && act->kind == TOY_TYPE_ARRAY) {
    691     return exp->count == act->count &&
    692            toy_type_accepts_storage_type(p, exp->elem, act->elem);
    693   }
    694   if (exp->kind == TOY_TYPE_SLICE && act->kind == TOY_TYPE_SLICE)
    695     return toy_type_accepts_storage_type(p, exp->elem, act->elem);
    696   if (exp->kind == TOY_TYPE_FUNC && act->kind == TOY_TYPE_FUNC) {
    697     size_t i;
    698     if (exp->nparams != act->nparams || exp->variadic != act->variadic)
    699       return 0;
    700     if (!toy_type_accepts_storage_type(p, exp->ret, act->ret)) return 0;
    701     if (!exp->params || !act->params) return exp->cg == act->cg;
    702     for (i = 0; i < exp->nparams; ++i) {
    703       if (!toy_type_accepts_storage_type(p, exp->params[i], act->params[i]))
    704         return 0;
    705     }
    706     return 1;
    707   }
    708   if (exp->kind == TOY_TYPE_ANON_RECORD && act->kind == TOY_TYPE_ANON_RECORD)
    709     return toy_anon_record_types_match(p, exp->cg, act->cg);
    710   if (exp->kind == TOY_TYPE_NOMINAL_RECORD ||
    711       exp->kind == TOY_TYPE_TUPLE_RECORD || exp->kind == TOY_TYPE_ENUM ||
    712       act->kind == TOY_TYPE_NOMINAL_RECORD ||
    713       act->kind == TOY_TYPE_TUPLE_RECORD || act->kind == TOY_TYPE_ENUM)
    714     return 0;
    715   exp_cg = toy_type_resolved_cg(p, expected);
    716   act_cg = toy_type_resolved_cg(p, actual);
    717   return exp_cg != KIT_CG_TYPE_NONE && exp_cg == act_cg;
    718 }
    719 
    720 int toy_type_accepts_storage(ToyParser* p, ToyTypeId expected,
    721                              ToyTypeId actual) {
    722   return toy_type_accepts_storage_type(p, expected, actual);
    723 }
    724 
    725 int toy_type_accepts_type(ToyParser* p, ToyTypeId expected, ToyTypeId actual) {
    726   const ToyType* exp = toy_type_get(p, expected);
    727   const ToyType* act = toy_type_get(p, actual);
    728   KitCgTypeId exp_cg, act_cg;
    729   if (!exp || !act) return 0;
    730   if (expected == actual) return 1;
    731   if (exp->kind == TOY_TYPE_ALIAS || exp->kind == TOY_TYPE_QUALIFIED)
    732     return toy_type_accepts_type(p, exp->base, actual);
    733   if (act->kind == TOY_TYPE_ALIAS || act->kind == TOY_TYPE_QUALIFIED)
    734     return toy_type_accepts_type(p, expected, act->base);
    735   if (exp->kind == TOY_TYPE_PTR && act->kind == TOY_TYPE_PTR) {
    736     return toy_type_accepts_storage_type(p, expected, actual);
    737   }
    738   if (exp->kind == TOY_TYPE_ARRAY && act->kind == TOY_TYPE_ARRAY) {
    739     return toy_type_accepts_storage_type(p, expected, actual);
    740   }
    741   if (exp->kind == TOY_TYPE_SLICE && act->kind == TOY_TYPE_SLICE)
    742     return toy_type_accepts_storage_type(p, expected, actual);
    743   if (exp->kind == TOY_TYPE_FUNC && act->kind == TOY_TYPE_FUNC) {
    744     return toy_type_accepts_storage_type(p, expected, actual);
    745   }
    746   if (exp->kind == TOY_TYPE_ANON_RECORD && act->kind == TOY_TYPE_ANON_RECORD)
    747     return toy_anon_record_types_match(p, exp->cg, act->cg);
    748   exp_cg = toy_type_resolved_cg(p, expected);
    749   act_cg = toy_type_resolved_cg(p, actual);
    750   if (exp_cg != KIT_CG_TYPE_NONE && act_cg != KIT_CG_TYPE_NONE) {
    751     KitCgTypeKind exp_kind = kit_cg_type_kind(p->c, exp_cg);
    752     KitCgTypeKind act_kind = kit_cg_type_kind(p->c, act_cg);
    753     if (exp_kind == KIT_CG_TYPE_INT && act_kind == KIT_CG_TYPE_INT &&
    754         toy_type_int_width(p, act_cg) <= toy_type_int_width(p, exp_cg)) {
    755       return 1;
    756     }
    757     if (exp_kind == KIT_CG_TYPE_FLOAT && act_kind == KIT_CG_TYPE_FLOAT &&
    758         kit_cg_type_float_width(p->c, act_cg) <=
    759             kit_cg_type_float_width(p->c, exp_cg)) {
    760       return 1;
    761     }
    762   }
    763   return exp_cg != KIT_CG_TYPE_NONE && exp_cg == act_cg &&
    764          exp->kind != TOY_TYPE_NOMINAL_RECORD &&
    765          exp->kind != TOY_TYPE_TUPLE_RECORD && exp->kind != TOY_TYPE_ENUM;
    766 }
    767 
    768 int toy_record_field_index(ToyParser* p, KitCgTypeId record_ty,
    769                            KitSym field_name, uint32_t* index_out,
    770                            KitCgFieldLayout* field_out) {
    771   const KitCgRecordLayout* L = kit_cg_type_record_layout(p->c, record_ty);
    772   uint32_t i;
    773   if (!L) return 0;
    774   for (i = 0; i < L->nfields; ++i) {
    775     if (L->fields[i].name == field_name) {
    776       if (index_out) *index_out = i;
    777       if (field_out) *field_out = L->fields[i];
    778       return 1;
    779     }
    780   }
    781   return 0;
    782 }
    783 
    784 ToyNamedType* toy_find_named_type(ToyParser* p, KitSym name) {
    785   size_t i;
    786   for (i = p->module->type_table.count; i > 0; --i) {
    787     if (p->module->type_table.named[i - 1].name == name)
    788       return &p->module->type_table.named[i - 1];
    789   }
    790   return NULL;
    791 }
    792 
    793 ToyNamedType* toy_find_named_type_by_type(ToyParser* p, KitCgTypeId type) {
    794   size_t i;
    795   for (i = p->module->type_table.count; i > 0; --i) {
    796     if (p->module->type_table.named[i - 1].type == type)
    797       return &p->module->type_table.named[i - 1];
    798   }
    799   return NULL;
    800 }
    801 
    802 int toy_add_named_type(ToyParser* p, KitSym name, KitCgTypeId type,
    803                        ToyNamedTypeKind kind, KitCgTypeId base_type) {
    804   ToyNamedType* existing = toy_find_named_type(p, name);
    805   ToyTypeId toy_type = TOY_TYPE_NONE;
    806   if (kind == TOY_NAMED_ALIAS)
    807     toy_type = toy_type_register_alias(p, name, type, base_type);
    808   else if (kind == TOY_NAMED_ENUM)
    809     toy_type = toy_type_register_enum(p, name, type, base_type);
    810   else
    811     toy_type =
    812         toy_type_register_named_record(p, name, type, kind == TOY_NAMED_TUPLE);
    813   if (toy_type == TOY_TYPE_NONE && type != KIT_CG_TYPE_NONE) return 0;
    814   if (existing && existing->type == KIT_CG_TYPE_NONE) {
    815     /* Completing a forward declaration mutates an existing entry in place; if
    816      * it was committed before this compile, snapshot it for rollback. */
    817     if (!toy_txn_record_named(
    818             p, (size_t)(existing - p->module->type_table.named))) {
    819       return 0;
    820     }
    821     existing->type = type;
    822     existing->toy_type = toy_type;
    823     existing->kind = kind;
    824     existing->base_type = base_type;
    825     return 1;
    826   }
    827   if (!toy_parser_reserve(p, (void**)&p->module->type_table.named,
    828                           &p->module->type_table.cap,
    829                           p->module->type_table.count + 1u,
    830                           sizeof *p->module->type_table.named, "named types")) {
    831     return 0;
    832   }
    833   memset(&p->module->type_table.named[p->module->type_table.count], 0,
    834          sizeof p->module->type_table.named[p->module->type_table.count]);
    835   p->module->type_table.named[p->module->type_table.count].name = name;
    836   p->module->type_table.named[p->module->type_table.count].type = type;
    837   p->module->type_table.named[p->module->type_table.count].toy_type = toy_type;
    838   p->module->type_table.named[p->module->type_table.count].kind = kind;
    839   p->module->type_table.named[p->module->type_table.count].base_type =
    840       base_type;
    841   p->module->type_table.count++;
    842   return 1;
    843 }
    844 
    845 int toy_set_named_type_fields(ToyParser* p, ToyNamedType* named,
    846                               const ToyRecordFieldInfo* fields,
    847                               size_t nfields) {
    848   if (!toy_txn_record_named(p, (size_t)(named - p->module->type_table.named))) {
    849     return 0;
    850   }
    851   if (!toy_parser_reserve(p, (void**)&named->fields, &named->cap_fields,
    852                           nfields, sizeof *named->fields, "record fields")) {
    853     return 0;
    854   }
    855   if (nfields) memcpy(named->fields, fields, sizeof *named->fields * nfields);
    856   named->nfields = nfields;
    857   return 1;
    858 }
    859 
    860 int toy_set_named_type_enum_values(ToyParser* p, ToyNamedType* named,
    861                                    const ToyEnumConst* values, size_t nvalues) {
    862   if (!named) return 0;
    863   if (!toy_txn_record_named(p, (size_t)(named - p->module->type_table.named))) {
    864     return 0;
    865   }
    866   if (!toy_parser_reserve(p, (void**)&named->enum_values,
    867                           &named->cap_enum_values, nvalues,
    868                           sizeof *named->enum_values, "enum values")) {
    869     return 0;
    870   }
    871   if (nvalues) memcpy(named->enum_values, values, sizeof values[0] * nvalues);
    872   named->nenum_values = nvalues;
    873   return 1;
    874 }