kit

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

data.c (17924B)


      1 #include <string.h>
      2 
      3 #include "internal.h"
      4 
      5 int toy_parse_data_array_builtin(ToyParser* p, KitCgTypeId elem_ty,
      6                                  uint64_t total_size, uint64_t* pos);
      7 
      8 int toy_parse_global_var(ToyParser* p, int is_extern, int is_pub) {
      9   KitSym name;
     10   KitCgTypeId ty;
     11   KitCgDecl decl;
     12   KitCgDataDefAttrs data_attrs;
     13   KitCgSym sym;
     14   ToyTypeId toy_type;
     15   int mutable;
     16   ToyAttrSet attrs;
     17   KitSymBind default_bind =
     18       (is_extern || is_pub ||
     19        p->input_kind != KIT_FRONTEND_INPUT_TRANSLATION_UNIT)
     20           ? KIT_SB_GLOBAL
     21           : KIT_SB_LOCAL;
     22 
     23   if (p->cur.kind == TOK_VAR) {
     24     mutable = 1;
     25     toy_parser_advance(p);
     26   } else {
     27     mutable = 0;
     28     toy_parser_advance(p); /* let */
     29   }
     30   if (!toy_parse_attr_list(p, &attrs, default_bind)) return 0;
     31   if (!toy_validate_attr_placement(p, &attrs,
     32                                    TOY_ATTR_SYMBOL | TOY_ATTR_OBJECT |
     33                                        TOY_ATTR_SECTION | TOY_ATTR_OBJECT_DATA |
     34                                        (is_extern ? 0u : TOY_ATTR_DATA),
     35                                    is_extern ? "invalid extern data attribute"
     36                                              : "invalid object attribute")) {
     37     return 0;
     38   }
     39 
     40   if (p->cur.kind != TOK_IDENT) {
     41     toy_error(p, p->cur.loc, "expected identifier");
     42     return 0;
     43   }
     44   name = toy_tok_sym(p, p->cur);
     45   toy_parser_advance(p);
     46   if (!toy_parser_expect(p, TOK_COLON)) {
     47     toy_error(p, p->cur.loc, "expected ':' after identifier");
     48     return 0;
     49   }
     50   ty = toy_parse_type(p);
     51   if (ty == KIT_CG_TYPE_NONE) return 0;
     52   toy_type = p->last_type;
     53   if (attrs.is_common && !mutable) {
     54     toy_error(p, p->cur.loc, "common object must be mutable");
     55     return 0;
     56   }
     57   if (attrs.is_common && p->cur.kind == TOK_EQ) {
     58     toy_error(p, p->cur.loc, "common object cannot have initializer");
     59     return 0;
     60   }
     61 
     62   memset(&decl, 0, sizeof(decl));
     63   decl.kind = KIT_CG_DECL_OBJECT;
     64   decl.linkage_name = toy_c_linkage_name(p, name);
     65   if (!decl.linkage_name) return 0;
     66   decl.display_name = name;
     67   decl.type = ty;
     68   decl.sym = attrs.sym;
     69   decl.as.object = attrs.object;
     70   if (!mutable) decl.as.object.flags |= KIT_CG_OBJ_READONLY;
     71 
     72   sym = kit_cg_decl(p->cg, decl);
     73   if (sym == KIT_CG_SYM_NONE) {
     74     toy_error(p, p->cur.loc, "failed to declare global");
     75     return 0;
     76   }
     77 
     78   if (!toy_add_global_typed(p, name, sym, ty, toy_type, mutable)) {
     79     return 0;
     80   }
     81   {
     82     ToyGlobal* g = toy_find_global(p, name);
     83     if (g) {
     84       g->sym_attrs = decl.sym;
     85       g->object_attrs = decl.as.object;
     86     }
     87   }
     88 
     89   data_attrs = attrs.data;
     90 
     91   if (is_extern) {
     92     if (!toy_parser_expect(p, TOK_SEMI)) {
     93       toy_error(p, p->cur.loc, "expected ';' after extern object");
     94       return 0;
     95     }
     96     return 1;
     97   }
     98 
     99   if (toy_parser_match(p, TOK_EQ)) {
    100     if (p->cur.kind == TOK_NUMBER) {
    101       if (p->cur.is_float) {
    102         if (!toy_type_is_float(p, ty)) {
    103           toy_error(p, p->cur.loc, "float initializer requires float object");
    104           return 0;
    105         }
    106         kit_cg_data_begin(p->cg, sym, data_attrs);
    107         kit_cg_data_float(p->cg, p->cur.float_value, ty);
    108         kit_cg_data_end(p->cg);
    109         toy_parser_advance(p);
    110       } else {
    111         uint8_t buf[16];
    112         size_t n = (size_t)kit_cg_type_size(p->c, ty);
    113         if (n > sizeof buf) {
    114           toy_error(p, p->cur.loc, "initializer too large");
    115           return 0;
    116         }
    117         toy_emit_int_bytes(p, (uint64_t)p->cur.int_value, buf, n);
    118         toy_parser_advance(p);
    119         kit_cg_data_begin(p->cg, sym, data_attrs);
    120         kit_cg_data_bytes(p->cg, buf, n);
    121         kit_cg_data_end(p->cg);
    122       }
    123     } else if (p->cur.kind == TOK_AMPERSAND) {
    124       KitSym target;
    125       KitCgSym target_sym;
    126       uint32_t nbytes = (uint32_t)kit_cg_type_size(p->c, ty);
    127       toy_parser_advance(p);
    128       if (p->cur.kind != TOK_IDENT) {
    129         toy_error(p, p->cur.loc, "expected identifier after '&'");
    130         return 0;
    131       }
    132       target = toy_tok_sym(p, p->cur);
    133       toy_parser_advance(p);
    134       target_sym = toy_find_decl_sym(p, target);
    135       if (target_sym == KIT_CG_SYM_NONE) {
    136         toy_error(p, p->cur.loc, "undefined symbol in initializer");
    137         return 0;
    138       }
    139       kit_cg_data_begin(p->cg, sym, data_attrs);
    140       kit_cg_data_addr(p->cg, target_sym, 0, nbytes, 0);
    141       kit_cg_data_end(p->cg);
    142     } else if (p->cur.kind == TOK_STRING &&
    143                kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_ARRAY &&
    144                kit_cg_type_array_elem(p->c, ty) ==
    145                    toy_builtin_type(p, KIT_CG_BUILTIN_I8)) {
    146       uint8_t buf[1024];
    147       size_t len = 0;
    148       uint64_t size = kit_cg_type_size(p->c, ty);
    149       if (!toy_parse_string_bytes(p, buf, sizeof buf, &len)) return 0;
    150       if ((uint64_t)len > size) {
    151         toy_error(p, p->cur.loc, "string initializer too large");
    152         return 0;
    153       }
    154       kit_cg_data_begin(p->cg, sym, data_attrs);
    155       kit_cg_data_bytes(p->cg, buf, len);
    156       if ((uint64_t)len < size) kit_cg_data_zero(p->cg, size - (uint64_t)len);
    157       kit_cg_data_end(p->cg);
    158     } else if (p->cur.kind == TOK_LBRACKET &&
    159                kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_ARRAY) {
    160       KitCgTypeId elem_ty = kit_cg_type_array_elem(p->c, ty);
    161       uint64_t total_size = kit_cg_type_size(p->c, ty);
    162       uint64_t elem_size = kit_cg_type_size(p->c, elem_ty);
    163       uint64_t pos = 0;
    164       toy_parser_advance(p);
    165       kit_cg_data_begin(p->cg, sym, data_attrs);
    166       while (p->cur.kind != TOK_RBRACKET && p->cur.kind != TOK_EOF) {
    167         if (pos >= total_size) {
    168           toy_error(p, p->cur.loc, "too many array initializer elements");
    169           return 0;
    170         }
    171         if (p->cur.kind == TOK_AT) {
    172           if (!toy_parse_data_array_builtin(p, elem_ty, total_size, &pos))
    173             return 0;
    174         } else if (p->cur.kind == TOK_NUMBER && !p->cur.is_float) {
    175           if (pos + elem_size > total_size) {
    176             toy_error(p, p->cur.loc, "too many array initializer elements");
    177             return 0;
    178           }
    179           kit_cg_data_int(p->cg, (uint64_t)p->cur.int_value, elem_ty);
    180           toy_parser_advance(p);
    181           pos += elem_size;
    182         } else {
    183           toy_error(p, p->cur.loc, "expected constant array initializer");
    184           return 0;
    185         }
    186         if (!toy_parser_match(p, TOK_COMMA)) break;
    187       }
    188       if (!toy_parser_expect(p, TOK_RBRACKET)) {
    189         toy_error(p, p->cur.loc, "expected ']' after array initializer");
    190         return 0;
    191       }
    192       if (pos < total_size) kit_cg_data_zero(p->cg, total_size - pos);
    193       kit_cg_data_end(p->cg);
    194     } else if ((p->cur.kind == TOK_IDENT || p->cur.kind == TOK_LBRACE) &&
    195                kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_RECORD) {
    196       if (!toy_parse_global_record_initializer(p, sym, ty, data_attrs))
    197         return 0;
    198     } else {
    199       toy_error(p, p->cur.loc, "expected constant global initializer");
    200       return 0;
    201     }
    202   } else if (attrs.is_common) {
    203     uint32_t align =
    204         data_attrs.align ? data_attrs.align : kit_cg_type_align(p->c, ty);
    205     kit_cg_data_common(p->cg, sym, kit_cg_type_size(p->c, ty), align);
    206   } else {
    207     kit_cg_data_begin(p->cg, sym, data_attrs);
    208     kit_cg_data_zero(p->cg, kit_cg_type_size(p->c, ty));
    209     kit_cg_data_end(p->cg);
    210   }
    211 
    212   if (!toy_parser_expect(p, TOK_SEMI)) {
    213     toy_error(p, p->cur.loc, "expected ';'");
    214     return 0;
    215   }
    216   return 1;
    217 }
    218 
    219 int toy_parse_global_record_initializer(ToyParser* p, KitCgSym sym,
    220                                         KitCgTypeId record_ty,
    221                                         KitCgDataDefAttrs data_attrs) {
    222   uint8_t* seen;
    223   uint64_t pos = 0;
    224   uint64_t total_size = kit_cg_type_size(p->c, record_ty);
    225   uint32_t nfields = kit_cg_type_record_nfields(p->c, record_ty);
    226   size_t seen_size = (size_t)(nfields ? nfields : 1u) * sizeof *seen;
    227   ToyNamedType* named = toy_find_named_type_by_type(p, record_ty);
    228   int positional = named && named->kind == TOY_NAMED_TUPLE;
    229   seen = (uint8_t*)toy_parser_zalloc(p, nfields ? nfields : 1u, sizeof *seen,
    230                                      "record initializer");
    231   if (!seen) {
    232     return 0;
    233   }
    234   if (p->cur.kind == TOK_IDENT) toy_parser_advance(p);
    235   if (!toy_parser_expect(p, TOK_LBRACE)) {
    236     toy_error(p, p->cur.loc, "expected record initializer");
    237     toy_parser_free_mem(p, seen, seen_size);
    238     return 0;
    239   }
    240   kit_cg_data_begin(p->cg, sym, data_attrs);
    241   if (positional) {
    242     uint32_t field_index = 0;
    243     while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) {
    244       KitCgField field;
    245       uint64_t field_off;
    246       if (field_index >= nfields) {
    247         toy_error(p, p->cur.loc, "too many tuple initializer elements");
    248         toy_parser_free_mem(p, seen, seen_size);
    249         return 0;
    250       }
    251       if (kit_cg_type_record_field(p->c, record_ty, field_index, &field,
    252                                    &field_off) != 0) {
    253         toy_parser_free_mem(p, seen, seen_size);
    254         return 0;
    255       }
    256       if (field_off > pos) {
    257         kit_cg_data_zero(p->cg, field_off - pos);
    258         pos = field_off;
    259       }
    260       if (p->cur.kind == TOK_AT) {
    261         if (!toy_parse_data_array_builtin(p, field.type, total_size, &pos)) {
    262           toy_parser_free_mem(p, seen, seen_size);
    263           return 0;
    264         }
    265       } else if (p->cur.kind != TOK_NUMBER || p->cur.is_float) {
    266         toy_error(p, p->cur.loc, "expected constant tuple initializer");
    267         toy_parser_free_mem(p, seen, seen_size);
    268         return 0;
    269       } else {
    270         kit_cg_data_int(p->cg, (uint64_t)p->cur.int_value, field.type);
    271         pos += kit_cg_type_size(p->c, field.type);
    272         toy_parser_advance(p);
    273       }
    274       field_index++;
    275       if (!toy_parser_match(p, TOK_COMMA)) break;
    276     }
    277     if (!toy_parser_expect(p, TOK_RBRACE)) {
    278       toy_error(p, p->cur.loc, "expected '}' after tuple initializer");
    279       toy_parser_free_mem(p, seen, seen_size);
    280       return 0;
    281     }
    282     if (pos < total_size) kit_cg_data_zero(p->cg, total_size - pos);
    283     kit_cg_data_end(p->cg);
    284     toy_parser_free_mem(p, seen, seen_size);
    285     return 1;
    286   }
    287   while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) {
    288     KitSym field_name;
    289     KitCgField field;
    290     uint32_t field_index;
    291     uint64_t field_off;
    292     if (p->cur.kind != TOK_IDENT) {
    293       toy_error(p, p->cur.loc, "expected field name");
    294       toy_parser_free_mem(p, seen, seen_size);
    295       return 0;
    296     }
    297     field_name = toy_tok_sym(p, p->cur);
    298     toy_parser_advance(p);
    299     if (!toy_parser_expect(p, TOK_COLON)) {
    300       toy_error(p, p->cur.loc, "expected ':' in record initializer");
    301       toy_parser_free_mem(p, seen, seen_size);
    302       return 0;
    303     }
    304     if (!toy_record_field_index(p, record_ty, field_name, &field_index,
    305                                 &field)) {
    306       toy_error(p, p->cur.loc, "unknown record field");
    307       toy_parser_free_mem(p, seen, seen_size);
    308       return 0;
    309     }
    310     if (field_index >= nfields || seen[field_index]) {
    311       toy_error(p, p->cur.loc, "duplicate record field initializer");
    312       toy_parser_free_mem(p, seen, seen_size);
    313       return 0;
    314     }
    315     seen[field_index] = 1;
    316     if (kit_cg_type_record_field(p->c, record_ty, field_index, NULL,
    317                                  &field_off) != 0) {
    318       toy_parser_free_mem(p, seen, seen_size);
    319       return 0;
    320     }
    321     if (field_off < pos) {
    322       toy_error(p, p->cur.loc, "record initializer fields out of order");
    323       toy_parser_free_mem(p, seen, seen_size);
    324       return 0;
    325     }
    326     if (field_off > pos) {
    327       kit_cg_data_zero(p->cg, field_off - pos);
    328       pos = field_off;
    329     }
    330     if (p->cur.kind == TOK_AT) {
    331       if (!toy_parse_data_array_builtin(p, field.type, total_size, &pos)) {
    332         toy_parser_free_mem(p, seen, seen_size);
    333         return 0;
    334       }
    335     } else if (p->cur.kind != TOK_NUMBER || p->cur.is_float) {
    336       toy_error(p, p->cur.loc, "expected constant record initializer");
    337       toy_parser_free_mem(p, seen, seen_size);
    338       return 0;
    339     } else {
    340       kit_cg_data_int(p->cg, (uint64_t)p->cur.int_value, field.type);
    341       pos += kit_cg_type_size(p->c, field.type);
    342       toy_parser_advance(p);
    343     }
    344     if (!toy_parser_match(p, TOK_COMMA)) break;
    345   }
    346   if (!toy_parser_expect(p, TOK_RBRACE)) {
    347     toy_error(p, p->cur.loc, "expected '}' after record initializer");
    348     toy_parser_free_mem(p, seen, seen_size);
    349     return 0;
    350   }
    351   if (pos < total_size) kit_cg_data_zero(p->cg, total_size - pos);
    352   kit_cg_data_end(p->cg);
    353   toy_parser_free_mem(p, seen, seen_size);
    354   return 1;
    355 }
    356 
    357 int toy_parse_data_array_builtin(ToyParser* p, KitCgTypeId elem_ty,
    358                                  uint64_t total_size, uint64_t* pos) {
    359   KitSym name;
    360   uint64_t elem_size = kit_cg_type_size(p->c, elem_ty);
    361   if (!toy_parser_expect(p, TOK_AT) || p->cur.kind != TOK_IDENT) {
    362     toy_error(p, p->cur.loc, "expected data initializer builtin");
    363     return 0;
    364   }
    365   name = toy_tok_sym(p, p->cur);
    366   toy_parser_advance(p);
    367   if (toy_sym_is(p, name, "pcrel")) {
    368     KitSym target_name;
    369     KitCgSym target_sym;
    370     int64_t addend;
    371     if (!toy_type_is_intlike(p, elem_ty) ||
    372         (elem_size != 4 && elem_size != 8)) {
    373       toy_error(p, p->cur.loc, "pcrel requires i32/i64 initializer slot");
    374       return 0;
    375     }
    376     if (pos && *pos + elem_size > total_size) {
    377       toy_error(p, p->cur.loc, "too many array initializer elements");
    378       return 0;
    379     }
    380     if (!toy_parser_expect(p, TOK_LPAREN) || p->cur.kind != TOK_IDENT) {
    381       toy_error(p, p->cur.loc, "expected pcrel target symbol");
    382       return 0;
    383     }
    384     target_name = toy_tok_sym(p, p->cur);
    385     toy_parser_advance(p);
    386     if (!toy_parser_expect(p, TOK_COMMA) || !toy_parse_number_arg(p, &addend) ||
    387         !toy_parser_expect(p, TOK_RPAREN)) {
    388       toy_error(p, p->cur.loc, "invalid pcrel initializer");
    389       return 0;
    390     }
    391     target_sym = toy_find_decl_sym(p, target_name);
    392     if (target_sym == KIT_CG_SYM_NONE) {
    393       toy_error(p, p->cur.loc, "undefined pcrel target");
    394       return 0;
    395     }
    396     kit_cg_data_pcrel(p->cg, target_sym, addend, (uint32_t)elem_size);
    397     *pos += elem_size;
    398     return 1;
    399   }
    400   if (toy_sym_is(p, name, "symdiff")) {
    401     KitSym lhs_name;
    402     KitSym rhs_name;
    403     KitCgSym lhs_sym;
    404     KitCgSym rhs_sym;
    405     int64_t addend;
    406     if (!toy_type_is_intlike(p, elem_ty) || elem_size == 0 || elem_size > 8) {
    407       toy_error(p, p->cur.loc, "symdiff requires integer initializer slot");
    408       return 0;
    409     }
    410     if (pos && *pos + elem_size > total_size) {
    411       toy_error(p, p->cur.loc, "too many array initializer elements");
    412       return 0;
    413     }
    414     if (!toy_parser_expect(p, TOK_LPAREN) || p->cur.kind != TOK_IDENT) {
    415       toy_error(p, p->cur.loc, "expected symdiff lhs symbol");
    416       return 0;
    417     }
    418     lhs_name = toy_tok_sym(p, p->cur);
    419     toy_parser_advance(p);
    420     if (!toy_parser_expect(p, TOK_COMMA) || p->cur.kind != TOK_IDENT) {
    421       toy_error(p, p->cur.loc, "expected symdiff rhs symbol");
    422       return 0;
    423     }
    424     rhs_name = toy_tok_sym(p, p->cur);
    425     toy_parser_advance(p);
    426     if (!toy_parser_expect(p, TOK_COMMA) || !toy_parse_number_arg(p, &addend) ||
    427         !toy_parser_expect(p, TOK_RPAREN)) {
    428       toy_error(p, p->cur.loc, "invalid symdiff initializer");
    429       return 0;
    430     }
    431     lhs_sym = toy_find_decl_sym(p, lhs_name);
    432     rhs_sym = toy_find_decl_sym(p, rhs_name);
    433     if (lhs_sym == KIT_CG_SYM_NONE || rhs_sym == KIT_CG_SYM_NONE) {
    434       toy_error(p, p->cur.loc, "undefined symdiff symbol");
    435       return 0;
    436     }
    437     kit_cg_data_symdiff(p->cg, lhs_sym, rhs_sym, addend, (uint32_t)elem_size);
    438     *pos += elem_size;
    439     return 1;
    440   }
    441   if (toy_sym_is(p, name, "labeladdr")) {
    442     KitSym label_name;
    443     ToyLabel* label;
    444     if (kit_cg_type_kind(p->c, elem_ty) != KIT_CG_TYPE_PTR || elem_size == 0 ||
    445         elem_size > 8) {
    446       toy_error(p, p->cur.loc, "labeladdr requires pointer initializer slot");
    447       return 0;
    448     }
    449     if (pos && *pos + elem_size > total_size) {
    450       toy_error(p, p->cur.loc, "too many array initializer elements");
    451       return 0;
    452     }
    453     if (!toy_parser_expect(p, TOK_LPAREN) || p->cur.kind != TOK_IDENT) {
    454       toy_error(p, p->cur.loc, "expected labeladdr label");
    455       return 0;
    456     }
    457     label_name = toy_tok_sym(p, p->cur);
    458     toy_parser_advance(p);
    459     if (!toy_parser_expect(p, TOK_RPAREN)) return 0;
    460     label = toy_find_label(p, label_name);
    461     if (!label) {
    462       toy_error(p, p->cur.loc, "unknown label");
    463       return 0;
    464     }
    465     kit_cg_data_label_addr(p->cg, label->label, 0, (uint32_t)elem_size, 0);
    466     *pos += elem_size;
    467     return 1;
    468   }
    469   if (elem_size != 1) {
    470     toy_error(p, p->cur.loc, "data initializer builtin requires byte array");
    471     return 0;
    472   }
    473   if (toy_sym_is(p, name, "pad")) {
    474     int64_t size;
    475     int64_t value;
    476     if (!toy_parser_expect(p, TOK_LPAREN) || !toy_parse_number_arg(p, &size) ||
    477         !toy_parser_expect(p, TOK_COMMA) || !toy_parse_number_arg(p, &value) ||
    478         !toy_parser_expect(p, TOK_RPAREN)) {
    479       return 0;
    480     }
    481     if (size < 0 || value < 0 || value > 255 ||
    482         *pos + (uint64_t)size > total_size) {
    483       toy_error(p, p->cur.loc, "invalid data pad initializer");
    484       return 0;
    485     }
    486     kit_cg_data_pad(p->cg, (uint64_t)size, (uint8_t)value);
    487     *pos += (uint64_t)size;
    488     return 1;
    489   }
    490   if (toy_sym_is(p, name, "align")) {
    491     int64_t align;
    492     uint64_t aligned;
    493     if (!toy_parser_expect(p, TOK_LPAREN) || !toy_parse_number_arg(p, &align) ||
    494         !toy_parser_expect(p, TOK_RPAREN)) {
    495       return 0;
    496     }
    497     if (align <= 0 || (align & (align - 1)) != 0) {
    498       toy_error(p, p->cur.loc, "invalid data alignment");
    499       return 0;
    500     }
    501     aligned = (*pos + (uint64_t)align - 1u) & ~((uint64_t)align - 1u);
    502     if (aligned > total_size) {
    503       toy_error(p, p->cur.loc, "data alignment exceeds initializer size");
    504       return 0;
    505     }
    506     kit_cg_data_align(p->cg, (uint32_t)align);
    507     *pos = aligned;
    508     return 1;
    509   }
    510   toy_error(p, p->cur.loc, "unknown data initializer builtin");
    511   return 0;
    512 }