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 }