kit

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

types.c (33993B)


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