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 }