expr.c (64055B)
1 #include <stddef.h> 2 #include <stdint.h> 3 #include <stdio.h> 4 #include <string.h> 5 6 #include "internal.h" 7 8 /* Public CG API coverage goals for this frontend are tracked in 9 * doc/toy-todo.md. Keep this file aligned with include/kit/cg.h rather than 10 * private CG implementation details. */ 11 12 /* ============================================================ 13 * Parser (single-pass parse -> codegen) 14 * ============================================================ */ 15 16 /* ============================================================ 17 * Expression parsing 18 * ============================================================ */ 19 20 KitCgTypeId toy_parse_expr(ToyParser* p); 21 KitCgMemAccess toy_mem_access(ToyParser* p, KitCgTypeId type); 22 KitCgTypeId toy_emit_var_lvalue(ToyParser* p, KitSym name); 23 24 static void toy_note_cg_result_type(ToyParser* p, KitCgTypeId ty) { 25 p->last_type = toy_type_from_cg(p, ty); 26 } 27 28 static void toy_note_builtin_result_type(ToyParser* p, KitCgTypeId ty) { 29 KitCgTypeId last_cg = toy_type_resolved_cg(p, p->last_type); 30 if (last_cg != ty) toy_note_cg_result_type(p, ty); 31 } 32 33 static int toy_reject_tail_call_operand(ToyParser* p) { 34 if (!p->tail_call_expr) return 0; 35 toy_error(p, p->cur.loc, "tail @call must be returned directly"); 36 return 1; 37 } 38 39 KitCgTypeId toy_push_named_rvalue(ToyParser* p, KitSym name) { 40 ToyVar* v = toy_find_var(p, name); 41 if (v) { 42 if (kit_cg_type_kind(p->c, v->type) == KIT_CG_TYPE_RECORD) { 43 /* Record: leave the address (pointer VALUE) for the caller's copy. */ 44 toy_push_var_lvalue(p, v); 45 } else if (v->is_static) { 46 /* Static scalar: its address is a pointer; deref to a place, then load. 47 */ 48 kit_cg_push_symbol_addr(p->cg, v->static_sym, 0); 49 kit_cg_deref(p->cg, 0); 50 kit_cg_load(p->cg, toy_mem_access(p, v->type)); 51 } else { 52 /* Local scalar: the local's PLACE loads directly (no address round-trip, 53 * which keeps small accessors inlinable). */ 54 kit_cg_push_local(p->cg, v->local); 55 kit_cg_load(p->cg, toy_mem_access(p, v->type)); 56 } 57 p->last_type = v->toy_type; 58 return v->type; 59 } 60 { 61 ToyGlobal* g = toy_find_global(p, name); 62 if (g) { 63 kit_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0); 64 if (kit_cg_type_kind(p->c, g->type) != KIT_CG_TYPE_RECORD) { 65 kit_cg_deref(p->cg, 0); 66 kit_cg_load(p->cg, toy_mem_access(p, g->type)); 67 } 68 p->last_type = g->toy_type; 69 return g->type; 70 } 71 } 72 { 73 ToyFn* fn = toy_find_fn(p, name); 74 if (fn) { 75 KitCgTypeId ptr_ty = kit_cg_type_ptr(p->c, fn->type, 0); 76 kit_cg_push_symbol_addr(p->cg, toy_fn_cur_sym(p, fn), 0); 77 p->last_type = toy_type_register_ptr(p, ptr_ty, fn->toy_type, 0); 78 return ptr_ty; 79 } 80 } 81 return KIT_CG_TYPE_NONE; 82 } 83 84 int toy_parse_call_args(ToyParser* p, ToyToken call_tok, KitCgTypeId fn_ty, 85 const ToyTypeId* toy_params, size_t toy_nparams, 86 size_t* out_nargs) { 87 uint32_t nparams = kit_cg_type_func_nparams(p->c, fn_ty); 88 int variadic = kit_cg_type_func_is_variadic(p->c, fn_ty); 89 size_t nargs = 0; 90 if (p->cur.kind != TOK_RPAREN) { 91 for (;;) { 92 KitCgTypeId arg_ty; 93 if (nargs < nparams && p->cur.kind == TOK_DOT) { 94 KitCgFuncParam param = 95 kit_cg_type_func_param(p->c, fn_ty, (uint32_t)nargs); 96 ToyNamedType* named = toy_find_named_type_by_type(p, param.type); 97 KitSym value_name; 98 size_t i; 99 int found = 0; 100 int64_t value = 0; 101 toy_parser_advance(p); /* . */ 102 if (p->cur.kind != TOK_IDENT) { 103 toy_error(p, p->cur.loc, "expected enum value"); 104 return 0; 105 } 106 value_name = toy_tok_sym(p, p->cur); 107 toy_parser_advance(p); 108 if (!named || named->kind != TOY_NAMED_ENUM) { 109 toy_error(p, p->cur.loc, "dot argument requires enum parameter"); 110 return 0; 111 } 112 for (i = 0; i < named->nenum_values; ++i) { 113 if (named->enum_values[i].name == value_name) { 114 found = 1; 115 value = named->enum_values[i].value; 116 break; 117 } 118 } 119 if (!found) { 120 toy_error(p, p->cur.loc, "unknown enum value"); 121 return 0; 122 } 123 kit_cg_push_int(p->cg, (uint64_t)value, param.type); 124 arg_ty = param.type; 125 p->last_type = (toy_params && nargs < toy_nparams) 126 ? toy_params[nargs] 127 : toy_type_from_cg(p, arg_ty); 128 } else { 129 arg_ty = toy_parse_expr(p); 130 } 131 if (arg_ty == KIT_CG_TYPE_NONE) return 0; 132 if (toy_reject_tail_call_operand(p)) return 0; 133 if (nargs < nparams) { 134 KitCgFuncParam param = 135 kit_cg_type_func_param(p->c, fn_ty, (uint32_t)nargs); 136 ToyTypeId expected = (toy_params && nargs < toy_nparams) 137 ? toy_params[nargs] 138 : TOY_TYPE_NONE; 139 ToyTypeId actual = p->last_type; 140 if (expected != TOY_TYPE_NONE && 141 !toy_type_accepts_type(p, expected, actual)) { 142 toy_error(p, call_tok.loc, "function argument type mismatch"); 143 return 0; 144 } 145 if (expected == TOY_TYPE_NONE && 146 !toy_type_can_implicitly_cast(p, arg_ty, param.type)) { 147 toy_error(p, call_tok.loc, "function argument type mismatch"); 148 return 0; 149 } 150 if (arg_ty != param.type) { 151 if (expected != TOY_TYPE_NONE) { 152 if (!toy_emit_checked_cast(p, arg_ty, param.type)) return 0; 153 } else if (!toy_emit_implicit_cast(p, arg_ty, param.type)) { 154 return 0; 155 } 156 } 157 } else if (!variadic) { 158 toy_error(p, call_tok.loc, "too many arguments"); 159 return 0; 160 } 161 nargs++; 162 if (!toy_parser_match(p, TOK_COMMA)) break; 163 } 164 } 165 if (!toy_parser_expect(p, TOK_RPAREN)) { 166 toy_error(p, p->cur.loc, "expected ')' after arguments"); 167 return 0; 168 } 169 if (nargs < nparams) { 170 toy_error(p, call_tok.loc, "too few arguments"); 171 return 0; 172 } 173 *out_nargs = nargs; 174 return 1; 175 } 176 177 KitCgMemAccess toy_mem_access(ToyParser* p, KitCgTypeId type) { 178 KitCgMemAccess access; 179 (void)p; 180 memset(&access, 0, sizeof access); 181 access.type = type; 182 return access; 183 } 184 185 static int toy_type_is_promotable_int(ToyParser* p, KitCgTypeId ty) { 186 return kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_INT; 187 } 188 189 static KitCgTypeId toy_int_literal_type(ToyParser* p, int64_t value) { 190 if (value <= INT8_MAX) return toy_builtin_type(p, KIT_CG_BUILTIN_I8); 191 if (value <= INT16_MAX) return toy_builtin_type(p, KIT_CG_BUILTIN_I16); 192 if (value <= INT32_MAX) return toy_builtin_type(p, KIT_CG_BUILTIN_I32); 193 return toy_builtin_type(p, KIT_CG_BUILTIN_I64); 194 } 195 196 int toy_type_can_implicitly_cast(ToyParser* p, KitCgTypeId src, 197 KitCgTypeId dst) { 198 KitCgTypeKind sk, dk; 199 if (src == dst) return 1; 200 sk = kit_cg_type_kind(p->c, src); 201 dk = kit_cg_type_kind(p->c, dst); 202 if (sk == KIT_CG_TYPE_INT && dk == KIT_CG_TYPE_INT) 203 return toy_type_int_width(p, src) <= toy_type_int_width(p, dst); 204 if (sk == KIT_CG_TYPE_FLOAT && dk == KIT_CG_TYPE_FLOAT) 205 return kit_cg_type_float_width(p->c, src) <= 206 kit_cg_type_float_width(p->c, dst); 207 return 0; 208 } 209 210 int toy_emit_cast(ToyParser* p, KitCgTypeId src, KitCgTypeId dst) { 211 KitCgTypeKind sk, dk; 212 if (src == dst) return 1; 213 sk = kit_cg_type_kind(p->c, src); 214 dk = kit_cg_type_kind(p->c, dst); 215 216 if (dk == KIT_CG_TYPE_BOOL && toy_type_is_intlike(p, src)) { 217 kit_cg_push_int(p->cg, 0, src); 218 kit_cg_int_cmp(p->cg, KIT_CG_INT_NE); 219 return 1; 220 } 221 if (toy_type_is_intlike(p, src) && toy_type_is_intlike(p, dst)) { 222 uint32_t sw = toy_type_int_width(p, src); 223 uint32_t dw = toy_type_int_width(p, dst); 224 if (dw > sw && sk == KIT_CG_TYPE_BOOL) 225 kit_cg_zext(p->cg, dst); 226 else if (dw > sw) 227 kit_cg_sext(p->cg, dst); 228 else if (dw < sw) 229 kit_cg_trunc(p->cg, dst); 230 return 1; 231 } 232 if (toy_type_is_intlike(p, src) && dk == KIT_CG_TYPE_FLOAT) { 233 kit_cg_sint_to_float(p->cg, dst, KIT_CG_ROUND_DEFAULT); 234 return 1; 235 } 236 if (sk == KIT_CG_TYPE_FLOAT && toy_type_is_intlike(p, dst)) { 237 kit_cg_float_to_sint(p->cg, dst, KIT_CG_ROUND_TOWARD_ZERO); 238 return 1; 239 } 240 if (sk == KIT_CG_TYPE_FLOAT && dk == KIT_CG_TYPE_FLOAT) { 241 uint32_t sw = kit_cg_type_float_width(p->c, src); 242 uint32_t dw = kit_cg_type_float_width(p->c, dst); 243 if (dw > sw) 244 kit_cg_fpext(p->cg, dst); 245 else if (dw < sw) 246 kit_cg_fptrunc(p->cg, dst); 247 return 1; 248 } 249 if (sk == KIT_CG_TYPE_PTR && toy_type_is_intlike(p, dst)) { 250 kit_cg_ptr_to_int(p->cg, dst); 251 return 1; 252 } 253 if (toy_type_is_intlike(p, src) && dk == KIT_CG_TYPE_PTR) { 254 kit_cg_int_to_ptr(p->cg, dst); 255 return 1; 256 } 257 if (sk == KIT_CG_TYPE_PTR && dk == KIT_CG_TYPE_PTR) { 258 kit_cg_bitcast(p->cg, dst); 259 return 1; 260 } 261 toy_error(p, p->cur.loc, "unsupported cast"); 262 return 0; 263 } 264 265 int toy_emit_implicit_cast(ToyParser* p, KitCgTypeId src, KitCgTypeId dst) { 266 if (src == dst) return 1; 267 if (!toy_type_can_implicitly_cast(p, src, dst)) { 268 toy_error(p, p->cur.loc, "implicit conversion would lose information"); 269 return 0; 270 } 271 return toy_emit_cast(p, src, dst); 272 } 273 274 int toy_emit_checked_cast(ToyParser* p, KitCgTypeId src, KitCgTypeId dst) { 275 KitCgTypeKind sk, dk; 276 if (src == dst) return 1; 277 if (toy_type_can_implicitly_cast(p, src, dst)) 278 return toy_emit_cast(p, src, dst); 279 sk = kit_cg_type_kind(p->c, src); 280 dk = kit_cg_type_kind(p->c, dst); 281 if (sk == KIT_CG_TYPE_PTR && dk == KIT_CG_TYPE_PTR) { 282 kit_cg_bitcast(p->cg, dst); 283 return 1; 284 } 285 toy_error(p, p->cur.loc, "unsupported checked conversion"); 286 return 0; 287 } 288 289 static int toy_promote_right_operand(ToyParser* p, KitCgTypeId src, 290 KitCgTypeId dst) { 291 return toy_emit_implicit_cast(p, src, dst); 292 } 293 294 static int toy_promote_left_operand(ToyParser* p, KitCgTypeId src, 295 KitCgTypeId dst) { 296 kit_cg_swap(p->cg); 297 if (!toy_emit_implicit_cast(p, src, dst)) return 0; 298 kit_cg_swap(p->cg); 299 return 1; 300 } 301 302 static int toy_promote_binary_int_operands(ToyParser* p, KitCgTypeId* left, 303 KitCgTypeId* right) { 304 uint32_t lw, rw; 305 if (*left == *right) return 1; 306 if (!toy_type_is_promotable_int(p, *left) || 307 !toy_type_is_promotable_int(p, *right)) 308 return 0; 309 lw = toy_type_int_width(p, *left); 310 rw = toy_type_int_width(p, *right); 311 if (lw < rw) { 312 if (!toy_promote_left_operand(p, *left, *right)) return 0; 313 *left = *right; 314 } else if (rw < lw) { 315 if (!toy_promote_right_operand(p, *right, *left)) return 0; 316 *right = *left; 317 } else { 318 return 0; 319 } 320 return 1; 321 } 322 323 KitCgLocalAttrs toy_slot_attrs(KitSym name) { 324 KitCgLocalAttrs attrs; 325 memset(&attrs, 0, sizeof attrs); 326 attrs.name = name; 327 return attrs; 328 } 329 330 KitSym toy_c_linkage_name(ToyParser* p, KitSym source_name) { 331 KitSym linkage_name = kit_cg_c_linkage_name(p->c, source_name); 332 if (!linkage_name) { 333 toy_error(p, p->cur.loc, "failed to create linkage name"); 334 } 335 return linkage_name; 336 } 337 338 void toy_inline_asm(ToyParser* p, KitSym tmpl, const KitCgAsmOperand* outputs, 339 uint32_t noutputs, const KitCgAsmOperand* inputs, 340 uint32_t ninputs, const KitSym* clobbers, 341 uint32_t nclobbers, uint32_t flags, 342 uint32_t clobber_abi_sets) { 343 KitCgInlineAsm asm_block; 344 memset(&asm_block, 0, sizeof asm_block); 345 asm_block.tmpl = tmpl; 346 asm_block.outputs = outputs; 347 asm_block.noutputs = noutputs; 348 asm_block.inputs = inputs; 349 asm_block.ninputs = ninputs; 350 asm_block.clobbers = clobbers; 351 asm_block.nclobbers = nclobbers; 352 asm_block.flags = flags; 353 asm_block.clobber_abi_sets = clobber_abi_sets; 354 kit_cg_inline_asm(p->cg, asm_block); 355 } 356 357 int toy_emit_truthy(ToyParser* p, KitCgTypeId type) { 358 if (type == toy_builtin_type(p, KIT_CG_BUILTIN_BOOL)) return 1; 359 if (toy_type_is_intlike(p, type)) { 360 kit_cg_push_int(p->cg, 0, type); 361 kit_cg_int_cmp(p->cg, KIT_CG_INT_NE); 362 return 1; 363 } 364 toy_error(p, p->cur.loc, "condition must be int or bool"); 365 return 0; 366 } 367 368 static int toy_note_expr_island(ToyParser* p, ToyExprIsland island) { 369 uint32_t prior = p->expr_island_mask; 370 if (prior && prior != (uint32_t)island) { 371 toy_error(p, p->cur.loc, "mixed precedence islands require parentheses"); 372 return 0; 373 } 374 p->expr_island_mask |= (uint32_t)island; 375 return 1; 376 } 377 378 int toy_expect_comma(ToyParser* p) { 379 if (!toy_parser_expect(p, TOK_COMMA)) { 380 toy_error(p, p->cur.loc, "expected ','"); 381 return 0; 382 } 383 return 1; 384 } 385 386 static int toy_parse_dot_constant_value(ToyParser* p, int64_t* out) { 387 KitSym name; 388 if (!toy_parser_expect(p, TOK_DOT) || p->cur.kind != TOK_IDENT) { 389 toy_error(p, p->cur.loc, "expected dot constant"); 390 return 0; 391 } 392 name = toy_tok_sym(p, p->cur); 393 toy_parser_advance(p); 394 if (toy_sym_is(p, name, "arm64")) 395 *out = 1; 396 else if (toy_sym_is(p, name, "x64")) 397 *out = 2; 398 else if (toy_sym_is(p, name, "rv64")) 399 *out = 3; 400 else if (toy_sym_is(p, name, "x86")) 401 *out = 4; 402 else if (toy_sym_is(p, name, "arm32")) 403 *out = 5; 404 else if (toy_sym_is(p, name, "rv32")) 405 *out = 6; 406 else if (toy_sym_is(p, name, "wasm")) 407 *out = 7; 408 else { 409 toy_error(p, p->cur.loc, "unknown dot constant"); 410 return 0; 411 } 412 return 1; 413 } 414 415 int toy_parse_switch_label_value(ToyParser* p, KitCgTypeId selector_ty, 416 int64_t* out) { 417 ToyNamedType* named; 418 KitSym value_name; 419 size_t i; 420 if (p->cur.kind != TOK_DOT) return toy_parse_number_arg(p, out); 421 named = toy_find_named_type_by_type(p, selector_ty); 422 if (!named || named->kind != TOY_NAMED_ENUM) 423 return toy_parse_dot_constant_value(p, out); 424 toy_parser_advance(p); /* . */ 425 if (p->cur.kind != TOK_IDENT) { 426 toy_error(p, p->cur.loc, "expected enum value"); 427 return 0; 428 } 429 value_name = toy_tok_sym(p, p->cur); 430 toy_parser_advance(p); 431 for (i = 0; i < named->nenum_values; ++i) { 432 if (named->enum_values[i].name == value_name) { 433 *out = named->enum_values[i].value; 434 return 1; 435 } 436 } 437 toy_error(p, p->cur.loc, "unknown enum value"); 438 return 0; 439 } 440 441 int toy_parse_symbol_feature_const(ToyParser* p, KitCgSymbolFeature* out) { 442 static const ToyConstRow rows[] = { 443 {"weak", KIT_CG_SYMFEAT_WEAK}, 444 {"protected_visibility", KIT_CG_SYMFEAT_PROTECTED_VISIBILITY}, 445 {"dllimport", KIT_CG_SYMFEAT_DLLIMPORT}, 446 {"dllexport", KIT_CG_SYMFEAT_DLLEXPORT}, 447 {"comdat", KIT_CG_SYMFEAT_COMDAT}, 448 {"common", KIT_CG_SYMFEAT_COMMON}, 449 {"merge_sections", KIT_CG_SYMFEAT_MERGE_SECTIONS}, 450 {"constructor_priority", KIT_CG_SYMFEAT_CONSTRUCTOR_PRIORITY}, 451 {"tls_local_exec", KIT_CG_SYMFEAT_TLS_LOCAL_EXEC}, 452 {"tls_initial_exec", KIT_CG_SYMFEAT_TLS_INITIAL_EXEC}, 453 {"tls_local_dynamic", KIT_CG_SYMFEAT_TLS_LOCAL_DYNAMIC}, 454 {"tls_general_dynamic", KIT_CG_SYMFEAT_TLS_GENERAL_DYNAMIC}, 455 }; 456 uint64_t v; 457 if (!toy_parse_dot_const(p, rows, sizeof rows / sizeof rows[0], 1, 458 "symbol feature", "symbol feature", &v)) 459 return 0; 460 *out = (KitCgSymbolFeature)v; 461 return 1; 462 } 463 464 int toy_parse_backend_feature_const(ToyParser* p, uint64_t* out) { 465 static const ToyConstRow rows[] = { 466 {"unaligned_memory", KIT_CG_BACKEND_UNALIGNED_MEMORY}, 467 {"strict_alignment", KIT_CG_BACKEND_STRICT_ALIGNMENT}, 468 {"red_zone", KIT_CG_BACKEND_RED_ZONE}, 469 {"simd", KIT_CG_BACKEND_SIMD}, 470 {"pointer_auth", KIT_CG_BACKEND_POINTER_AUTH}, 471 {"branch_protection", KIT_CG_BACKEND_BRANCH_PROTECTION}, 472 }; 473 return toy_parse_dot_const(p, rows, sizeof rows / sizeof rows[0], 1, 474 "backend feature", "backend feature", out); 475 } 476 477 int toy_parse_intrinsic_const(ToyParser* p, KitCgIntrinsic* out) { 478 static const ToyConstRow rows[] = { 479 {"cpu_nop", KIT_CG_INTRIN_CPU_NOP}, 480 {"cpu_yield", KIT_CG_INTRIN_CPU_YIELD}, 481 {"wfi", KIT_CG_INTRIN_WFI}, 482 {"wfe", KIT_CG_INTRIN_WFE}, 483 {"sev", KIT_CG_INTRIN_SEV}, 484 {"isb", KIT_CG_INTRIN_ISB}, 485 {"dmb", KIT_CG_INTRIN_DMB}, 486 {"dsb", KIT_CG_INTRIN_DSB}, 487 {"irq_save", KIT_CG_INTRIN_IRQ_SAVE}, 488 {"irq_restore", KIT_CG_INTRIN_IRQ_RESTORE}, 489 {"irq_enable", KIT_CG_INTRIN_IRQ_ENABLE}, 490 {"irq_disable", KIT_CG_INTRIN_IRQ_DISABLE}, 491 {"syscall", KIT_CG_INTRIN_SYSCALL}, 492 {"coro_switch", KIT_CG_INTRIN_CORO_SWITCH}, 493 }; 494 uint64_t v; 495 if (!toy_parse_dot_const(p, rows, sizeof rows / sizeof rows[0], 1, 496 "intrinsic name", "intrinsic", &v)) 497 return 0; 498 *out = (KitCgIntrinsic)v; 499 return 1; 500 } 501 502 int toy_parse_rounding_const(ToyParser* p, KitCgRounding* out) { 503 static const ToyConstRow rows[] = { 504 {"default", KIT_CG_ROUND_DEFAULT}, 505 {"nearest_even", KIT_CG_ROUND_NEAREST_EVEN}, 506 {"toward_zero", KIT_CG_ROUND_TOWARD_ZERO}, 507 {"down", KIT_CG_ROUND_DOWN}, 508 {"up", KIT_CG_ROUND_UP}, 509 }; 510 uint64_t v; 511 if (!toy_parse_dot_const(p, rows, sizeof rows / sizeof rows[0], 0, NULL, 512 "rounding mode", &v)) 513 return 0; 514 *out = (KitCgRounding)v; 515 return 1; 516 } 517 518 int toy_validate_bit_range(ToyParser* p, KitCgTypeId ty, int64_t lo, 519 int64_t width, int allow_full_width) { 520 uint32_t type_width; 521 if (!toy_type_is_intlike(p, ty) || lo < 0 || width <= 0) return 0; 522 type_width = toy_type_int_width(p, ty); 523 if (width > (int64_t)type_width) return 0; 524 if (!allow_full_width && width >= 64) return 0; 525 if (lo > (int64_t)type_width || width > (int64_t)type_width - lo) return 0; 526 return 1; 527 } 528 529 int toy_target_code(ToyParser* p) { 530 switch (p->target.arch) { 531 case KIT_ARCH_ARM_64: 532 return 1; 533 case KIT_ARCH_X86_64: 534 return 2; 535 case KIT_ARCH_RV64: 536 return 3; 537 case KIT_ARCH_RV32: 538 return 6; 539 case KIT_ARCH_WASM: 540 return 7; 541 default: 542 return 0; 543 } 544 } 545 546 int toy_parse_arch_string(ToyParser* p, KitSym* out, size_t* len_out) { 547 if (p->cur.kind == TOK_STRING) return toy_parse_string_sym(p, out, len_out); 548 549 toy_error(p, p->cur.loc, "expected asm template"); 550 return 0; 551 } 552 553 static int toy_emit_var_addr(ToyParser* p, KitSym name) { 554 ToyVar* v = toy_find_var(p, name); 555 if (v) { 556 toy_push_var_addr(p, v); 557 return 1; 558 } 559 { 560 ToyGlobal* g = toy_find_global(p, name); 561 if (g) { 562 kit_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0); 563 return 1; 564 } 565 } 566 return 0; 567 } 568 569 KitCgTypeId toy_emit_var_lvalue(ToyParser* p, KitSym name) { 570 ToyVar* v = toy_find_var(p, name); 571 if (v) { 572 toy_push_var_lvalue(p, v); 573 return v->type; 574 } 575 { 576 ToyGlobal* g = toy_find_global(p, name); 577 if (g) { 578 kit_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0); 579 return g->type; 580 } 581 } 582 return KIT_CG_TYPE_NONE; 583 } 584 585 static KitCgTypeId toy_type_id_cg_or_none(ToyParser* p, ToyTypeId id) { 586 KitCgTypeId ty = toy_type_resolved_cg(p, id); 587 return ty != KIT_CG_TYPE_NONE ? ty : toy_type_cg(p, id); 588 } 589 590 static void toy_store_tos_to_local(ToyParser* p, KitCgLocal local, 591 KitCgTypeId ty) { 592 kit_cg_push_local(p->cg, local); 593 kit_cg_swap(p->cg); 594 kit_cg_store(p->cg, toy_mem_access(p, ty)); 595 } 596 597 /* Consumes [slice_base, idx] where slice_base is a pointer to the slice 598 * record. Produces [elem_ptr] -- a pointer-rvalue to the element. */ 599 KitCgTypeId toy_emit_slice_index_lvalue(ToyParser* p, KitCgTypeId slice_ty, 600 ToyTypeId slice_toy_type, 601 ToyTypeId* elem_toy_out) { 602 ToyTypeId elem_toy = toy_type_slice_elem(p, slice_toy_type); 603 KitCgTypeId elem_ty = toy_type_id_cg_or_none(p, elem_toy); 604 KitCgField ptr_field; 605 KitCgLocal idx_slot; 606 uint64_t ptr_field_off = 0; 607 if (elem_ty == KIT_CG_TYPE_NONE || 608 kit_cg_type_kind(p->c, slice_ty) != KIT_CG_TYPE_RECORD || 609 kit_cg_type_record_field(p->c, slice_ty, 0, &ptr_field, &ptr_field_off) != 610 0) { 611 toy_error(p, p->cur.loc, "cannot index non-array/non-pointer"); 612 return KIT_CG_TYPE_NONE; 613 } 614 /* Stash the index, then load the slice's ptr field, then re-push idx 615 * and compute element pointer. */ 616 idx_slot = kit_cg_local(p->cg, p->size_type, toy_slot_attrs(0)); 617 toy_store_tos_to_local(p, idx_slot, p->size_type); 618 kit_cg_deref(p->cg, (int64_t)ptr_field_off); 619 kit_cg_load(p->cg, toy_mem_access(p, ptr_field.type)); 620 kit_cg_push_local(p->cg, idx_slot); 621 kit_cg_load(p->cg, toy_mem_access(p, p->size_type)); 622 toy_addr_index(p, kit_cg_type_size(p->c, elem_ty), 623 kit_cg_type_ptr(p->c, elem_ty, 0)); 624 if (elem_toy_out) *elem_toy_out = elem_toy; 625 return elem_ty; 626 } 627 628 KitCgTypeId toy_emit_slice_value(ToyParser* p, KitCgTypeId base_ty, 629 ToyTypeId base_toy_type, KitCgTypeId start_ty, 630 KitCgTypeId end_ty, ToyTypeId* slice_toy_out) { 631 ToyTypeId elem_toy = TOY_TYPE_NONE; 632 KitCgTypeId elem_ty = KIT_CG_TYPE_NONE; 633 ToyTypeId slice_toy; 634 KitCgTypeId slice_ty; 635 KitCgField ptr_field; 636 KitCgLocal start_slot; 637 KitCgLocal end_slot; 638 KitCgLocal result_slot; 639 640 if (start_ty != p->size_type || end_ty != p->size_type) { 641 toy_error(p, p->cur.loc, "slice bounds must be isize"); 642 return KIT_CG_TYPE_NONE; 643 } 644 645 if (kit_cg_type_kind(p->c, base_ty) == KIT_CG_TYPE_ARRAY) { 646 elem_ty = kit_cg_type_array_elem(p->c, base_ty); 647 elem_toy = toy_type_array_elem(p, base_toy_type); 648 } else if (toy_type_is_slice(p, base_toy_type)) { 649 elem_toy = toy_type_slice_elem(p, base_toy_type); 650 elem_ty = toy_type_id_cg_or_none(p, elem_toy); 651 } 652 if (elem_toy == TOY_TYPE_NONE && elem_ty != KIT_CG_TYPE_NONE) 653 elem_toy = toy_type_from_cg(p, elem_ty); 654 if (elem_ty == KIT_CG_TYPE_NONE || elem_toy == TOY_TYPE_NONE) { 655 toy_error(p, p->cur.loc, "cannot slice non-array/non-slice"); 656 return KIT_CG_TYPE_NONE; 657 } 658 659 slice_toy = toy_type_register_slice(p, elem_ty, elem_toy); 660 slice_ty = toy_type_cg(p, slice_toy); 661 { 662 uint64_t ptr_off = 0; 663 uint64_t len_off = 0; 664 KitCgField len_field; 665 (void)len_field; 666 if (slice_ty == KIT_CG_TYPE_NONE || 667 kit_cg_type_record_field(p->c, slice_ty, 0, &ptr_field, &ptr_off) != 668 0 || 669 kit_cg_type_record_field(p->c, slice_ty, 1, &len_field, &len_off) != 670 0) { 671 toy_error(p, p->cur.loc, "failed to create slice type"); 672 return KIT_CG_TYPE_NONE; 673 } 674 675 end_slot = kit_cg_local(p->cg, p->size_type, toy_slot_attrs(0)); 676 toy_store_tos_to_local(p, end_slot, p->size_type); 677 start_slot = kit_cg_local(p->cg, p->size_type, toy_slot_attrs(0)); 678 toy_store_tos_to_local(p, start_slot, p->size_type); 679 680 result_slot = kit_cg_local(p->cg, slice_ty, toy_slot_attrs(0)); 681 /* TOS = [base] (slice lvalue/pointer or array lvalue/pointer). */ 682 if (toy_type_is_slice(p, base_toy_type)) { 683 /* Replace slice base with its data pointer (a pointer-rvalue). */ 684 kit_cg_deref(p->cg, (int64_t)ptr_off); 685 kit_cg_load(p->cg, toy_mem_access(p, ptr_field.type)); 686 } else { 687 /* Array base: TOS is a pointer-rvalue (callers always project 688 * to a pointer for array/slice bases now). Bitcast to *elem. */ 689 kit_cg_bitcast(p->cg, kit_cg_type_ptr(p->c, elem_ty, 0)); 690 } 691 /* Compute (base + start * sizeof(elem)) as a pointer to the slice's 692 * first element. */ 693 kit_cg_push_local(p->cg, start_slot); 694 kit_cg_load(p->cg, toy_mem_access(p, p->size_type)); 695 toy_addr_index(p, kit_cg_type_size(p->c, elem_ty), 696 kit_cg_type_ptr(p->c, elem_ty, 0)); 697 /* Store the data pointer into result_slot.ptr. */ 698 kit_cg_push_local(p->cg, result_slot); 699 kit_cg_addr(p->cg); 700 kit_cg_deref(p->cg, (int64_t)ptr_off); 701 kit_cg_swap(p->cg); 702 kit_cg_store(p->cg, toy_mem_access(p, ptr_field.type)); 703 704 /* len = end - start; store into result_slot.len. */ 705 kit_cg_push_local(p->cg, result_slot); 706 kit_cg_addr(p->cg); 707 kit_cg_deref(p->cg, (int64_t)len_off); 708 kit_cg_push_local(p->cg, end_slot); 709 kit_cg_load(p->cg, toy_mem_access(p, p->size_type)); 710 kit_cg_push_local(p->cg, start_slot); 711 kit_cg_load(p->cg, toy_mem_access(p, p->size_type)); 712 kit_cg_int_binop(p->cg, KIT_CG_INT_SUB, 0); 713 kit_cg_store(p->cg, toy_mem_access(p, p->size_type)); 714 } 715 716 /* Hand back the slice record as a pointer VALUE (its address), matching the 717 * "records/slices are pointer VALUEs" shape the downstream record-copy and 718 * slice-index paths consume. */ 719 kit_cg_push_local_addr(p->cg, result_slot); 720 if (slice_toy_out) *slice_toy_out = slice_toy; 721 p->last_type = slice_toy; 722 return slice_ty; 723 } 724 725 int toy_parse_va_list_addr_arg(ToyParser* p) { 726 KitSym name; 727 ToyVar* v; 728 if (p->cur.kind != TOK_IDENT) { 729 toy_error(p, p->cur.loc, "expected va_list identifier"); 730 return 0; 731 } 732 name = toy_tok_sym(p, p->cur); 733 v = toy_find_var(p, name); 734 if (!v || v->type != p->va_list_type) { 735 toy_error(p, p->cur.loc, "expected va_list local"); 736 return 0; 737 } 738 toy_parser_advance(p); 739 return toy_emit_var_addr(p, name); 740 } 741 742 static KitCgTypeId toy_parse_expr_primary(ToyParser* p) { 743 toy_set_loc(p); 744 if (p->cur.kind == TOK_AT) { 745 KitSym name; 746 ToyToken at_tok = p->cur; 747 toy_parser_advance(p); 748 if (p->cur.kind != TOK_IDENT) { 749 toy_error(p, p->cur.loc, "expected builtin name after '@'"); 750 return KIT_CG_TYPE_NONE; 751 } 752 name = toy_tok_sym(p, p->cur); 753 toy_parser_advance(p); 754 755 if (p->cur.kind == TOK_LT) { 756 int recognized = 0; 757 KitCgTypeId builtin_ty = toy_parse_generic_builtin(p, name, &recognized); 758 if (recognized) { 759 if (builtin_ty != KIT_CG_TYPE_NONE) 760 toy_note_builtin_result_type(p, builtin_ty); 761 return builtin_ty; 762 } 763 } 764 765 if (p->cur.kind == TOK_LPAREN) { 766 int recognized = 0; 767 KitCgTypeId builtin_ty = toy_parse_builtin_call(p, name, &recognized); 768 if (recognized) { 769 if (builtin_ty != KIT_CG_TYPE_NONE) 770 toy_note_builtin_result_type(p, builtin_ty); 771 return builtin_ty; 772 } 773 } 774 775 toy_error(p, at_tok.loc, "unknown builtin"); 776 return KIT_CG_TYPE_NONE; 777 } 778 779 if (p->cur.kind == TOK_NUMBER) { 780 if (p->cur.is_float) { 781 kit_cg_push_float(p->cg, p->cur.float_value, 782 toy_builtin_type(p, KIT_CG_BUILTIN_F64)); 783 toy_parser_advance(p); 784 p->last_type = 785 toy_type_from_cg(p, toy_builtin_type(p, KIT_CG_BUILTIN_F64)); 786 return toy_builtin_type(p, KIT_CG_BUILTIN_F64); 787 } 788 { 789 KitCgTypeId lit_ty = toy_int_literal_type(p, p->cur.int_value); 790 kit_cg_push_int(p->cg, (uint64_t)p->cur.int_value, lit_ty); 791 toy_parser_advance(p); 792 p->last_type = toy_type_from_cg(p, lit_ty); 793 return lit_ty; 794 } 795 } 796 797 if (p->cur.kind == TOK_IDENT) { 798 KitSym name = toy_tok_sym(p, p->cur); 799 ToyToken ident_tok = p->cur; 800 toy_parser_advance(p); 801 802 if (toy_sym_is(p, name, "true") || toy_sym_is(p, name, "false")) { 803 kit_cg_push_int(p->cg, toy_sym_is(p, name, "true") ? 1u : 0u, 804 toy_builtin_type(p, KIT_CG_BUILTIN_BOOL)); 805 p->last_type = 806 toy_type_from_cg(p, toy_builtin_type(p, KIT_CG_BUILTIN_BOOL)); 807 return toy_builtin_type(p, KIT_CG_BUILTIN_BOOL); 808 } 809 810 if (toy_sym_is(p, name, "NULL")) { 811 kit_cg_push_int(p->cg, 0, p->int_type); 812 p->last_type = TOY_TYPE_NONE; 813 return p->int_type; 814 } 815 816 if (p->cur.kind == TOK_LT) { 817 int recognized = 0; 818 KitCgTypeId builtin_ty = toy_parse_generic_builtin(p, name, &recognized); 819 if (recognized) return builtin_ty; 820 } 821 822 if (p->cur.kind == TOK_LPAREN) { 823 /* Function call */ 824 int recognized = 0; 825 KitCgTypeId builtin_ty = toy_parse_builtin_call(p, name, &recognized); 826 if (recognized) return builtin_ty; 827 828 ToyFn* fn = toy_find_fn(p, name); 829 toy_parser_advance(p); /* ( */ 830 831 size_t nargs = 0; 832 if (fn) { 833 if (!toy_parse_call_args(p, ident_tok, fn->type, fn->toy_params, 834 fn->nparams, &nargs)) 835 return KIT_CG_TYPE_NONE; 836 { 837 KitCgCallAttrs attrs; 838 memset(&attrs, 0, sizeof attrs); 839 attrs.inline_policy = fn->func_attrs.inline_policy; 840 kit_cg_call_symbol(p->cg, toy_fn_cur_sym(p, fn), (uint32_t)nargs, 841 attrs); 842 } 843 /* An aggregate return is a PLACE; project it to a pointer VALUE so it 844 * matches the records-are-pointers invariant used downstream. */ 845 if (kit_cg_type_kind(p->c, fn->ret) == KIT_CG_TYPE_RECORD) 846 kit_cg_addr(p->cg); 847 p->last_type = fn->toy_ret; 848 return fn->ret; 849 } 850 851 KitCgTypeId callee_ty = toy_push_named_rvalue(p, name); 852 ToyTypeId callee_toy_type = p->last_type; 853 const ToyType* source_fn_type = NULL; 854 if (callee_ty == KIT_CG_TYPE_NONE) { 855 toy_error(p, ident_tok.loc, "undefined function '%.*s'", 856 (int)ident_tok.text_len, (const char*)ident_tok.text); 857 return KIT_CG_TYPE_NONE; 858 } 859 KitCgTypeId fn_ty = toy_ptr_pointee_func_type(p, callee_ty); 860 if (fn_ty == KIT_CG_TYPE_NONE) { 861 toy_error(p, ident_tok.loc, "callee is not a function pointer"); 862 return KIT_CG_TYPE_NONE; 863 } 864 source_fn_type = toy_type_get(p, toy_type_pointee(p, callee_toy_type)); 865 if (source_fn_type && source_fn_type->kind != TOY_TYPE_FUNC) 866 source_fn_type = NULL; 867 if (!toy_parse_call_args(p, ident_tok, fn_ty, 868 source_fn_type ? source_fn_type->params : NULL, 869 source_fn_type ? source_fn_type->nparams : 0, 870 &nargs)) 871 return KIT_CG_TYPE_NONE; 872 kit_cg_call_default(p->cg, (uint32_t)nargs, fn_ty); 873 if (kit_cg_type_kind(p->c, toy_cg_func_ret(p, fn_ty)) == 874 KIT_CG_TYPE_RECORD) 875 kit_cg_addr(p->cg); 876 p->last_type = source_fn_type 877 ? source_fn_type->ret 878 : toy_type_from_cg(p, toy_cg_func_ret(p, fn_ty)); 879 return toy_cg_func_ret(p, fn_ty); 880 } 881 882 if (p->cur.kind == TOK_LBRACKET || p->cur.kind == TOK_DOT) { 883 ToyVar* v = toy_find_var(p, name); 884 if (v && (kit_cg_type_kind(p->c, v->type) == KIT_CG_TYPE_ARRAY || 885 kit_cg_type_kind(p->c, v->type) == KIT_CG_TYPE_RECORD)) { 886 if (kit_cg_type_kind(p->c, v->type) == KIT_CG_TYPE_ARRAY) { 887 /* Array slicing/indexing wants a pointer root for address math. */ 888 toy_push_var_addr(p, v); 889 } else { 890 toy_push_var_lvalue(p, v); 891 } 892 p->last_type = v->toy_type; 893 return v->type; 894 } 895 { 896 ToyGlobal* g = toy_find_global(p, name); 897 if (g && (kit_cg_type_kind(p->c, g->type) == KIT_CG_TYPE_ARRAY || 898 kit_cg_type_kind(p->c, g->type) == KIT_CG_TYPE_RECORD)) { 899 kit_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0); 900 p->last_type = g->toy_type; 901 return g->type; 902 } 903 } 904 } 905 906 { 907 ToyVar* v = toy_find_var(p, name); 908 if (v && toy_type_is_slice(p, v->toy_type)) { 909 toy_push_var_lvalue(p, v); 910 p->last_type = v->toy_type; 911 return v->type; 912 } 913 { 914 ToyGlobal* g = toy_find_global(p, name); 915 if (g && toy_type_is_slice(p, g->toy_type)) { 916 kit_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0); 917 p->last_type = g->toy_type; 918 return g->type; 919 } 920 } 921 } 922 923 { 924 KitCgTypeId ty = toy_push_named_rvalue(p, name); 925 if (ty != KIT_CG_TYPE_NONE) return ty; 926 } 927 toy_error(p, ident_tok.loc, "undefined variable '%.*s'", 928 (int)ident_tok.text_len, (const char*)ident_tok.text); 929 return KIT_CG_TYPE_NONE; 930 } 931 932 if (p->cur.kind == TOK_LPAREN) { 933 toy_parser_advance(p); 934 KitCgTypeId ty = toy_parse_expr(p); 935 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 936 if (!toy_parser_expect(p, TOK_RPAREN)) { 937 toy_error(p, p->cur.loc, "expected ')'"); 938 return KIT_CG_TYPE_NONE; 939 } 940 return ty; 941 } 942 943 toy_error(p, p->cur.loc, "expected expression"); 944 return KIT_CG_TYPE_NONE; 945 } 946 947 static KitCgTypeId toy_parse_expr_postfix(ToyParser* p) { 948 KitCgTypeId ty = toy_parse_expr_primary(p); 949 ToyTypeId toy_ty = p->last_type; 950 if (p->tail_call_expr) return ty; 951 while (ty != KIT_CG_TYPE_NONE) { 952 if (toy_parser_match(p, TOK_DOTSTAR)) { 953 if (kit_cg_type_kind(p->c, ty) != KIT_CG_TYPE_PTR) { 954 toy_error(p, p->cur.loc, "cannot dereference non-pointer"); 955 return KIT_CG_TYPE_NONE; 956 } 957 ty = kit_cg_type_ptr_pointee(p->c, ty); 958 toy_ty = toy_type_pointee(p, toy_ty); 959 /* TOS is a pointer VALUE; deref it to a PLACE, then load. */ 960 kit_cg_deref(p->cg, 0); 961 kit_cg_load(p->cg, toy_mem_access(p, ty)); 962 p->last_type = toy_ty != TOY_TYPE_NONE ? toy_ty : toy_type_from_cg(p, ty); 963 continue; 964 } 965 966 if (toy_parser_match(p, TOK_LBRACKET)) { 967 KitCgTypeId idx_ty = toy_parse_expr(p); 968 if (idx_ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 969 if (!toy_type_can_implicitly_cast(p, idx_ty, p->size_type)) { 970 toy_error(p, p->cur.loc, "index must be isize"); 971 return KIT_CG_TYPE_NONE; 972 } 973 if (!toy_emit_implicit_cast(p, idx_ty, p->size_type)) 974 return KIT_CG_TYPE_NONE; 975 idx_ty = p->size_type; 976 if (toy_parser_match(p, TOK_COLON)) { 977 KitCgTypeId end_ty = toy_parse_expr(p); 978 ToyTypeId slice_toy_type = TOY_TYPE_NONE; 979 if (end_ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 980 if (!toy_type_can_implicitly_cast(p, end_ty, p->size_type)) { 981 toy_error(p, p->cur.loc, "slice bounds must be isize"); 982 return KIT_CG_TYPE_NONE; 983 } 984 if (!toy_emit_implicit_cast(p, end_ty, p->size_type)) 985 return KIT_CG_TYPE_NONE; 986 end_ty = p->size_type; 987 if (!toy_parser_expect(p, TOK_RBRACKET)) { 988 toy_error(p, p->cur.loc, "expected ']' after slice"); 989 return KIT_CG_TYPE_NONE; 990 } 991 ty = toy_emit_slice_value(p, ty, toy_ty, idx_ty, end_ty, 992 &slice_toy_type); 993 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 994 toy_ty = slice_toy_type; 995 p->last_type = toy_ty; 996 continue; 997 } 998 if (!toy_parser_expect(p, TOK_RBRACKET)) { 999 toy_error(p, p->cur.loc, "expected ']' after index"); 1000 return KIT_CG_TYPE_NONE; 1001 } 1002 if (kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_PTR) { 1003 KitCgTypeId pointee = kit_cg_type_ptr_pointee(p->c, ty); 1004 ToyTypeId source_pointee = toy_type_pointee(p, toy_ty); 1005 if (kit_cg_type_kind(p->c, pointee) == KIT_CG_TYPE_ARRAY) { 1006 /* TOS = [ptr-to-array, idx]. Cast pointer to *elem so the load 1007 * can apply the array's elem-scale on the next memop. */ 1008 KitCgTypeId elem_ty = kit_cg_type_array_elem(p->c, pointee); 1009 kit_cg_swap(p->cg); 1010 kit_cg_bitcast(p->cg, kit_cg_type_ptr(p->c, elem_ty, 0)); 1011 kit_cg_swap(p->cg); 1012 ty = elem_ty; 1013 toy_ty = toy_type_array_elem(p, source_pointee); 1014 } else { 1015 ty = pointee; 1016 toy_ty = source_pointee; 1017 } 1018 } else if (kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_ARRAY) { 1019 /* TOS = [ptr-to-array, idx]. Decay the base to *elem so kit_cg_elem 1020 * scales by the element size, not the whole array. */ 1021 KitCgTypeId elem_ty = kit_cg_type_array_elem(p->c, ty); 1022 kit_cg_swap(p->cg); 1023 kit_cg_bitcast(p->cg, kit_cg_type_ptr(p->c, elem_ty, 0)); 1024 kit_cg_swap(p->cg); 1025 ty = elem_ty; 1026 toy_ty = toy_type_array_elem(p, toy_ty); 1027 } else if (toy_type_is_slice(p, toy_ty)) { 1028 ty = toy_emit_slice_index_lvalue(p, ty, toy_ty, &toy_ty); 1029 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1030 /* toy_emit_slice_index_lvalue returns an element pointer VALUE. */ 1031 kit_cg_deref(p->cg, 0); 1032 kit_cg_load(p->cg, toy_mem_access(p, ty)); 1033 p->last_type = 1034 toy_ty != TOY_TYPE_NONE ? toy_ty : toy_type_from_cg(p, ty); 1035 continue; 1036 } else { 1037 toy_error(p, p->cur.loc, "cannot index non-array/non-pointer"); 1038 return KIT_CG_TYPE_NONE; 1039 } 1040 /* TOS = [base, idx]; elem yields the element PLACE, then load. */ 1041 kit_cg_elem(p->cg, 0); 1042 kit_cg_load(p->cg, toy_mem_access(p, ty)); 1043 p->last_type = toy_ty != TOY_TYPE_NONE ? toy_ty : toy_type_from_cg(p, ty); 1044 continue; 1045 } 1046 1047 if (toy_parser_match(p, TOK_DOT)) { 1048 KitSym field_name; 1049 uint32_t i, nfields; 1050 int found = 0; 1051 KitCgField found_field; 1052 uint64_t found_off = 0; 1053 ToyNamedType* named; 1054 ToyTypeId field_toy_type = TOY_TYPE_NONE; 1055 if (kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_PTR && 1056 kit_cg_type_kind(p->c, kit_cg_type_ptr_pointee(p->c, ty)) == 1057 KIT_CG_TYPE_RECORD) { 1058 /* TOS is a pointer to the record; the memop accepts it directly, 1059 * so no intermediate op is needed -- we just update `ty`. */ 1060 ty = kit_cg_type_ptr_pointee(p->c, ty); 1061 toy_ty = toy_type_pointee(p, toy_ty); 1062 } 1063 named = toy_find_named_type_by_type(p, ty); 1064 if (p->cur.kind == TOK_NUMBER && !p->cur.is_float) { 1065 uint32_t field_index; 1066 if (kit_cg_type_kind(p->c, ty) != KIT_CG_TYPE_RECORD || 1067 p->cur.int_value < 0 || 1068 p->cur.int_value >= (int64_t)kit_cg_type_record_nfields(p->c, ty)) { 1069 toy_error(p, p->cur.loc, "invalid tuple field"); 1070 return KIT_CG_TYPE_NONE; 1071 } 1072 field_index = (uint32_t)p->cur.int_value; 1073 toy_parser_advance(p); 1074 if (kit_cg_type_record_field(p->c, ty, field_index, &found_field, 1075 &found_off) != 0) { 1076 return KIT_CG_TYPE_NONE; 1077 } 1078 if (named && field_index < named->nfields) 1079 field_toy_type = named->fields[field_index].toy_type; 1080 ty = found_field.type; 1081 kit_cg_deref(p->cg, (int64_t)found_off); 1082 kit_cg_load(p->cg, toy_mem_access(p, ty)); 1083 if (field_toy_type != TOY_TYPE_NONE) { 1084 KitCgTypeId resolved = toy_type_resolved_cg(p, field_toy_type); 1085 p->last_type = field_toy_type; 1086 toy_ty = field_toy_type; 1087 if (resolved != KIT_CG_TYPE_NONE && resolved != ty) { 1088 if (!toy_emit_checked_cast(p, ty, resolved)) 1089 return KIT_CG_TYPE_NONE; 1090 ty = resolved; 1091 } 1092 } else { 1093 p->last_type = toy_type_from_cg(p, ty); 1094 toy_ty = p->last_type; 1095 } 1096 continue; 1097 } 1098 if (p->cur.kind != TOK_IDENT) { 1099 toy_error(p, p->cur.loc, "expected field name"); 1100 return KIT_CG_TYPE_NONE; 1101 } 1102 field_name = toy_tok_sym(p, p->cur); 1103 toy_parser_advance(p); 1104 if (kit_cg_type_kind(p->c, ty) != KIT_CG_TYPE_RECORD) { 1105 toy_error(p, p->cur.loc, "field access on non-record"); 1106 return KIT_CG_TYPE_NONE; 1107 } 1108 nfields = kit_cg_type_record_nfields(p->c, ty); 1109 memset(&found_field, 0, sizeof found_field); 1110 for (i = 0; i < nfields; ++i) { 1111 KitCgField field; 1112 uint64_t off = 0; 1113 if (kit_cg_type_record_field(p->c, ty, i, &field, &off) == 0 && 1114 field.name == field_name) { 1115 found = 1; 1116 found_field = field; 1117 found_off = off; 1118 if (named && i < named->nfields) 1119 field_toy_type = named->fields[i].toy_type; 1120 break; 1121 } 1122 } 1123 if (!found) { 1124 toy_error(p, p->cur.loc, "unknown record field"); 1125 return KIT_CG_TYPE_NONE; 1126 } 1127 ty = found_field.type; 1128 kit_cg_deref(p->cg, (int64_t)found_off); 1129 kit_cg_load(p->cg, toy_mem_access(p, ty)); 1130 if (field_toy_type != TOY_TYPE_NONE) { 1131 KitCgTypeId resolved = toy_type_resolved_cg(p, field_toy_type); 1132 p->last_type = field_toy_type; 1133 toy_ty = field_toy_type; 1134 if (resolved != KIT_CG_TYPE_NONE && resolved != ty) { 1135 if (!toy_emit_checked_cast(p, ty, resolved)) 1136 return KIT_CG_TYPE_NONE; 1137 ty = resolved; 1138 } 1139 } else { 1140 p->last_type = toy_type_from_cg(p, ty); 1141 toy_ty = p->last_type; 1142 } 1143 continue; 1144 } 1145 1146 break; 1147 } 1148 return ty; 1149 } 1150 1151 static KitCgTypeId toy_parse_expr_unary(ToyParser* p) { 1152 toy_set_loc(p); 1153 if (toy_parser_match(p, TOK_MINUS)) { 1154 KitCgTypeId ty = toy_parse_expr_unary(p); 1155 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1156 if (p->tail_call_expr) { 1157 toy_error(p, p->cur.loc, "tail @call must be returned directly"); 1158 return KIT_CG_TYPE_NONE; 1159 } 1160 if (toy_type_is_float(p, ty)) { 1161 kit_cg_fp_unop(p->cg, KIT_CG_FP_NEG, 0); 1162 return ty; 1163 } 1164 if (!toy_type_is_intlike(p, ty)) { 1165 toy_error(p, p->cur.loc, "invalid operand for unary '-'"); 1166 return KIT_CG_TYPE_NONE; 1167 } 1168 kit_cg_int_unop(p->cg, KIT_CG_INT_NEG, 0); 1169 return ty; 1170 } 1171 1172 if (toy_parser_match(p, TOK_BANG)) { 1173 KitCgTypeId ty = toy_parse_expr_unary(p); 1174 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1175 if (p->tail_call_expr) { 1176 toy_error(p, p->cur.loc, "tail @call must be returned directly"); 1177 return KIT_CG_TYPE_NONE; 1178 } 1179 if (!toy_type_is_intlike(p, ty)) { 1180 toy_error(p, p->cur.loc, "invalid operand for '!'"); 1181 return KIT_CG_TYPE_NONE; 1182 } 1183 kit_cg_int_unop(p->cg, KIT_CG_INT_NOT, 0); 1184 return ty; 1185 } 1186 1187 if (toy_parser_match(p, TOK_TILDE)) { 1188 KitCgTypeId ty = toy_parse_expr_unary(p); 1189 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1190 if (p->tail_call_expr) { 1191 toy_error(p, p->cur.loc, "tail @call must be returned directly"); 1192 return KIT_CG_TYPE_NONE; 1193 } 1194 if (!toy_type_is_intlike(p, ty)) { 1195 toy_error(p, p->cur.loc, "invalid operand for '~'"); 1196 return KIT_CG_TYPE_NONE; 1197 } 1198 kit_cg_int_unop(p->cg, KIT_CG_INT_BNOT, 0); 1199 return ty; 1200 } 1201 1202 if (toy_parser_match(p, TOK_AMPERSAND)) { 1203 KitSym name; 1204 KitCgTypeId ty; 1205 if (p->cur.kind != TOK_IDENT) { 1206 toy_error(p, p->cur.loc, "expected identifier after '&'"); 1207 return KIT_CG_TYPE_NONE; 1208 } 1209 name = toy_tok_sym(p, p->cur); 1210 toy_parser_advance(p); 1211 1212 if (p->cur.kind == TOK_LBRACKET || p->cur.kind == TOK_DOTSTAR || 1213 p->cur.kind == TOK_DOT) { 1214 /* `&expr` chain. Maintain the invariant that TOS holds a 1215 * pointer-rvalue of type *ty. The chain returns a pointer-rvalue 1216 * directly (no trailing kit_cg_addr needed). */ 1217 ToyTypeId ty_toy = TOY_TYPE_NONE; 1218 { 1219 ToyVar* v = toy_find_var(p, name); 1220 ToyGlobal* g = toy_find_global(p, name); 1221 if (v) { 1222 toy_push_var_addr(p, v); 1223 ty = v->type; 1224 ty_toy = v->toy_type; 1225 } else if (g) { 1226 kit_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0); 1227 ty = g->type; 1228 ty_toy = g->toy_type; 1229 } else { 1230 ty = KIT_CG_TYPE_NONE; 1231 } 1232 } 1233 if (ty == KIT_CG_TYPE_NONE) { 1234 toy_error(p, p->cur.loc, "undefined variable"); 1235 return KIT_CG_TYPE_NONE; 1236 } 1237 for (;;) { 1238 if (toy_parser_match(p, TOK_LBRACKET)) { 1239 KitCgTypeId idx_ty = toy_parse_expr(p); 1240 if (idx_ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1241 if (!toy_type_can_implicitly_cast(p, idx_ty, p->size_type)) { 1242 toy_error(p, p->cur.loc, "index must be isize"); 1243 return KIT_CG_TYPE_NONE; 1244 } 1245 if (!toy_emit_implicit_cast(p, idx_ty, p->size_type)) 1246 return KIT_CG_TYPE_NONE; 1247 idx_ty = p->size_type; 1248 if (!toy_parser_expect(p, TOK_RBRACKET)) { 1249 toy_error(p, p->cur.loc, "expected ']' after index"); 1250 return KIT_CG_TYPE_NONE; 1251 } 1252 if (kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_PTR) { 1253 KitCgTypeId pointee = kit_cg_type_ptr_pointee(p->c, ty); 1254 /* TOS holds **T_chain; load the inner pointer first. */ 1255 { 1256 KitCgLocal idx_slot = 1257 kit_cg_local(p->cg, p->size_type, toy_slot_attrs(0)); 1258 kit_cg_push_local(p->cg, idx_slot); 1259 kit_cg_swap(p->cg); 1260 kit_cg_store(p->cg, toy_mem_access(p, p->size_type)); 1261 /* TOS is the chain pointer VALUE (**T); deref to a PLACE and 1262 * load the inner pointer it addresses. */ 1263 kit_cg_deref(p->cg, 0); 1264 kit_cg_load(p->cg, toy_mem_access(p, ty)); 1265 kit_cg_push_local(p->cg, idx_slot); 1266 kit_cg_load(p->cg, toy_mem_access(p, p->size_type)); 1267 } 1268 if (kit_cg_type_kind(p->c, pointee) == KIT_CG_TYPE_ARRAY) { 1269 KitCgTypeId elem_ty = kit_cg_type_array_elem(p->c, pointee); 1270 ty = elem_ty; 1271 ty_toy = toy_type_array_elem(p, toy_type_pointee(p, ty_toy)); 1272 toy_addr_index(p, kit_cg_type_size(p->c, elem_ty), 1273 kit_cg_type_ptr(p->c, elem_ty, 0)); 1274 } else { 1275 ty = pointee; 1276 ty_toy = toy_type_pointee(p, ty_toy); 1277 toy_addr_index(p, kit_cg_type_size(p->c, ty), 1278 kit_cg_type_ptr(p->c, ty, 0)); 1279 } 1280 } else if (kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_ARRAY) { 1281 KitCgTypeId elem_ty = kit_cg_type_array_elem(p->c, ty); 1282 ty = elem_ty; 1283 ty_toy = toy_type_array_elem(p, ty_toy); 1284 toy_addr_index(p, kit_cg_type_size(p->c, elem_ty), 1285 kit_cg_type_ptr(p->c, elem_ty, 0)); 1286 } else if (toy_type_is_slice(p, ty_toy)) { 1287 ToyTypeId elem_toy = TOY_TYPE_NONE; 1288 ty = toy_emit_slice_index_lvalue(p, ty, ty_toy, &elem_toy); 1289 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1290 ty_toy = elem_toy; 1291 } else { 1292 toy_error(p, p->cur.loc, "cannot index non-array/non-pointer"); 1293 return KIT_CG_TYPE_NONE; 1294 } 1295 continue; 1296 } 1297 if (toy_parser_match(p, TOK_DOTSTAR)) { 1298 if (kit_cg_type_kind(p->c, ty) != KIT_CG_TYPE_PTR) { 1299 toy_error(p, p->cur.loc, "cannot dereference non-pointer"); 1300 return KIT_CG_TYPE_NONE; 1301 } 1302 /* TOS = **T (pointer VALUE); deref to PLACE and load to TOS = *T. */ 1303 kit_cg_deref(p->cg, 0); 1304 kit_cg_load(p->cg, toy_mem_access(p, ty)); 1305 ty = kit_cg_type_ptr_pointee(p->c, ty); 1306 ty_toy = toy_type_pointee(p, ty_toy); 1307 continue; 1308 } 1309 if (toy_parser_match(p, TOK_DOT)) { 1310 KitCgField field; 1311 uint32_t field_index = 0; 1312 uint64_t foff = 0; 1313 ToyNamedType* named; 1314 if (kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_PTR && 1315 kit_cg_type_kind(p->c, kit_cg_type_ptr_pointee(p->c, ty)) == 1316 KIT_CG_TYPE_RECORD) { 1317 /* TOS = **Rec (pointer VALUE); deref to PLACE and load to *Rec. */ 1318 kit_cg_deref(p->cg, 0); 1319 kit_cg_load(p->cg, toy_mem_access(p, ty)); 1320 ty = kit_cg_type_ptr_pointee(p->c, ty); 1321 ty_toy = toy_type_pointee(p, ty_toy); 1322 } 1323 if (kit_cg_type_kind(p->c, ty) != KIT_CG_TYPE_RECORD) { 1324 toy_error(p, p->cur.loc, "field access on non-record"); 1325 return KIT_CG_TYPE_NONE; 1326 } 1327 named = toy_find_named_type_by_type(p, ty); 1328 if (p->cur.kind == TOK_NUMBER && !p->cur.is_float) { 1329 if (p->cur.int_value < 0 || 1330 p->cur.int_value >= 1331 (int64_t)kit_cg_type_record_nfields(p->c, ty)) { 1332 toy_error(p, p->cur.loc, "invalid tuple field"); 1333 return KIT_CG_TYPE_NONE; 1334 } 1335 field_index = (uint32_t)p->cur.int_value; 1336 toy_parser_advance(p); 1337 if (kit_cg_type_record_field(p->c, ty, field_index, &field, 1338 &foff) != 0) 1339 return KIT_CG_TYPE_NONE; 1340 } else { 1341 KitSym field_name; 1342 if (p->cur.kind != TOK_IDENT) { 1343 toy_error(p, p->cur.loc, "expected field name"); 1344 return KIT_CG_TYPE_NONE; 1345 } 1346 field_name = toy_tok_sym(p, p->cur); 1347 toy_parser_advance(p); 1348 if (!toy_record_field_index(p, ty, field_name, &field_index, 1349 &field)) { 1350 toy_error(p, p->cur.loc, "unknown record field"); 1351 return KIT_CG_TYPE_NONE; 1352 } 1353 if (kit_cg_type_record_field(p->c, ty, field_index, NULL, &foff) != 1354 0) 1355 return KIT_CG_TYPE_NONE; 1356 } 1357 ty = field.type; 1358 ty_toy = (named && field_index < named->nfields) 1359 ? named->fields[field_index].toy_type 1360 : toy_type_from_cg(p, ty); 1361 toy_addr_offset(p, (int64_t)foff, kit_cg_type_ptr(p->c, ty, 0)); 1362 continue; 1363 } 1364 break; 1365 } 1366 /* TOS already holds a pointer-rvalue of type *ty. */ 1367 { 1368 KitCgTypeId ptr_ty = kit_cg_type_ptr(p->c, ty, 0); 1369 p->last_type = toy_type_register_ptr( 1370 p, ptr_ty, 1371 ty_toy != TOY_TYPE_NONE ? ty_toy : toy_type_from_cg(p, ty), 0); 1372 return ptr_ty; 1373 } 1374 } 1375 1376 { 1377 ToyVar* v = toy_find_var(p, name); 1378 if (v) { 1379 KitCgTypeId ptr_ty = kit_cg_type_ptr(p->c, v->type, 0); 1380 toy_push_var_addr(p, v); 1381 p->last_type = toy_type_register_ptr(p, ptr_ty, v->toy_type, 0); 1382 return ptr_ty; 1383 } else { 1384 ToyGlobal* g = toy_find_global(p, name); 1385 if (g) { 1386 KitCgTypeId ptr_ty = kit_cg_type_ptr(p->c, g->type, 0); 1387 kit_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0); 1388 p->last_type = toy_type_register_ptr(p, ptr_ty, g->toy_type, 0); 1389 return ptr_ty; 1390 } else { 1391 ToyFn* fn = toy_find_fn(p, name); 1392 if (fn) { 1393 KitCgTypeId ptr_ty = kit_cg_type_ptr(p->c, fn->type, 0); 1394 kit_cg_push_symbol_addr(p->cg, toy_fn_cur_sym(p, fn), 0); 1395 p->last_type = toy_type_register_ptr(p, ptr_ty, fn->toy_type, 0); 1396 return ptr_ty; 1397 } 1398 } 1399 toy_error(p, p->cur.loc, "undefined variable"); 1400 return KIT_CG_TYPE_NONE; 1401 } 1402 } 1403 } 1404 1405 return toy_parse_expr_postfix(p); 1406 } 1407 1408 static KitCgTypeId toy_parse_expr_cast(ToyParser* p) { 1409 KitCgTypeId ty = toy_parse_expr_unary(p); 1410 while (ty != KIT_CG_TYPE_NONE && !p->tail_call_expr && 1411 toy_parser_match(p, TOK_AS)) { 1412 KitCgTypeId dst = toy_parse_type(p); 1413 if (dst == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1414 if (!toy_emit_cast(p, ty, dst)) return KIT_CG_TYPE_NONE; 1415 ty = dst; 1416 } 1417 return ty; 1418 } 1419 1420 static KitCgTypeId toy_parse_expr_mul(ToyParser* p) { 1421 KitCgTypeId ty = toy_parse_expr_cast(p); 1422 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1423 while (p->cur.kind == TOK_STAR || p->cur.kind == TOK_SLASH || 1424 p->cur.kind == TOK_PERCENT) { 1425 if (p->tail_call_expr) break; 1426 ToyTokenKind op = p->cur.kind; 1427 KitCgIntBinOp binop; 1428 if (!toy_note_expr_island(p, TOY_EXPR_ISLAND_ARITH)) 1429 return KIT_CG_TYPE_NONE; 1430 toy_parser_advance(p); 1431 KitCgTypeId ty2 = toy_parse_expr_cast(p); 1432 if (ty2 == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1433 if (toy_reject_tail_call_operand(p)) return KIT_CG_TYPE_NONE; 1434 if (toy_type_is_intlike(p, ty) && toy_type_is_intlike(p, ty2)) { 1435 if (!toy_promote_binary_int_operands(p, &ty, &ty2)) { 1436 toy_error(p, p->cur.loc, 1437 "arithmetic operands must have same numeric type"); 1438 return KIT_CG_TYPE_NONE; 1439 } 1440 } else if (ty != ty2 || !toy_type_is_float(p, ty)) { 1441 toy_error(p, p->cur.loc, 1442 "arithmetic operands must have same numeric type"); 1443 return KIT_CG_TYPE_NONE; 1444 } 1445 if (toy_type_is_float(p, ty)) { 1446 KitCgFpBinOp fp_op; 1447 if (op == TOK_PERCENT) { 1448 toy_error(p, p->cur.loc, "floating-point remainder is unsupported"); 1449 return KIT_CG_TYPE_NONE; 1450 } 1451 switch (op) { 1452 case TOK_STAR: 1453 fp_op = KIT_CG_FP_MUL; 1454 break; 1455 case TOK_SLASH: 1456 fp_op = KIT_CG_FP_DIV; 1457 break; 1458 default: 1459 return KIT_CG_TYPE_NONE; 1460 } 1461 kit_cg_fp_binop(p->cg, fp_op, 0); 1462 } else { 1463 switch (op) { 1464 case TOK_STAR: 1465 binop = KIT_CG_INT_MUL; 1466 break; 1467 case TOK_SLASH: 1468 binop = KIT_CG_INT_SDIV; 1469 break; 1470 case TOK_PERCENT: 1471 binop = KIT_CG_INT_SREM; 1472 break; 1473 default: 1474 return KIT_CG_TYPE_NONE; 1475 } 1476 kit_cg_int_binop(p->cg, binop, 0); 1477 } 1478 toy_note_cg_result_type(p, ty); 1479 } 1480 return ty; 1481 } 1482 1483 static KitCgTypeId toy_parse_expr_add(ToyParser* p) { 1484 KitCgTypeId ty = toy_parse_expr_mul(p); 1485 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1486 while (p->cur.kind == TOK_PLUS || p->cur.kind == TOK_MINUS) { 1487 if (p->tail_call_expr) break; 1488 ToyTokenKind op = p->cur.kind; 1489 KitCgIntBinOp binop = (op == TOK_PLUS) ? KIT_CG_INT_ADD : KIT_CG_INT_SUB; 1490 if (!toy_note_expr_island(p, TOY_EXPR_ISLAND_ARITH)) 1491 return KIT_CG_TYPE_NONE; 1492 toy_parser_advance(p); 1493 KitCgTypeId ty2 = toy_parse_expr_mul(p); 1494 if (ty2 == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1495 if (toy_reject_tail_call_operand(p)) return KIT_CG_TYPE_NONE; 1496 if (toy_type_is_intlike(p, ty) && toy_type_is_intlike(p, ty2)) { 1497 if (!toy_promote_binary_int_operands(p, &ty, &ty2)) { 1498 toy_error(p, p->cur.loc, 1499 "arithmetic operands must have same numeric type"); 1500 return KIT_CG_TYPE_NONE; 1501 } 1502 } else if (ty != ty2 || !toy_type_is_float(p, ty)) { 1503 toy_error(p, p->cur.loc, 1504 "arithmetic operands must have same numeric type"); 1505 return KIT_CG_TYPE_NONE; 1506 } 1507 if (toy_type_is_float(p, ty)) { 1508 kit_cg_fp_binop(p->cg, op == TOK_PLUS ? KIT_CG_FP_ADD : KIT_CG_FP_SUB, 0); 1509 } else { 1510 kit_cg_int_binop(p->cg, binop, 0); 1511 } 1512 toy_note_cg_result_type(p, ty); 1513 } 1514 return ty; 1515 } 1516 1517 static KitCgTypeId toy_parse_expr_cmp(ToyParser* p) { 1518 KitCgTypeId ty = toy_parse_expr_add(p); 1519 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1520 if (!p->tail_call_expr && (p->cur.kind == TOK_EQEQ || p->cur.kind == TOK_NE || 1521 p->cur.kind == TOK_LT || p->cur.kind == TOK_GT || 1522 p->cur.kind == TOK_LE || p->cur.kind == TOK_GE)) { 1523 ToyTokenKind op = p->cur.kind; 1524 KitCgIntCmpOp cmp; 1525 if (!toy_note_expr_island(p, TOY_EXPR_ISLAND_CMP)) return KIT_CG_TYPE_NONE; 1526 toy_parser_advance(p); 1527 KitCgTypeId ty2 = toy_parse_expr_add(p); 1528 if (ty2 == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1529 if (toy_reject_tail_call_operand(p)) return KIT_CG_TYPE_NONE; 1530 if (toy_type_is_intlike(p, ty) && toy_type_is_intlike(p, ty2)) { 1531 if (!toy_promote_binary_int_operands(p, &ty, &ty2)) { 1532 toy_error(p, p->cur.loc, "comparison operands must have same type"); 1533 return KIT_CG_TYPE_NONE; 1534 } 1535 } else if (ty != ty2) { 1536 toy_error(p, p->cur.loc, "comparison operands must have same type"); 1537 return KIT_CG_TYPE_NONE; 1538 } 1539 if (toy_type_is_float(p, ty)) { 1540 KitCgFpCmpOp fp_cmp; 1541 switch (op) { 1542 case TOK_EQEQ: 1543 fp_cmp = KIT_CG_FP_OEQ; 1544 break; 1545 case TOK_NE: 1546 /* `!=` on floats is unordered not-equal (true on NaN), not ONE. */ 1547 fp_cmp = KIT_CG_FP_UNE; 1548 break; 1549 case TOK_LT: 1550 fp_cmp = KIT_CG_FP_OLT; 1551 break; 1552 case TOK_GT: 1553 fp_cmp = KIT_CG_FP_OGT; 1554 break; 1555 case TOK_LE: 1556 fp_cmp = KIT_CG_FP_OLE; 1557 break; 1558 case TOK_GE: 1559 fp_cmp = KIT_CG_FP_OGE; 1560 break; 1561 default: 1562 return KIT_CG_TYPE_NONE; 1563 } 1564 kit_cg_fp_cmp(p->cg, fp_cmp); 1565 } else if (toy_type_is_intlike(p, ty) || toy_type_is_ptr(p, ty)) { 1566 switch (op) { 1567 case TOK_EQEQ: 1568 cmp = KIT_CG_INT_EQ; 1569 break; 1570 case TOK_NE: 1571 cmp = KIT_CG_INT_NE; 1572 break; 1573 case TOK_LT: 1574 cmp = KIT_CG_INT_LT_S; 1575 break; 1576 case TOK_GT: 1577 cmp = KIT_CG_INT_GT_S; 1578 break; 1579 case TOK_LE: 1580 cmp = KIT_CG_INT_LE_S; 1581 break; 1582 case TOK_GE: 1583 cmp = KIT_CG_INT_GE_S; 1584 break; 1585 default: 1586 return KIT_CG_TYPE_NONE; 1587 } 1588 kit_cg_int_cmp(p->cg, cmp); 1589 } else { 1590 toy_error(p, p->cur.loc, "comparison operands must be scalar"); 1591 return KIT_CG_TYPE_NONE; 1592 } 1593 kit_cg_zext(p->cg, p->int_type); 1594 ty = p->int_type; 1595 toy_note_cg_result_type(p, ty); 1596 } 1597 return ty; 1598 } 1599 1600 static KitCgTypeId toy_parse_expr_shift(ToyParser* p) { 1601 KitCgTypeId ty = toy_parse_expr_cmp(p); 1602 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1603 while (p->cur.kind == TOK_SHL || p->cur.kind == TOK_SHR) { 1604 if (p->tail_call_expr) break; 1605 ToyTokenKind op = p->cur.kind; 1606 KitCgIntBinOp binop = (op == TOK_SHL) ? KIT_CG_INT_SHL : KIT_CG_INT_ASHR; 1607 if (!toy_note_expr_island(p, TOY_EXPR_ISLAND_SHIFT)) 1608 return KIT_CG_TYPE_NONE; 1609 toy_parser_advance(p); 1610 KitCgTypeId ty2 = toy_parse_expr_cmp(p); 1611 if (ty2 == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1612 if (toy_reject_tail_call_operand(p)) return KIT_CG_TYPE_NONE; 1613 if (!toy_type_is_promotable_int(p, ty) || 1614 !toy_type_is_promotable_int(p, ty2) || 1615 !toy_promote_binary_int_operands(p, &ty, &ty2)) { 1616 toy_error(p, p->cur.loc, "shift operands must be int"); 1617 return KIT_CG_TYPE_NONE; 1618 } 1619 kit_cg_int_binop(p->cg, binop, 0); 1620 toy_note_cg_result_type(p, ty); 1621 } 1622 return ty; 1623 } 1624 1625 static KitCgTypeId toy_parse_expr_band(ToyParser* p) { 1626 KitCgTypeId ty = toy_parse_expr_shift(p); 1627 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1628 while (p->cur.kind == TOK_AMPERSAND) { 1629 if (p->tail_call_expr) break; 1630 if (!toy_note_expr_island(p, TOY_EXPR_ISLAND_BIT_AND)) 1631 return KIT_CG_TYPE_NONE; 1632 toy_parser_advance(p); 1633 KitCgTypeId ty2 = toy_parse_expr_shift(p); 1634 if (ty2 == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1635 if (toy_reject_tail_call_operand(p)) return KIT_CG_TYPE_NONE; 1636 if (!toy_type_is_promotable_int(p, ty) || 1637 !toy_type_is_promotable_int(p, ty2) || 1638 !toy_promote_binary_int_operands(p, &ty, &ty2)) { 1639 toy_error(p, p->cur.loc, "bitwise operands must be int"); 1640 return KIT_CG_TYPE_NONE; 1641 } 1642 kit_cg_int_binop(p->cg, KIT_CG_INT_AND, 0); 1643 toy_note_cg_result_type(p, ty); 1644 } 1645 return ty; 1646 } 1647 1648 static KitCgTypeId toy_parse_expr_bxor(ToyParser* p) { 1649 KitCgTypeId ty = toy_parse_expr_band(p); 1650 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1651 while (p->cur.kind == TOK_CARET) { 1652 if (p->tail_call_expr) break; 1653 if (!toy_note_expr_island(p, TOY_EXPR_ISLAND_BIT_XOR)) 1654 return KIT_CG_TYPE_NONE; 1655 toy_parser_advance(p); 1656 KitCgTypeId ty2 = toy_parse_expr_band(p); 1657 if (ty2 == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1658 if (toy_reject_tail_call_operand(p)) return KIT_CG_TYPE_NONE; 1659 if (!toy_type_is_promotable_int(p, ty) || 1660 !toy_type_is_promotable_int(p, ty2) || 1661 !toy_promote_binary_int_operands(p, &ty, &ty2)) { 1662 toy_error(p, p->cur.loc, "bitwise operands must be int"); 1663 return KIT_CG_TYPE_NONE; 1664 } 1665 kit_cg_int_binop(p->cg, KIT_CG_INT_XOR, 0); 1666 toy_note_cg_result_type(p, ty); 1667 } 1668 return ty; 1669 } 1670 1671 static KitCgTypeId toy_parse_expr_bor(ToyParser* p) { 1672 KitCgTypeId ty = toy_parse_expr_bxor(p); 1673 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1674 while (p->cur.kind == TOK_PIPE) { 1675 if (p->tail_call_expr) break; 1676 if (!toy_note_expr_island(p, TOY_EXPR_ISLAND_BIT_OR)) 1677 return KIT_CG_TYPE_NONE; 1678 toy_parser_advance(p); 1679 KitCgTypeId ty2 = toy_parse_expr_bxor(p); 1680 if (ty2 == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1681 if (toy_reject_tail_call_operand(p)) return KIT_CG_TYPE_NONE; 1682 if (!toy_type_is_promotable_int(p, ty) || 1683 !toy_type_is_promotable_int(p, ty2) || 1684 !toy_promote_binary_int_operands(p, &ty, &ty2)) { 1685 toy_error(p, p->cur.loc, "bitwise operands must be int"); 1686 return KIT_CG_TYPE_NONE; 1687 } 1688 kit_cg_int_binop(p->cg, KIT_CG_INT_OR, 0); 1689 toy_note_cg_result_type(p, ty); 1690 } 1691 return ty; 1692 } 1693 1694 static KitCgTypeId toy_parse_expr_and(ToyParser* p) { 1695 KitCgTypeId ty = toy_parse_expr_bor(p); 1696 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1697 while (p->cur.kind == TOK_AND) { 1698 if (p->tail_call_expr) break; 1699 KitCgTypeId bool_ty = toy_builtin_type(p, KIT_CG_BUILTIN_BOOL); 1700 KitCgLabel false_label; 1701 KitCgLabel end_label; 1702 KitCgLocal result_slot; 1703 if (!toy_note_expr_island(p, TOY_EXPR_ISLAND_LOGIC_AND)) 1704 return KIT_CG_TYPE_NONE; 1705 toy_parser_advance(p); 1706 false_label = kit_cg_label_new(p->cg); 1707 end_label = kit_cg_label_new(p->cg); 1708 result_slot = kit_cg_local(p->cg, bool_ty, toy_slot_attrs(0)); 1709 if (!toy_emit_truthy(p, ty)) return KIT_CG_TYPE_NONE; 1710 kit_cg_branch_false(p->cg, false_label); 1711 ty = toy_parse_expr_bor(p); 1712 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1713 if (toy_reject_tail_call_operand(p)) return KIT_CG_TYPE_NONE; 1714 if (!toy_emit_truthy(p, ty)) return KIT_CG_TYPE_NONE; 1715 kit_cg_branch_false(p->cg, false_label); 1716 kit_cg_push_local(p->cg, result_slot); 1717 kit_cg_push_int(p->cg, 1, bool_ty); 1718 kit_cg_store(p->cg, toy_mem_access(p, bool_ty)); 1719 kit_cg_jump(p->cg, end_label); 1720 kit_cg_label_place(p->cg, false_label); 1721 kit_cg_push_local(p->cg, result_slot); 1722 kit_cg_push_int(p->cg, 0, bool_ty); 1723 kit_cg_store(p->cg, toy_mem_access(p, bool_ty)); 1724 kit_cg_label_place(p->cg, end_label); 1725 kit_cg_push_local(p->cg, result_slot); 1726 kit_cg_load(p->cg, toy_mem_access(p, bool_ty)); 1727 ty = bool_ty; 1728 toy_note_cg_result_type(p, ty); 1729 } 1730 return ty; 1731 } 1732 1733 static KitCgTypeId toy_parse_expr_or(ToyParser* p) { 1734 KitCgTypeId ty = toy_parse_expr_and(p); 1735 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1736 while (p->cur.kind == TOK_OR) { 1737 if (p->tail_call_expr) break; 1738 KitCgTypeId bool_ty = toy_builtin_type(p, KIT_CG_BUILTIN_BOOL); 1739 KitCgLabel true_label; 1740 KitCgLabel end_label; 1741 KitCgLocal result_slot; 1742 if (!toy_note_expr_island(p, TOY_EXPR_ISLAND_LOGIC_OR)) 1743 return KIT_CG_TYPE_NONE; 1744 toy_parser_advance(p); 1745 true_label = kit_cg_label_new(p->cg); 1746 end_label = kit_cg_label_new(p->cg); 1747 result_slot = kit_cg_local(p->cg, bool_ty, toy_slot_attrs(0)); 1748 if (!toy_emit_truthy(p, ty)) return KIT_CG_TYPE_NONE; 1749 kit_cg_branch_true(p->cg, true_label); 1750 ty = toy_parse_expr_and(p); 1751 if (ty == KIT_CG_TYPE_NONE) return KIT_CG_TYPE_NONE; 1752 if (toy_reject_tail_call_operand(p)) return KIT_CG_TYPE_NONE; 1753 if (!toy_emit_truthy(p, ty)) return KIT_CG_TYPE_NONE; 1754 kit_cg_branch_true(p->cg, true_label); 1755 kit_cg_push_local(p->cg, result_slot); 1756 kit_cg_push_int(p->cg, 0, bool_ty); 1757 kit_cg_store(p->cg, toy_mem_access(p, bool_ty)); 1758 kit_cg_jump(p->cg, end_label); 1759 kit_cg_label_place(p->cg, true_label); 1760 kit_cg_push_local(p->cg, result_slot); 1761 kit_cg_push_int(p->cg, 1, bool_ty); 1762 kit_cg_store(p->cg, toy_mem_access(p, bool_ty)); 1763 kit_cg_label_place(p->cg, end_label); 1764 kit_cg_push_local(p->cg, result_slot); 1765 kit_cg_load(p->cg, toy_mem_access(p, bool_ty)); 1766 ty = bool_ty; 1767 toy_note_cg_result_type(p, ty); 1768 } 1769 return ty; 1770 } 1771 1772 KitCgTypeId toy_parse_expr(ToyParser* p) { 1773 uint32_t saved_island_mask = p->expr_island_mask; 1774 KitCgTypeId ty; 1775 p->expr_island_mask = 0; 1776 ty = toy_parse_expr_or(p); 1777 if (ty != KIT_CG_TYPE_NONE && 1778 (p->cur.kind == TOK_ANDAND || p->cur.kind == TOK_PIPEPIPE)) { 1779 toy_error(p, p->cur.loc, 1780 "legacy logical operator is unsupported; use 'and' or 'or'"); 1781 ty = KIT_CG_TYPE_NONE; 1782 } 1783 p->expr_island_mask = saved_island_mask; 1784 return ty; 1785 }