kit

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

data.c (17724B)


      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   const KitCgRecordLayout* L = kit_cg_type_record_layout(p->c, record_ty);
    226   uint32_t nfields = L ? L->nfields : 0;
    227   size_t seen_size = (size_t)(nfields ? nfields : 1u) * sizeof *seen;
    228   ToyNamedType* named = toy_find_named_type_by_type(p, record_ty);
    229   int positional = named && named->kind == TOY_NAMED_TUPLE;
    230   if (!L) return 0;
    231   seen = (uint8_t*)toy_parser_zalloc(p, nfields ? nfields : 1u, sizeof *seen,
    232                                      "record initializer");
    233   if (!seen) {
    234     return 0;
    235   }
    236   if (p->cur.kind == TOK_IDENT) toy_parser_advance(p);
    237   if (!toy_parser_expect(p, TOK_LBRACE)) {
    238     toy_error(p, p->cur.loc, "expected record initializer");
    239     toy_parser_free_mem(p, seen, seen_size);
    240     return 0;
    241   }
    242   kit_cg_data_begin(p->cg, sym, data_attrs);
    243   if (positional) {
    244     uint32_t field_index = 0;
    245     while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) {
    246       const KitCgFieldLayout* field;
    247       uint64_t field_off;
    248       if (field_index >= nfields) {
    249         toy_error(p, p->cur.loc, "too many tuple initializer elements");
    250         toy_parser_free_mem(p, seen, seen_size);
    251         return 0;
    252       }
    253       field = &L->fields[field_index];
    254       field_off = field->offset;
    255       if (field_off > pos) {
    256         kit_cg_data_zero(p->cg, field_off - pos);
    257         pos = field_off;
    258       }
    259       if (p->cur.kind == TOK_AT) {
    260         if (!toy_parse_data_array_builtin(p, field->type, total_size, &pos)) {
    261           toy_parser_free_mem(p, seen, seen_size);
    262           return 0;
    263         }
    264       } else if (p->cur.kind != TOK_NUMBER || p->cur.is_float) {
    265         toy_error(p, p->cur.loc, "expected constant tuple initializer");
    266         toy_parser_free_mem(p, seen, seen_size);
    267         return 0;
    268       } else {
    269         kit_cg_data_int(p->cg, (uint64_t)p->cur.int_value, field->type);
    270         pos += kit_cg_type_size(p->c, field->type);
    271         toy_parser_advance(p);
    272       }
    273       field_index++;
    274       if (!toy_parser_match(p, TOK_COMMA)) break;
    275     }
    276     if (!toy_parser_expect(p, TOK_RBRACE)) {
    277       toy_error(p, p->cur.loc, "expected '}' after tuple initializer");
    278       toy_parser_free_mem(p, seen, seen_size);
    279       return 0;
    280     }
    281     if (pos < total_size) kit_cg_data_zero(p->cg, total_size - pos);
    282     kit_cg_data_end(p->cg);
    283     toy_parser_free_mem(p, seen, seen_size);
    284     return 1;
    285   }
    286   while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) {
    287     KitSym field_name;
    288     KitCgFieldLayout field;
    289     uint32_t field_index;
    290     uint64_t field_off;
    291     if (p->cur.kind != TOK_IDENT) {
    292       toy_error(p, p->cur.loc, "expected field name");
    293       toy_parser_free_mem(p, seen, seen_size);
    294       return 0;
    295     }
    296     field_name = toy_tok_sym(p, p->cur);
    297     toy_parser_advance(p);
    298     if (!toy_parser_expect(p, TOK_COLON)) {
    299       toy_error(p, p->cur.loc, "expected ':' in record initializer");
    300       toy_parser_free_mem(p, seen, seen_size);
    301       return 0;
    302     }
    303     if (!toy_record_field_index(p, record_ty, field_name, &field_index,
    304                                 &field)) {
    305       toy_error(p, p->cur.loc, "unknown record field");
    306       toy_parser_free_mem(p, seen, seen_size);
    307       return 0;
    308     }
    309     if (field_index >= nfields || seen[field_index]) {
    310       toy_error(p, p->cur.loc, "duplicate record field initializer");
    311       toy_parser_free_mem(p, seen, seen_size);
    312       return 0;
    313     }
    314     seen[field_index] = 1;
    315     field_off = field.offset;
    316     if (field_off < pos) {
    317       toy_error(p, p->cur.loc, "record initializer fields out of order");
    318       toy_parser_free_mem(p, seen, seen_size);
    319       return 0;
    320     }
    321     if (field_off > pos) {
    322       kit_cg_data_zero(p->cg, field_off - pos);
    323       pos = field_off;
    324     }
    325     if (p->cur.kind == TOK_AT) {
    326       if (!toy_parse_data_array_builtin(p, field.type, total_size, &pos)) {
    327         toy_parser_free_mem(p, seen, seen_size);
    328         return 0;
    329       }
    330     } else if (p->cur.kind != TOK_NUMBER || p->cur.is_float) {
    331       toy_error(p, p->cur.loc, "expected constant record initializer");
    332       toy_parser_free_mem(p, seen, seen_size);
    333       return 0;
    334     } else {
    335       kit_cg_data_int(p->cg, (uint64_t)p->cur.int_value, field.type);
    336       pos += kit_cg_type_size(p->c, field.type);
    337       toy_parser_advance(p);
    338     }
    339     if (!toy_parser_match(p, TOK_COMMA)) break;
    340   }
    341   if (!toy_parser_expect(p, TOK_RBRACE)) {
    342     toy_error(p, p->cur.loc, "expected '}' after record initializer");
    343     toy_parser_free_mem(p, seen, seen_size);
    344     return 0;
    345   }
    346   if (pos < total_size) kit_cg_data_zero(p->cg, total_size - pos);
    347   kit_cg_data_end(p->cg);
    348   toy_parser_free_mem(p, seen, seen_size);
    349   return 1;
    350 }
    351 
    352 int toy_parse_data_array_builtin(ToyParser* p, KitCgTypeId elem_ty,
    353                                  uint64_t total_size, uint64_t* pos) {
    354   KitSym name;
    355   uint64_t elem_size = kit_cg_type_size(p->c, elem_ty);
    356   if (!toy_parser_expect(p, TOK_AT) || p->cur.kind != TOK_IDENT) {
    357     toy_error(p, p->cur.loc, "expected data initializer builtin");
    358     return 0;
    359   }
    360   name = toy_tok_sym(p, p->cur);
    361   toy_parser_advance(p);
    362   if (toy_sym_is(p, name, "pcrel")) {
    363     KitSym target_name;
    364     KitCgSym target_sym;
    365     int64_t addend;
    366     if (!toy_type_is_intlike(p, elem_ty) ||
    367         (elem_size != 4 && elem_size != 8)) {
    368       toy_error(p, p->cur.loc, "pcrel requires i32/i64 initializer slot");
    369       return 0;
    370     }
    371     if (pos && *pos + elem_size > total_size) {
    372       toy_error(p, p->cur.loc, "too many array initializer elements");
    373       return 0;
    374     }
    375     if (!toy_parser_expect(p, TOK_LPAREN) || p->cur.kind != TOK_IDENT) {
    376       toy_error(p, p->cur.loc, "expected pcrel target symbol");
    377       return 0;
    378     }
    379     target_name = toy_tok_sym(p, p->cur);
    380     toy_parser_advance(p);
    381     if (!toy_parser_expect(p, TOK_COMMA) || !toy_parse_number_arg(p, &addend) ||
    382         !toy_parser_expect(p, TOK_RPAREN)) {
    383       toy_error(p, p->cur.loc, "invalid pcrel initializer");
    384       return 0;
    385     }
    386     target_sym = toy_find_decl_sym(p, target_name);
    387     if (target_sym == KIT_CG_SYM_NONE) {
    388       toy_error(p, p->cur.loc, "undefined pcrel target");
    389       return 0;
    390     }
    391     kit_cg_data_pcrel(p->cg, target_sym, addend, (uint32_t)elem_size);
    392     *pos += elem_size;
    393     return 1;
    394   }
    395   if (toy_sym_is(p, name, "symdiff")) {
    396     KitSym lhs_name;
    397     KitSym rhs_name;
    398     KitCgSym lhs_sym;
    399     KitCgSym rhs_sym;
    400     int64_t addend;
    401     if (!toy_type_is_intlike(p, elem_ty) || elem_size == 0 || elem_size > 8) {
    402       toy_error(p, p->cur.loc, "symdiff requires integer initializer slot");
    403       return 0;
    404     }
    405     if (pos && *pos + elem_size > total_size) {
    406       toy_error(p, p->cur.loc, "too many array initializer elements");
    407       return 0;
    408     }
    409     if (!toy_parser_expect(p, TOK_LPAREN) || p->cur.kind != TOK_IDENT) {
    410       toy_error(p, p->cur.loc, "expected symdiff lhs symbol");
    411       return 0;
    412     }
    413     lhs_name = toy_tok_sym(p, p->cur);
    414     toy_parser_advance(p);
    415     if (!toy_parser_expect(p, TOK_COMMA) || p->cur.kind != TOK_IDENT) {
    416       toy_error(p, p->cur.loc, "expected symdiff rhs symbol");
    417       return 0;
    418     }
    419     rhs_name = toy_tok_sym(p, p->cur);
    420     toy_parser_advance(p);
    421     if (!toy_parser_expect(p, TOK_COMMA) || !toy_parse_number_arg(p, &addend) ||
    422         !toy_parser_expect(p, TOK_RPAREN)) {
    423       toy_error(p, p->cur.loc, "invalid symdiff initializer");
    424       return 0;
    425     }
    426     lhs_sym = toy_find_decl_sym(p, lhs_name);
    427     rhs_sym = toy_find_decl_sym(p, rhs_name);
    428     if (lhs_sym == KIT_CG_SYM_NONE || rhs_sym == KIT_CG_SYM_NONE) {
    429       toy_error(p, p->cur.loc, "undefined symdiff symbol");
    430       return 0;
    431     }
    432     kit_cg_data_symdiff(p->cg, lhs_sym, rhs_sym, addend, (uint32_t)elem_size);
    433     *pos += elem_size;
    434     return 1;
    435   }
    436   if (toy_sym_is(p, name, "labeladdr")) {
    437     KitSym label_name;
    438     ToyLabel* label;
    439     if (kit_cg_type_kind(p->c, elem_ty) != KIT_CG_TYPE_PTR || elem_size == 0 ||
    440         elem_size > 8) {
    441       toy_error(p, p->cur.loc, "labeladdr requires pointer initializer slot");
    442       return 0;
    443     }
    444     if (pos && *pos + elem_size > total_size) {
    445       toy_error(p, p->cur.loc, "too many array initializer elements");
    446       return 0;
    447     }
    448     if (!toy_parser_expect(p, TOK_LPAREN) || p->cur.kind != TOK_IDENT) {
    449       toy_error(p, p->cur.loc, "expected labeladdr label");
    450       return 0;
    451     }
    452     label_name = toy_tok_sym(p, p->cur);
    453     toy_parser_advance(p);
    454     if (!toy_parser_expect(p, TOK_RPAREN)) return 0;
    455     label = toy_find_label(p, label_name);
    456     if (!label) {
    457       toy_error(p, p->cur.loc, "unknown label");
    458       return 0;
    459     }
    460     kit_cg_data_label_addr(p->cg, label->label, 0, (uint32_t)elem_size, 0);
    461     *pos += elem_size;
    462     return 1;
    463   }
    464   if (elem_size != 1) {
    465     toy_error(p, p->cur.loc, "data initializer builtin requires byte array");
    466     return 0;
    467   }
    468   if (toy_sym_is(p, name, "pad")) {
    469     int64_t size;
    470     int64_t value;
    471     if (!toy_parser_expect(p, TOK_LPAREN) || !toy_parse_number_arg(p, &size) ||
    472         !toy_parser_expect(p, TOK_COMMA) || !toy_parse_number_arg(p, &value) ||
    473         !toy_parser_expect(p, TOK_RPAREN)) {
    474       return 0;
    475     }
    476     if (size < 0 || value < 0 || value > 255 ||
    477         *pos + (uint64_t)size > total_size) {
    478       toy_error(p, p->cur.loc, "invalid data pad initializer");
    479       return 0;
    480     }
    481     kit_cg_data_pad(p->cg, (uint64_t)size, (uint8_t)value);
    482     *pos += (uint64_t)size;
    483     return 1;
    484   }
    485   if (toy_sym_is(p, name, "align")) {
    486     int64_t align;
    487     uint64_t aligned;
    488     if (!toy_parser_expect(p, TOK_LPAREN) || !toy_parse_number_arg(p, &align) ||
    489         !toy_parser_expect(p, TOK_RPAREN)) {
    490       return 0;
    491     }
    492     if (align <= 0 || (align & (align - 1)) != 0) {
    493       toy_error(p, p->cur.loc, "invalid data alignment");
    494       return 0;
    495     }
    496     aligned = (*pos + (uint64_t)align - 1u) & ~((uint64_t)align - 1u);
    497     if (aligned > total_size) {
    498       toy_error(p, p->cur.loc, "data alignment exceeds initializer size");
    499       return 0;
    500     }
    501     kit_cg_data_align(p->cg, (uint32_t)align);
    502     *pos = aligned;
    503     return 1;
    504   }
    505   toy_error(p, p->cur.loc, "unknown data initializer builtin");
    506   return 0;
    507 }