cg_adapter.c (42618B)
1 #include <string.h> 2 3 #include "parse/parse_priv.h" 4 5 KitCgTypeId pcg_tid(Parser* p, const Type* ty) { 6 return type_cg_id_in_pool(p->c, p->pool, ty); 7 } 8 9 static u32 pcg_sizeof(Parser* p, const Type* ty) { 10 return (u32)kit_cg_type_size(p->c, pcg_tid(p, ty)); 11 } 12 13 static u32 pcg_alignof(Parser* p, const Type* ty) { 14 return (u32)kit_cg_type_align(p->c, pcg_tid(p, ty)); 15 } 16 17 #define PCG_VALUE_LVALUE 1u 18 #define PCG_VALUE_MODIFIABLE 2u 19 #define PCG_VALUE_BITFIELD 4u 20 #define PCG_VALUE_NULL_PTR_CONST 8u 21 #define PCG_VALUE_REGISTER 16u 22 23 static u8 pcg_lvalue_flags_for_type(const Type* ty) { 24 u8 flags = PCG_VALUE_LVALUE; 25 if (ty && !(ty->qual & Q_CONST) && ty->kind != TY_ARRAY && 26 ty->kind != TY_FUNC && ty->kind != TY_VOID) { 27 flags |= PCG_VALUE_MODIFIABLE; 28 } 29 return flags; 30 } 31 32 KitCgMemAccess pcg_mem(Parser* p, const Type* ty) { 33 KitCgMemAccess m; 34 memset(&m, 0, sizeof m); 35 m.type = pcg_tid(p, ty); 36 m.align = pcg_alignof(p, ty); 37 if (ty && (ty->qual & Q_VOLATILE)) m.flags |= KIT_CG_MEM_VOLATILE; 38 return m; 39 } 40 41 static void pcg_aux_clear(PcgLvAux* a) { 42 a->offset = 0; 43 a->scale = 0; 44 a->bit_offset = 0; 45 a->bit_width = 0; 46 a->storage_size = 0; 47 a->bit_signed = 0; 48 a->base_kind = PCG_LV_BASE_LOCAL; 49 a->is_subobject = 0; 50 a->pad[0] = a->pad[1] = a->pad[2] = a->pad[3] = a->pad[4] = 0; 51 } 52 53 static void pcg_stack_grow(Parser* p, u32 want) { 54 const Type** ns; 55 u8* nf; 56 PcgLvAux* na; 57 u32 nc; 58 if (p->cg_type_cap >= want) return; 59 nc = p->cg_type_cap ? p->cg_type_cap * 2u : 64u; 60 while (nc < want) nc *= 2u; 61 ns = arena_array(p->pool->arena, const Type*, nc); 62 if (!ns) perr(p, "out of memory in CG type stack"); 63 nf = arena_zarray(p->pool->arena, u8, nc); 64 if (!nf) perr(p, "out of memory in CG value stack"); 65 na = arena_zarray(p->pool->arena, PcgLvAux, nc); 66 if (!na) perr(p, "out of memory in CG lvalue aux stack"); 67 if (p->cg_type_stack && p->cg_type_sp) { 68 memcpy(ns, p->cg_type_stack, sizeof(*ns) * p->cg_type_sp); 69 } 70 if (p->cg_value_flags && p->cg_type_sp) { 71 memcpy(nf, p->cg_value_flags, sizeof(*nf) * p->cg_type_sp); 72 } 73 if (p->cg_lv_aux && p->cg_type_sp) { 74 memcpy(na, p->cg_lv_aux, sizeof(*na) * p->cg_type_sp); 75 } 76 p->cg_type_stack = ns; 77 p->cg_value_flags = nf; 78 p->cg_lv_aux = na; 79 p->cg_type_cap = nc; 80 } 81 82 void pcg_push_type(Parser* p, const Type* ty) { 83 pcg_stack_grow(p, p->cg_type_sp + 1u); 84 p->cg_type_stack[p->cg_type_sp] = ty; 85 p->cg_value_flags[p->cg_type_sp] = 0; 86 pcg_aux_clear(&p->cg_lv_aux[p->cg_type_sp]); 87 ++p->cg_type_sp; 88 } 89 90 void pcg_drop_type(Parser* p) { 91 if (p->cg_type_sp) --p->cg_type_sp; 92 } 93 94 void pcg_dup_type(Parser* p) { 95 const Type* ty = pcg_top_type(p); 96 u8 flags = p->cg_type_sp ? p->cg_value_flags[p->cg_type_sp - 1u] : 0; 97 PcgLvAux aux; 98 if (p->cg_type_sp) 99 aux = p->cg_lv_aux[p->cg_type_sp - 1u]; 100 else 101 pcg_aux_clear(&aux); 102 pcg_push_type(p, ty); 103 if (p->cg_type_sp) { 104 p->cg_value_flags[p->cg_type_sp - 1u] = flags; 105 p->cg_lv_aux[p->cg_type_sp - 1u] = aux; 106 } 107 } 108 109 void pcg_swap_type(Parser* p) { 110 if (p->cg_type_sp >= 2) { 111 const Type* a = p->cg_type_stack[p->cg_type_sp - 1u]; 112 u8 af = p->cg_value_flags[p->cg_type_sp - 1u]; 113 PcgLvAux ax = p->cg_lv_aux[p->cg_type_sp - 1u]; 114 p->cg_type_stack[p->cg_type_sp - 1u] = p->cg_type_stack[p->cg_type_sp - 2u]; 115 p->cg_value_flags[p->cg_type_sp - 1u] = 116 p->cg_value_flags[p->cg_type_sp - 2u]; 117 p->cg_lv_aux[p->cg_type_sp - 1u] = p->cg_lv_aux[p->cg_type_sp - 2u]; 118 p->cg_type_stack[p->cg_type_sp - 2u] = a; 119 p->cg_value_flags[p->cg_type_sp - 2u] = af; 120 p->cg_lv_aux[p->cg_type_sp - 2u] = ax; 121 } 122 } 123 124 void pcg_rot3_type(Parser* p) { 125 if (p->cg_type_sp >= 3) { 126 const Type* a = p->cg_type_stack[p->cg_type_sp - 3u]; 127 u8 af = p->cg_value_flags[p->cg_type_sp - 3u]; 128 PcgLvAux ax = p->cg_lv_aux[p->cg_type_sp - 3u]; 129 p->cg_type_stack[p->cg_type_sp - 3u] = p->cg_type_stack[p->cg_type_sp - 2u]; 130 p->cg_value_flags[p->cg_type_sp - 3u] = 131 p->cg_value_flags[p->cg_type_sp - 2u]; 132 p->cg_lv_aux[p->cg_type_sp - 3u] = p->cg_lv_aux[p->cg_type_sp - 2u]; 133 p->cg_type_stack[p->cg_type_sp - 2u] = p->cg_type_stack[p->cg_type_sp - 1u]; 134 p->cg_value_flags[p->cg_type_sp - 2u] = 135 p->cg_value_flags[p->cg_type_sp - 1u]; 136 p->cg_lv_aux[p->cg_type_sp - 2u] = p->cg_lv_aux[p->cg_type_sp - 1u]; 137 p->cg_type_stack[p->cg_type_sp - 1u] = a; 138 p->cg_value_flags[p->cg_type_sp - 1u] = af; 139 p->cg_lv_aux[p->cg_type_sp - 1u] = ax; 140 } 141 } 142 143 /* Structural CG ops that must keep the parser's typed shadow stack in lockstep 144 * with the CG stack: each emits the CG op (when codegen is enabled) and mirrors 145 * the same structural effect onto the type stack. */ 146 void pcg_dup(Parser* p) { 147 if (pcg_emit_enabled(p)) kit_cg_dup(p->cg); 148 pcg_dup_type(p); 149 } 150 151 void pcg_swap(Parser* p) { 152 if (pcg_emit_enabled(p)) kit_cg_swap(p->cg); 153 pcg_swap_type(p); 154 } 155 156 void pcg_drop(Parser* p) { 157 if (pcg_emit_enabled(p)) kit_cg_drop(p->cg); 158 pcg_drop_type(p); 159 } 160 161 PcgLvAux* pcg_top_lv_aux(Parser* p) { 162 return p->cg_type_sp ? &p->cg_lv_aux[p->cg_type_sp - 1u] : NULL; 163 } 164 165 PcgLvAux* pcg_lv_aux_at(Parser* p, u32 depth) { 166 return (p->cg_type_sp > depth) ? &p->cg_lv_aux[p->cg_type_sp - 1u - depth] 167 : NULL; 168 } 169 170 const Type* pcg_top_type(Parser* p) { 171 return p->cg_type_sp ? p->cg_type_stack[p->cg_type_sp - 1u] : NULL; 172 } 173 174 const Type* pcg_top2_type(Parser* p) { 175 return p->cg_type_sp >= 2 ? p->cg_type_stack[p->cg_type_sp - 2u] : NULL; 176 } 177 178 void pcg_retag_top(Parser* p, const Type* ty) { 179 if (p->cg_type_sp) { 180 p->cg_type_stack[p->cg_type_sp - 1u] = ty; 181 p->cg_value_flags[p->cg_type_sp - 1u] = 0; 182 pcg_aux_clear(&p->cg_lv_aux[p->cg_type_sp - 1u]); 183 } 184 } 185 186 int pcg_top_is_bitfield(Parser* p) { 187 return p->cg_type_sp && 188 (p->cg_value_flags[p->cg_type_sp - 1u] & PCG_VALUE_BITFIELD) != 0; 189 } 190 191 void pcg_set_top_bitfield(Parser* p) { 192 if (p->cg_type_sp) 193 p->cg_value_flags[p->cg_type_sp - 1u] |= PCG_VALUE_BITFIELD; 194 } 195 196 int pcg_top_is_register(Parser* p) { 197 return p->cg_type_sp && 198 (p->cg_value_flags[p->cg_type_sp - 1u] & PCG_VALUE_REGISTER) != 0; 199 } 200 201 void pcg_set_top_register(Parser* p) { 202 if (p->cg_type_sp) 203 p->cg_value_flags[p->cg_type_sp - 1u] |= PCG_VALUE_REGISTER; 204 } 205 206 int pcg_top_is_lvalue(Parser* p) { 207 return p->cg_type_sp && 208 (p->cg_value_flags[p->cg_type_sp - 1u] & PCG_VALUE_LVALUE) != 0; 209 } 210 211 int pcg_top_is_modifiable_lvalue(Parser* p) { 212 return p->cg_type_sp && (p->cg_value_flags[p->cg_type_sp - 1u] & 213 (PCG_VALUE_LVALUE | PCG_VALUE_MODIFIABLE)) == 214 (PCG_VALUE_LVALUE | PCG_VALUE_MODIFIABLE); 215 } 216 217 int pcg_top_is_null_ptr_const(Parser* p) { 218 return p->cg_type_sp && (p->cg_value_flags[p->cg_type_sp - 1u] & 219 PCG_VALUE_NULL_PTR_CONST) != 0; 220 } 221 222 void pcg_set_top_lvalue(Parser* p) { 223 const Type* ty = pcg_top_type(p); 224 if (p->cg_type_sp) 225 p->cg_value_flags[p->cg_type_sp - 1u] = pcg_lvalue_flags_for_type(ty); 226 } 227 228 int pcg_emit_enabled(Parser* p) { return p && p->suppress_codegen == 0; } 229 230 void pcg_codegen_suppress_push(Parser* p) { 231 if (p) ++p->suppress_codegen; 232 } 233 234 void pcg_codegen_suppress_pop(Parser* p) { 235 if (!p) return; 236 if (!p->suppress_codegen) 237 perr(p, "internal parser codegen suppression underflow"); 238 --p->suppress_codegen; 239 } 240 241 int pcg_type_is_fp(const Type* ty) { 242 return ty && type_kind_is_fp((TypeKind)ty->kind); 243 } 244 245 int pcg_type_is_signed(const Type* ty) { return type_is_signed_integer(ty); } 246 247 KitCgIntBinOp pcg_int_binop(BinOp op) { 248 switch (op) { 249 case BO_IADD: 250 return KIT_CG_INT_ADD; 251 case BO_ISUB: 252 return KIT_CG_INT_SUB; 253 case BO_IMUL: 254 return KIT_CG_INT_MUL; 255 case BO_SDIV: 256 return KIT_CG_INT_SDIV; 257 case BO_UDIV: 258 return KIT_CG_INT_UDIV; 259 case BO_SREM: 260 return KIT_CG_INT_SREM; 261 case BO_UREM: 262 return KIT_CG_INT_UREM; 263 case BO_AND: 264 return KIT_CG_INT_AND; 265 case BO_OR: 266 return KIT_CG_INT_OR; 267 case BO_XOR: 268 return KIT_CG_INT_XOR; 269 case BO_SHL: 270 return KIT_CG_INT_SHL; 271 case BO_SHR_S: 272 return KIT_CG_INT_ASHR; 273 case BO_SHR_U: 274 return KIT_CG_INT_LSHR; 275 default: 276 return KIT_CG_INT_ADD; 277 } 278 } 279 280 KitCgFpBinOp pcg_fp_binop(BinOp op) { 281 switch (op) { 282 case BO_FADD: 283 return KIT_CG_FP_ADD; 284 case BO_FSUB: 285 return KIT_CG_FP_SUB; 286 case BO_FMUL: 287 return KIT_CG_FP_MUL; 288 case BO_FDIV: 289 return KIT_CG_FP_DIV; 290 default: 291 return KIT_CG_FP_ADD; 292 } 293 } 294 295 KitCgIntCmpOp pcg_int_cmp(CmpOp op) { 296 switch (op) { 297 case CMP_EQ: 298 return KIT_CG_INT_EQ; 299 case CMP_NE: 300 return KIT_CG_INT_NE; 301 case CMP_LT_S: 302 return KIT_CG_INT_LT_S; 303 case CMP_LE_S: 304 return KIT_CG_INT_LE_S; 305 case CMP_GT_S: 306 return KIT_CG_INT_GT_S; 307 case CMP_GE_S: 308 return KIT_CG_INT_GE_S; 309 case CMP_LT_U: 310 return KIT_CG_INT_LT_U; 311 case CMP_LE_U: 312 return KIT_CG_INT_LE_U; 313 case CMP_GT_U: 314 return KIT_CG_INT_GT_U; 315 case CMP_GE_U: 316 return KIT_CG_INT_GE_U; 317 default: 318 return KIT_CG_INT_EQ; 319 } 320 } 321 322 KitCgFpCmpOp pcg_fp_cmp(CmpOp op) { 323 switch (op) { 324 case CMP_EQ: 325 return KIT_CG_FP_OEQ; 326 case CMP_NE: 327 /* C `!=` on floats is *unordered* not-equal: `NaN != x` is true (and 328 * `__builtin_isnan(x)` lowers to `x != x`). Map to UNE, not ONE. */ 329 return KIT_CG_FP_UNE; 330 case CMP_LT_F: 331 case CMP_OLT_F: 332 return KIT_CG_FP_OLT; 333 case CMP_LE_F: 334 case CMP_OLE_F: 335 return KIT_CG_FP_OLE; 336 case CMP_GT_F: 337 case CMP_OGT_F: 338 return KIT_CG_FP_OGT; 339 case CMP_GE_F: 340 case CMP_OGE_F: 341 return KIT_CG_FP_OGE; 342 case CMP_OEQ_F: 343 return KIT_CG_FP_OEQ; 344 case CMP_ONE_F: 345 return KIT_CG_FP_ONE; 346 case CMP_UEQ_F: 347 return KIT_CG_FP_UEQ; 348 case CMP_UNE_F: 349 return KIT_CG_FP_UNE; 350 case CMP_ULT_F: 351 return KIT_CG_FP_ULT; 352 case CMP_ULE_F: 353 return KIT_CG_FP_ULE; 354 case CMP_UGT_F: 355 return KIT_CG_FP_UGT; 356 case CMP_UGE_F: 357 return KIT_CG_FP_UGE; 358 default: 359 return KIT_CG_FP_OEQ; 360 } 361 } 362 363 KitCgAtomicOp pcg_atomic_op(AtomicOp op) { 364 switch (op) { 365 case AO_XCHG: 366 return KIT_CG_ATOMIC_XCHG; 367 case AO_ADD: 368 return KIT_CG_ATOMIC_ADD; 369 case AO_SUB: 370 return KIT_CG_ATOMIC_SUB; 371 case AO_AND: 372 return KIT_CG_ATOMIC_AND; 373 case AO_OR: 374 return KIT_CG_ATOMIC_OR; 375 case AO_XOR: 376 return KIT_CG_ATOMIC_XOR; 377 case AO_NAND: 378 return KIT_CG_ATOMIC_NAND; 379 } 380 return KIT_CG_ATOMIC_XCHG; 381 } 382 383 KitCgMemOrder pcg_mem_order(MemOrder ord) { return (KitCgMemOrder)ord; } 384 385 static int pcg_slot_is_volatile(const FrameSlotDesc* fsd) { 386 return fsd && ((fsd->flags & FSF_VOLATILE) || 387 (fsd->type && (fsd->type->qual & Q_VOLATILE))); 388 } 389 390 FrameSlot pcg_local(Parser* p, const FrameSlotDesc* fsd) { 391 KitCgLocalAttrs attrs; 392 memset(&attrs, 0, sizeof attrs); 393 if (!pcg_emit_enabled(p)) return FRAME_SLOT_NONE; 394 attrs.name = fsd->name; 395 attrs.align = fsd->align; 396 if (pcg_slot_is_volatile(fsd)) attrs.flags |= KIT_CG_LOCAL_MEMORY_REQUIRED; 397 /* FSF_ADDR_TAKEN is no longer propagated to CG: there is no 398 * KIT_CG_LOCAL_ADDRESS_TAKEN attribute. The C-side flag stays for any 399 * parser-internal uses; opt's opt_promote_scalar_locals (Stream I) decides 400 * register-promotion from observed access patterns, not from the flag. */ 401 return kit_cg_local(p->cg, pcg_tid(p, fsd->type), attrs); 402 } 403 404 FrameSlot pcg_param_slot(Parser* p, u32 index, const FrameSlotDesc* fsd) { 405 KitCgLocalAttrs attrs; 406 if (!pcg_emit_enabled(p)) return FRAME_SLOT_NONE; 407 memset(&attrs, 0, sizeof attrs); 408 attrs.name = fsd->name; 409 attrs.align = fsd->align; 410 if (pcg_slot_is_volatile(fsd)) attrs.flags |= KIT_CG_LOCAL_MEMORY_REQUIRED; 411 return kit_cg_param(p->cg, index, pcg_tid(p, fsd->type), attrs); 412 } 413 414 void pcg_param(Parser* p, const CGParamDesc* pd) { 415 (void)p; 416 (void)pd; 417 } 418 419 void pcg_func_begin(Parser* p, const CGFuncDesc* fd) { 420 if (pcg_emit_enabled(p)) { 421 KitCgFuncAttrs attrs; 422 memset(&attrs, 0, sizeof attrs); 423 attrs.inline_policy = fd->inline_policy; 424 if (fd->flags & CGFD_NORETURN) attrs.flags |= KIT_CG_FUNC_NORETURN; 425 kit_cg_func_begin_attrs(p->cg, fd->sym, attrs); 426 } 427 } 428 429 void pcg_func_end(Parser* p) { 430 if (pcg_emit_enabled(p)) kit_cg_func_end(p->cg); 431 } 432 433 void pcg_set_loc(Parser* p, SrcLoc loc) { 434 if (pcg_emit_enabled(p)) kit_cg_set_loc(p->cg, loc); 435 } 436 437 void pcg_push_int(Parser* p, i64 v, const Type* ty) { 438 if (pcg_emit_enabled(p)) { 439 kit_cg_push_int(p->cg, (uint64_t)v, pcg_tid(p, ty)); 440 } 441 pcg_push_type(p, ty); 442 if (v == 0 && p->cg_type_sp) { 443 p->cg_value_flags[p->cg_type_sp - 1u] |= PCG_VALUE_NULL_PTR_CONST; 444 } 445 } 446 447 void pcg_push_float(Parser* p, double v, const Type* ty) { 448 if (pcg_emit_enabled(p)) kit_cg_push_float(p->cg, v, pcg_tid(p, ty)); 449 pcg_push_type(p, ty); 450 } 451 452 /* Tag the TOS place as a bit-field place when `lv` carries bit-field geometry. 453 * The frontend builds the storage-unit place itself (materialize + deref), so 454 * it attaches the descriptor here; a plain load/store then extracts/inserts the 455 * field. Must be called on the place each time a fresh one is built (each deref 456 * yields a plain place). No-op for non-bit-field lvalues. */ 457 static void pcg_apply_bitfield(Parser* p, const PcgLvAux* lv) { 458 if (lv && lv->bit_width) { 459 kit_cg_field_bits(p->cg, lv->bit_offset, lv->bit_width, lv->storage_size, 460 lv->bit_signed); 461 } 462 } 463 464 /* A trivially-addressable lvalue: a bare local slot with no pending field 465 * offset, array scale, or bit-field. Its PLACE is already on the CG stack 466 * (push_local), so a load/store can consume it directly without first 467 * materializing an address. */ 468 static int pcg_lv_is_trivial_local(const PcgLvAux* lv) { 469 return lv && lv->base_kind == PCG_LV_BASE_LOCAL && lv->offset == 0 && 470 lv->scale == 0 && lv->bit_width == 0; 471 } 472 473 /* Materialize the TOS lvalue (folding its pending field offset / array scale 474 * into the address) as a single pointer rvalue. Defined below; the memops use 475 * it to build an explicit place before load/store. */ 476 static void pcg_materialize_lv_to_ptr(Parser* p, const Type* result_ptr_ty); 477 478 void pcg_push_local_typed(Parser* p, FrameSlot s, const Type* ty) { 479 if (pcg_emit_enabled(p)) kit_cg_push_local(p->cg, s); 480 pcg_push_type(p, ty); 481 if (p->cg_type_sp) { 482 p->cg_value_flags[p->cg_type_sp - 1u] = pcg_lvalue_flags_for_type(ty); 483 p->cg_lv_aux[p->cg_type_sp - 1u].base_kind = PCG_LV_BASE_LOCAL; 484 } 485 } 486 487 void pcg_push_global(Parser* p, ObjSymId sym, const Type* ty) { 488 /* push_symbol_addr produces a pointer rvalue; the parser tags the slot as 489 * a C-language lvalue with PCG_LV_BASE_POINTER_RV so subsequent 490 * load/store/addr know the base is already a pointer. The cg layer accepts 491 * pointer-rvalue bases for memops uniformly (Stream A). */ 492 if (pcg_emit_enabled(p)) kit_cg_push_symbol_addr(p->cg, sym, 0); 493 pcg_push_type(p, ty); 494 if (p->cg_type_sp) { 495 p->cg_value_flags[p->cg_type_sp - 1u] = pcg_lvalue_flags_for_type(ty); 496 p->cg_lv_aux[p->cg_type_sp - 1u].base_kind = PCG_LV_BASE_POINTER_RV; 497 } 498 } 499 500 void pcg_load(Parser* p) { 501 const Type* ty = pcg_top_type(p); 502 int was_lvalue = pcg_top_is_lvalue(p); 503 if (pcg_emit_enabled(p)) { 504 PcgLvAux* lv = pcg_top_lv_aux(p); 505 KitCgMemAccess access = pcg_mem(p, ty); 506 /* Snapshot bit-field geometry before materialize clears the aux. */ 507 PcgLvAux bf = lv ? *lv : (PcgLvAux){0}; 508 /* Build the PLACE the strict load requires. A trivial local already has its 509 * PLACE on the CG stack (push_local) and loads directly; anything else is 510 * reduced to a single pointer (materialize, or a pointer-rvalue base) and 511 * then deref'd to a place. A bit-field place is then tagged with its bit 512 * geometry so the load extracts the field. */ 513 if (!was_lvalue || !pcg_lv_is_trivial_local(lv)) { 514 if (was_lvalue) pcg_materialize_lv_to_ptr(p, type_ptr(p->pool, ty)); 515 kit_cg_deref(p->cg, 0); 516 } 517 pcg_apply_bitfield(p, &bf); 518 kit_cg_load(p->cg, access); 519 } 520 if (was_lvalue && p->cg_type_sp) { 521 p->cg_type_stack[p->cg_type_sp - 1u] = ty; 522 p->cg_value_flags[p->cg_type_sp - 1u] = 0; 523 pcg_aux_clear(&p->cg_lv_aux[p->cg_type_sp - 1u]); 524 } 525 } 526 527 /* Materialize the pending EA on the TOS lvalue as a pointer rvalue. 528 * Postcondition: TOS is a pointer rvalue of type result_ptr_ty (which the 529 * caller has computed as type_ptr(pool, current_lv_type)) and the CG stack 530 * holds that single pointer where the lvalue's [base] or [base, index] used 531 * to be. Aux is cleared. 532 * 533 * The materialization sequence depends on the aux: 534 * base_kind == LOCAL: 535 * - scale == 0, offset == 0: addr 536 * - scale == 0, offset != 0: addr ; ptr_to_int ; +offset ; 537 * int_to_ptr 538 * - scale != 0: addr ; ptr_to_int ; idx*scale + ofs ; 539 * int_to_ptr base_kind == POINTER_RV: 540 * - scale == 0, offset == 0: no-op 541 * - scale == 0, offset != 0: ptr_to_int ; +offset ; int_to_ptr 542 * - scale != 0: ptr_to_int ; idx*scale + ofs ; 543 * int_to_ptr */ 544 static void pcg_materialize_lv_to_ptr(Parser* p, const Type* result_ptr_ty) { 545 PcgLvAux* lv = pcg_top_lv_aux(p); 546 int emit = pcg_emit_enabled(p); 547 PcgLvBaseKind base_kind = 548 lv ? (PcgLvBaseKind)lv->base_kind : PCG_LV_BASE_LOCAL; 549 i64 ofs = lv ? lv->offset : 0; 550 u32 scale = lv ? lv->scale : 0u; 551 const Type* idx_ty = c_abi_ptrdiff_type(p->abi, p->pool); 552 KitCgTypeId idx_tid = pcg_tid(p, idx_ty); 553 KitCgTypeId ptr_tid = pcg_tid(p, result_ptr_ty); 554 if (scale == 0 && ofs == 0) { 555 if (base_kind == PCG_LV_BASE_LOCAL) { 556 if (emit) kit_cg_addr(p->cg); 557 } 558 /* Already a pointer with no pending modifiers. */ 559 } else if (scale == 0) { 560 if (emit) { 561 if (base_kind == PCG_LV_BASE_LOCAL) kit_cg_addr(p->cg); 562 kit_cg_ptr_to_int(p->cg, idx_tid); 563 kit_cg_push_int(p->cg, (uint64_t)ofs, idx_tid); 564 kit_cg_int_binop(p->cg, KIT_CG_INT_ADD, KIT_CG_INTOP_NONE); 565 kit_cg_int_to_ptr(p->cg, ptr_tid); 566 } 567 } else { 568 /* CG stack on entry: [base_ptr_now, index]. Compute 569 * base_ptr_now + index*scale + ofs. */ 570 if (emit) { 571 if (base_kind == PCG_LV_BASE_LOCAL) { 572 kit_cg_swap(p->cg); /* [index, base_lv] */ 573 kit_cg_addr(p->cg); /* [index, base_ptr] */ 574 kit_cg_swap(p->cg); /* [base_ptr, index] */ 575 } 576 kit_cg_swap(p->cg); /* [index, base_ptr] */ 577 kit_cg_ptr_to_int(p->cg, idx_tid); 578 kit_cg_swap(p->cg); /* [base_int, index] */ 579 kit_cg_push_int(p->cg, (uint64_t)scale, idx_tid); 580 kit_cg_int_binop(p->cg, KIT_CG_INT_MUL, KIT_CG_INTOP_NONE); 581 kit_cg_int_binop(p->cg, KIT_CG_INT_ADD, KIT_CG_INTOP_NONE); 582 if (ofs != 0) { 583 kit_cg_push_int(p->cg, (uint64_t)ofs, idx_tid); 584 kit_cg_int_binop(p->cg, KIT_CG_INT_ADD, KIT_CG_INTOP_NONE); 585 } 586 kit_cg_int_to_ptr(p->cg, ptr_tid); 587 } 588 } 589 pcg_retag_top(p, result_ptr_ty); 590 { 591 PcgLvAux* out = pcg_top_lv_aux(p); 592 if (out) out->base_kind = PCG_LV_BASE_POINTER_RV; 593 } 594 } 595 596 void pcg_addr(Parser* p) { 597 const Type* ty = pcg_top_type(p); 598 pcg_materialize_lv_to_ptr(p, type_ptr(p->pool, ty)); 599 } 600 601 /* Pushes the address of a label as a `void*` rvalue (GNU `&&label`). */ 602 void pcg_push_label_addr(Parser* p, CGLabel label) { 603 const Type* vp = type_ptr(p->pool, type_void(p->pool)); 604 if (pcg_emit_enabled(p)) kit_cg_push_label_addr(p->cg, label, pcg_tid(p, vp)); 605 pcg_push_type(p, vp); 606 } 607 608 /* Pops the target pointer and emits a computed `goto *expr;`. */ 609 void pcg_computed_goto(Parser* p, const CGLabel* targets, u32 ntargets) { 610 if (pcg_emit_enabled(p)) kit_cg_computed_goto(p->cg, targets, ntargets); 611 pcg_drop_type(p); 612 } 613 614 /* ---- Control flow ---- 615 * 616 * Label placement / jump / branch ops gate on emit; the conditional branches 617 * also pop the tested value off the type stack to mirror the CG-side consume. 618 * Suppressed parses, such as C99 `extern inline` bodies, do not open a CG 619 * function, so they use a nonzero dummy label only for semantic bookkeeping 620 * around break/continue/case validation. */ 621 CGLabel pcg_label_new(Parser* p) { 622 if (!pcg_emit_enabled(p)) return (CGLabel)1; 623 return kit_cg_label_new(p->cg); 624 } 625 626 void pcg_label_place(Parser* p, CGLabel l) { 627 if (pcg_emit_enabled(p)) kit_cg_label_place(p->cg, l); 628 } 629 630 void pcg_jump(Parser* p, CGLabel l) { 631 if (pcg_emit_enabled(p)) kit_cg_jump(p->cg, l); 632 } 633 634 void pcg_branch_true(Parser* p, CGLabel l) { 635 if (pcg_emit_enabled(p)) kit_cg_branch_true(p->cg, l); 636 pcg_drop_type(p); 637 } 638 639 void pcg_branch_false(Parser* p, CGLabel l) { 640 if (pcg_emit_enabled(p)) kit_cg_branch_false(p->cg, l); 641 pcg_drop_type(p); 642 } 643 644 /* Store [lv, rv] -> [rv]. The expression-value of an assignment is the 645 * assigned rvalue, so the store sequence must leave a copy of rv on TOS. */ 646 void pcg_store(Parser* p) { 647 const Type* lv_ty = pcg_top2_type(p); 648 const Type* rv_ty = pcg_top_type(p); 649 const Type* mem_ty = lv_ty; 650 int emit = pcg_emit_enabled(p); 651 /* The aux to consume lives on the lvalue slot at parser depth 1. */ 652 PcgLvAux* lv = pcg_lv_aux_at(p, 1); 653 /* Snapshot bit-field geometry before materialize clears the aux. */ 654 PcgLvAux bf = lv ? *lv : (PcgLvAux){0}; 655 KitCgMemAccess access; 656 if (rv_ty && type_is_ptr(rv_ty) && (!lv_ty || !type_is_ptr(lv_ty))) { 657 mem_ty = rv_ty; 658 } 659 access = pcg_mem(p, mem_ty ? mem_ty : rv_ty); 660 if (emit) { 661 int wide = 662 rv_ty && (rv_ty->kind == TY_INT128 || rv_ty->kind == TY_UINT128 || 663 rv_ty->kind == TY_LDOUBLE); 664 if (pcg_lv_is_trivial_local(lv) && !wide) { 665 /* The destination place is already on the CG stack. Keep a copy of rv as 666 * the assignment's value. Stack: [place, value]. */ 667 kit_cg_dup(p->cg); 668 kit_cg_rot3(p->cg); 669 kit_cg_swap(p->cg); 670 kit_cg_store(p->cg, access); 671 } else { 672 /* Stash rv into a temp so the destination place can be built from the 673 * base — folding any field offset / array scale into an explicit pointer 674 * — then reload rv to store it and to leave it as the expression value. 675 */ 676 FrameSlotDesc fsd; 677 FrameSlot tmp; 678 KitCgMemAccess rv_access = pcg_mem(p, rv_ty); 679 int trivial = pcg_lv_is_trivial_local(lv); 680 memset(&fsd, 0, sizeof fsd); 681 fsd.type = rv_ty; 682 fsd.size = c_abi_sizeof(p->abi, rv_ty); 683 fsd.align = c_abi_alignof(p->abi, rv_ty); 684 fsd.kind = FS_LOCAL; 685 tmp = pcg_local(p, &fsd); 686 kit_cg_push_local(p->cg, tmp); /* [base.., value, &tmp] */ 687 kit_cg_swap(p->cg); /* [base.., &tmp, value] */ 688 kit_cg_store(p->cg, rv_access); /* [base..] (stash rv) */ 689 if (!trivial) { 690 /* Materialize operates on the parser-TOS lvalue; drop the rv type slot 691 * so the lvalue is on top and matches the CG [base..]. The pointer is 692 * deref'd to the PLACE the strict store requires, then tagged with the 693 * bit-field geometry so the store inserts the field. */ 694 pcg_drop_type(p); 695 pcg_materialize_lv_to_ptr(p, type_ptr(p->pool, lv_ty)); /* [dst_ptr] */ 696 kit_cg_deref(p->cg, 0); /* [dst_place] */ 697 pcg_apply_bitfield(p, &bf); 698 pcg_push_type(p, rv_ty); 699 } 700 kit_cg_push_local(p->cg, tmp); 701 kit_cg_load(p->cg, rv_access); /* [dst, value] */ 702 kit_cg_store(p->cg, access); /* [] */ 703 kit_cg_push_local(p->cg, tmp); 704 kit_cg_load(p->cg, rv_access); /* [value] */ 705 } 706 } 707 pcg_drop_type(p); 708 pcg_drop_type(p); 709 pcg_push_type(p, rv_ty); 710 } 711 712 void pcg_deref(Parser* p, const Type* pointee) { 713 const Type* ptr_ty = pcg_top_type(p); 714 if (pointee && pointee->kind == TY_FUNC) { 715 /* Function lvalues collapse to function pointers in C; no CG-level 716 * dereference is needed (functions aren't first-class data). */ 717 pcg_retag_top(p, pointee); 718 return; 719 } 720 if (ptr_ty && ptr_ty->kind == TY_PTR && ptr_ty->ptr.pointee != pointee) { 721 const Type* want_ptr_ty = type_ptr(p->pool, pointee); 722 if (pcg_emit_enabled(p)) kit_cg_bitcast(p->cg, pcg_tid(p, want_ptr_ty)); 723 pcg_retag_top(p, want_ptr_ty); 724 } 725 /* No kit_cg_indirect: the cg load/store accept pointer-rvalue bases 726 * directly. Mark the slot as a C-language lvalue with POINTER_RV base; the 727 * pointer stays on the CG stack untouched. */ 728 pcg_retag_top(p, pointee); 729 if (p->cg_type_sp) { 730 p->cg_value_flags[p->cg_type_sp - 1u] = pcg_lvalue_flags_for_type(pointee); 731 p->cg_lv_aux[p->cg_type_sp - 1u].base_kind = PCG_LV_BASE_POINTER_RV; 732 } 733 } 734 735 /* ---- Lvalue chain helpers ---- */ 736 737 void pcg_lv_member(Parser* p, i64 byte_offset, const Type* field_ty, 738 u16 bf_offset, u16 bf_width, u32 bf_storage_size) { 739 PcgLvAux* lv = pcg_top_lv_aux(p); 740 int was_lvalue = pcg_top_is_lvalue(p); 741 const Type* base_ty = pcg_top_type(p); 742 /* A member of an rvalue aggregate (e.g. `mk().field` for a struct-returning 743 * call) lives in a CG-side temporary that is memory-backed, so the member is 744 * readable as an lvalue — but per C it is not a *modifiable* lvalue. */ 745 int base_is_rvalue_agg = 746 !was_lvalue && base_ty && 747 (base_ty->kind == TY_STRUCT || base_ty->kind == TY_UNION); 748 i64 saved_offset = lv ? lv->offset + byte_offset : byte_offset; 749 u32 saved_scale = lv ? lv->scale : 0u; 750 u8 saved_base_kind = lv ? lv->base_kind : PCG_LV_BASE_LOCAL; 751 /* Bumping the offset preserves the base kind and any earlier offset/scale 752 * accumulated on the chain (`a[i].f.g` keeps `scale = sizeof(elem)` and 753 * adds the field offsets). */ 754 pcg_retag_top(p, field_ty); 755 if (was_lvalue) { 756 pcg_set_top_lvalue(p); 757 } else if (base_is_rvalue_agg && p->cg_type_sp) { 758 p->cg_value_flags[p->cg_type_sp - 1u] = PCG_VALUE_LVALUE; 759 } 760 /* pcg_retag_top cleared aux; re-apply the bumped offset and base kind. */ 761 { 762 PcgLvAux* lv_after = pcg_top_lv_aux(p); 763 if (lv_after) { 764 lv_after->offset = saved_offset; 765 lv_after->scale = saved_scale; 766 lv_after->base_kind = saved_base_kind; 767 lv_after->bit_offset = bf_offset; 768 lv_after->bit_width = bf_width; 769 lv_after->storage_size = bf_storage_size; 770 lv_after->bit_signed = pcg_type_is_signed(field_ty) ? 1u : 0u; 771 /* A member access narrows to a sub-object of a larger CG-tracked 772 * object; record it so aggregate reads materialize a pointer to the 773 * exact sub-object (the offset alone can be 0 for a first member). */ 774 lv_after->is_subobject = 1u; 775 } 776 if (bf_width && p->cg_type_sp) 777 p->cg_value_flags[p->cg_type_sp - 1u] |= PCG_VALUE_BITFIELD; 778 } 779 } 780 781 void pcg_lv_subscript(Parser* p, u32 elem_size, const Type* elem_ty) { 782 /* Stack on entry (parser side): [base_lv, index_rv]. 783 * Stack on entry (CG side): [base, index]. 784 * After this call (parser): [elem_lv] with aux.scale = elem_size. 785 * After this call (CG): [base, index] — unchanged; the eventual 786 * load/store consumes both via the EA. */ 787 PcgLvAux* base_lv = pcg_lv_aux_at(p, 1); 788 i64 saved_offset = base_lv ? base_lv->offset : 0; 789 u8 base_is_lvalue = 790 (p->cg_type_sp >= 2u && 791 (p->cg_value_flags[p->cg_type_sp - 2u] & PCG_VALUE_LVALUE) != 0); 792 u8 saved_base_kind = !base_is_lvalue 793 ? PCG_LV_BASE_POINTER_RV 794 : (base_lv ? base_lv->base_kind : PCG_LV_BASE_LOCAL); 795 if (base_lv && base_lv->scale != 0) { 796 perr(p, "internal: nested subscript without materialization"); 797 } 798 pcg_drop_type(p); /* drop index parser slot */ 799 pcg_retag_top(p, elem_ty); /* retag base parser slot as element */ 800 pcg_set_top_lvalue(p); 801 { 802 PcgLvAux* lv = pcg_top_lv_aux(p); 803 if (lv) { 804 lv->offset = saved_offset; 805 lv->scale = elem_size; 806 lv->base_kind = saved_base_kind; 807 } 808 } 809 } 810 811 void pcg_decay_array(Parser* p, const Type* arr_ty) { 812 const Type* ptr_ty = type_ptr(p->pool, arr_ty->arr.elem); 813 pcg_materialize_lv_to_ptr(p, ptr_ty); 814 } 815 816 void pcg_binop(Parser* p, BinOp op) { 817 const Type* result = pcg_top2_type(p); 818 if (op == BO_FADD || op == BO_FSUB || op == BO_FMUL || op == BO_FDIV) { 819 if (pcg_emit_enabled(p)) { 820 kit_cg_fp_binop(p->cg, pcg_fp_binop(op), KIT_CG_FP_NONE); 821 } 822 } else { 823 if (pcg_emit_enabled(p)) { 824 kit_cg_int_binop(p->cg, pcg_int_binop(op), KIT_CG_INTOP_NONE); 825 } 826 } 827 pcg_drop_type(p); 828 pcg_retag_top(p, result); 829 } 830 831 void pcg_unop(Parser* p, UnOp op) { 832 if (op == UO_NEG && pcg_type_is_fp(pcg_top_type(p))) { 833 if (pcg_emit_enabled(p)) 834 kit_cg_fp_unop(p->cg, KIT_CG_FP_NEG, KIT_CG_FP_NONE); 835 } else { 836 KitCgIntUnOp iop = op == UO_NOT ? KIT_CG_INT_NOT 837 : op == UO_BNOT ? KIT_CG_INT_BNOT 838 : KIT_CG_INT_NEG; 839 if (pcg_emit_enabled(p)) kit_cg_int_unop(p->cg, iop, KIT_CG_INTOP_NONE); 840 } 841 } 842 843 void pcg_cmp(Parser* p, CmpOp op) { 844 /* The FP block starts at CMP_LT_F (relational operator markers) and runs 845 * through the ordered/unordered predicate members; everything below is 846 * integer. CMP_EQ/CMP_NE additionally route to FP when the operand type is 847 * floating (C `==`/`!=` on floats is ordered-equal / unordered-not-equal). */ 848 if (op >= CMP_LT_F || 849 ((op == CMP_EQ || op == CMP_NE) && pcg_type_is_fp(pcg_top_type(p)))) { 850 if (pcg_emit_enabled(p)) kit_cg_fp_cmp(p->cg, pcg_fp_cmp(op)); 851 } else { 852 if (pcg_emit_enabled(p)) kit_cg_int_cmp(p->cg, pcg_int_cmp(op)); 853 } 854 pcg_drop_type(p); 855 pcg_retag_top(p, type_prim(p->pool, TY_INT)); 856 } 857 858 void pcg_convert(Parser* p, const Type* dst) { 859 const Type* src = pcg_top_type(p); 860 u32 ss = pcg_sizeof(p, src); 861 u32 ds = pcg_sizeof(p, dst); 862 int si = type_is_int(src) || type_is_ptr(src); 863 int di = type_is_int(dst) || type_is_ptr(dst); 864 int sf = pcg_type_is_fp(src); 865 int df = pcg_type_is_fp(dst); 866 KitCgTypeId id = pcg_tid(p, dst); 867 int emit = pcg_emit_enabled(p); 868 if (src == dst) return; 869 /* Conversion to _Bool is "value != 0", not a truncation: a value whose set 870 * bits all lie above the bool storage width (e.g. 256, or the sign bit of a 871 * 128-bit operand) must still become 1. Emit an explicit compare-against-zero 872 * for any non-bool scalar source. */ 873 if (dst->kind == TY_BOOL && src->kind != TY_BOOL) { 874 if (emit) { 875 KitCgTypeId sid = pcg_tid(p, src); 876 if (sf) { 877 kit_cg_push_float(p->cg, 0.0, sid); 878 kit_cg_fp_cmp(p->cg, KIT_CG_FP_UNE); 879 } else { 880 kit_cg_push_int(p->cg, 0, sid); 881 kit_cg_int_cmp(p->cg, KIT_CG_INT_NE); 882 } 883 /* The compare yields a 0/1 int; narrow it to the bool storage width. */ 884 kit_cg_trunc(p->cg, id); 885 } 886 pcg_retag_top(p, dst); 887 return; 888 } 889 if (type_is_ptr(src) && type_is_ptr(dst)) { 890 if (emit) kit_cg_bitcast(p->cg, id); 891 pcg_retag_top(p, dst); 892 return; 893 } 894 if (si && di) { 895 if (ds < ss) { 896 if (emit) kit_cg_trunc(p->cg, id); 897 } else if (ds > ss && type_is_int(src) && pcg_type_is_signed(src)) { 898 if (emit) kit_cg_sext(p->cg, id); 899 } else if (ds > ss) { 900 if (emit) kit_cg_zext(p->cg, id); 901 } else if (type_is_ptr(src) != type_is_ptr(dst)) { 902 if (emit) kit_cg_bitcast(p->cg, id); 903 } 904 } else if (type_is_int(src) && df) { 905 if (pcg_type_is_signed(src)) { 906 if (emit) kit_cg_sint_to_float(p->cg, id, KIT_CG_ROUND_DEFAULT); 907 } else { 908 if (emit) kit_cg_uint_to_float(p->cg, id, KIT_CG_ROUND_DEFAULT); 909 } 910 } else if (sf && type_is_int(dst)) { 911 if (pcg_type_is_signed(dst)) { 912 if (emit) kit_cg_float_to_sint(p->cg, id, KIT_CG_ROUND_DEFAULT); 913 } else { 914 if (emit) kit_cg_float_to_uint(p->cg, id, KIT_CG_ROUND_DEFAULT); 915 } 916 } else if (sf && df) { 917 if (ds > ss) { 918 if (emit) kit_cg_fpext(p->cg, id); 919 } else if (ds < ss) { 920 if (emit) kit_cg_fptrunc(p->cg, id); 921 } 922 } else { 923 if (emit) kit_cg_bitcast(p->cg, id); 924 } 925 pcg_retag_top(p, dst); 926 } 927 928 /* Emit "value <op> step" for an inc/dec, picking the float or integer binop 929 * based on the operand type. Floating operands step by 1.0 via an FP add/sub; 930 * pointers step by the pointee size and everything else by 1. */ 931 static void pcg_emit_inc_step(Parser* p, const Type* ty, BinOp op, 932 KitCgIntBinOp cg_op, const Type* step_ty, 933 u32 step) { 934 if (pcg_type_is_fp(ty)) { 935 BinOp fop = (op == BO_ISUB) ? BO_FSUB : BO_FADD; 936 kit_cg_push_float(p->cg, 1.0, pcg_tid(p, ty)); 937 kit_cg_fp_binop(p->cg, pcg_fp_binop(fop), KIT_CG_FP_NONE); 938 } else { 939 i64 amount = (ty && ty->kind == TY_PTR) ? (i64)step : 1; 940 kit_cg_push_int(p->cg, amount, pcg_tid(p, step_ty)); 941 kit_cg_int_binop(p->cg, cg_op, 0); 942 } 943 } 944 945 void pcg_inc_dec(Parser* p, BinOp op, int post) { 946 const Type* ty = pcg_top_type(p); 947 if (!pcg_emit_enabled(p)) { 948 /* Drop the lvalue parser slot and push the rvalue result type. */ 949 pcg_drop_type(p); 950 pcg_push_type(p, ty); 951 return; 952 } 953 { 954 KitCgIntBinOp cg_op = pcg_int_binop(op); 955 PcgLvAux* lv = pcg_top_lv_aux(p); 956 /* Snapshot bit-field geometry before materialize clears the aux. */ 957 PcgLvAux bf = lv ? *lv : (PcgLvAux){0}; 958 KitCgMemAccess access = pcg_mem(p, ty); 959 const Type* step_ty = ty; 960 u32 step = 1; 961 if (ty && ty->kind == TY_PTR) { 962 const Type* pointee = ty->ptr.pointee; 963 if (pointee && pointee->kind == TY_VOID) 964 perr(p, "pointer arithmetic on void pointer"); 965 step = c_abi_sizeof(p->abi, pointee); 966 step_ty = c_abi_ptrdiff_type(p->abi, p->pool); 967 } 968 /* Materialize the lvalue to a single destination pointer so its address can 969 * be duplicated for the read-modify-write. */ 970 pcg_materialize_lv_to_ptr(p, type_ptr(p->pool, ty)); 971 { 972 FrameSlotDesc fsd; 973 FrameSlot tmp; 974 const Type* result_ty = ty; 975 KitCgMemAccess r_access = pcg_mem(p, result_ty); 976 memset(&fsd, 0, sizeof fsd); 977 fsd.type = result_ty; 978 fsd.size = c_abi_sizeof(p->abi, result_ty); 979 fsd.align = c_abi_alignof(p->abi, result_ty); 980 fsd.kind = FS_LOCAL; 981 tmp = pcg_local(p, &fsd); 982 kit_cg_dup(p->cg); /* [ptr, ptr] */ 983 kit_cg_deref(p->cg, 0); /* [ptr, place] */ 984 pcg_apply_bitfield(p, &bf); 985 kit_cg_load(p->cg, access); /* [ptr, old] */ 986 if (post) { 987 /* Stash old, compute new, store, then re-load old as result. */ 988 kit_cg_dup(p->cg); /* [ptr, old, old] */ 989 kit_cg_push_local(p->cg, tmp); 990 kit_cg_swap(p->cg); 991 kit_cg_store(p->cg, r_access); /* [ptr, old] */ 992 pcg_emit_inc_step(p, ty, op, cg_op, step_ty, step); /* [ptr, new] */ 993 kit_cg_swap(p->cg); /* [new, ptr] */ 994 kit_cg_deref(p->cg, 0); /* [new, place] */ 995 pcg_apply_bitfield(p, &bf); 996 kit_cg_swap(p->cg); /* [place, new] */ 997 kit_cg_store(p->cg, access); /* [] */ 998 kit_cg_push_local(p->cg, tmp); 999 kit_cg_load(p->cg, r_access); /* [old] */ 1000 } else { 1001 /* Compute new, stash new, store, then re-load new as result. */ 1002 pcg_emit_inc_step(p, ty, op, cg_op, step_ty, step); /* [ptr, new] */ 1003 kit_cg_dup(p->cg); /* [ptr, new, new] */ 1004 kit_cg_push_local(p->cg, tmp); 1005 kit_cg_swap(p->cg); 1006 kit_cg_store(p->cg, r_access); /* [ptr, new] */ 1007 kit_cg_swap(p->cg); /* [new, ptr] */ 1008 kit_cg_deref(p->cg, 0); /* [new, place] */ 1009 pcg_apply_bitfield(p, &bf); 1010 kit_cg_swap(p->cg); /* [place, new] */ 1011 kit_cg_store(p->cg, access); /* [] */ 1012 kit_cg_push_local(p->cg, tmp); 1013 kit_cg_load(p->cg, r_access); /* [new] */ 1014 } 1015 (void)step; 1016 } 1017 } 1018 /* Parser stack: drop the lvalue slot, push the result rvalue type. */ 1019 pcg_drop_type(p); 1020 pcg_push_type(p, ty); 1021 } 1022 1023 void pcg_call(Parser* p, u32 nargs, const Type* fn_type) { 1024 if (pcg_emit_enabled(p)) { 1025 kit_cg_call_default(p->cg, nargs, pcg_tid(p, fn_type)); 1026 } 1027 for (u32 i = 0; i < nargs + 1u; ++i) pcg_drop_type(p); 1028 if (fn_type && fn_type->kind == TY_FUNC && fn_type->fn.ret->kind != TY_VOID) { 1029 pcg_push_type(p, fn_type->fn.ret); 1030 } 1031 } 1032 1033 void pcg_call_symbol(Parser* p, KitCgSym sym, u32 nargs, const Type* fn_type) { 1034 if (pcg_emit_enabled(p)) { 1035 KitCgCallAttrs attrs; 1036 memset(&attrs, 0, sizeof attrs); 1037 kit_cg_call_symbol(p->cg, sym, nargs, attrs); 1038 } 1039 for (u32 i = 0; i < nargs; ++i) pcg_drop_type(p); 1040 if (fn_type && fn_type->kind == TY_FUNC && fn_type->fn.ret->kind != TY_VOID) { 1041 pcg_push_type(p, fn_type->fn.ret); 1042 } 1043 } 1044 1045 void pcg_ret(Parser* p, int has_value) { 1046 if (has_value) { 1047 if (pcg_emit_enabled(p)) kit_cg_ret(p->cg); 1048 pcg_drop_type(p); 1049 } else if (pcg_emit_enabled(p)) { 1050 /* No value supplied. For a void function this is the normal 0-result 1051 * return. For a non-void function it is a UB fall-off-the-end or an 1052 * already-diagnosed bare `return;` — terminate with unreachable rather 1053 * than asking kit_cg_ret to pop a result that was never pushed. */ 1054 if (p->cur_func_ret && p->cur_func_ret->kind != TY_VOID) 1055 kit_cg_unreachable(p->cg); 1056 else 1057 kit_cg_ret(p->cg); 1058 } 1059 } 1060 1061 void pcg_alloca(Parser* p) { 1062 if (pcg_emit_enabled(p)) { 1063 kit_cg_alloca(p->cg, 16, pcg_tid(p, type_ptr(p->pool, type_void(p->pool)))); 1064 } 1065 pcg_drop_type(p); 1066 pcg_push_type(p, type_ptr(p->pool, type_void(p->pool))); 1067 } 1068 1069 void pcg_va_arg(Parser* p, const Type* ty) { 1070 if (pcg_emit_enabled(p)) kit_cg_vararg_next(p->cg, pcg_tid(p, ty)); 1071 pcg_drop_type(p); 1072 pcg_push_type(p, ty); 1073 } 1074 1075 void pcg_va_start(Parser* p) { 1076 if (pcg_emit_enabled(p)) kit_cg_vararg_start(p->cg); 1077 } 1078 1079 void pcg_va_end(Parser* p) { 1080 if (pcg_emit_enabled(p)) kit_cg_vararg_end(p->cg); 1081 } 1082 1083 void pcg_va_copy(Parser* p) { 1084 if (pcg_emit_enabled(p)) kit_cg_vararg_copy(p->cg); 1085 } 1086 1087 void pcg_atomic_load(Parser* p, MemOrder ord) { 1088 const Type* pty = pcg_top_type(p); 1089 const Type* ty = (pty && pty->kind == TY_PTR) ? pty->ptr.pointee : pty; 1090 if (pcg_emit_enabled(p)) { 1091 kit_cg_atomic_load(p->cg, pcg_mem(p, ty), pcg_mem_order(ord)); 1092 } 1093 pcg_retag_top(p, ty); 1094 } 1095 1096 void pcg_atomic_store(Parser* p, MemOrder ord) { 1097 const Type* pty = pcg_top2_type(p); 1098 const Type* ty = (pty && pty->kind == TY_PTR) ? pty->ptr.pointee : pty; 1099 if (pcg_emit_enabled(p)) { 1100 kit_cg_atomic_store(p->cg, pcg_mem(p, ty), pcg_mem_order(ord)); 1101 } 1102 pcg_drop_type(p); 1103 pcg_drop_type(p); 1104 } 1105 1106 void pcg_atomic_rmw(Parser* p, AtomicOp op, MemOrder ord) { 1107 const Type* pty = pcg_top2_type(p); 1108 const Type* ty = (pty && pty->kind == TY_PTR) ? pty->ptr.pointee : pty; 1109 if (pcg_emit_enabled(p)) { 1110 kit_cg_atomic_rmw(p->cg, pcg_mem(p, ty), pcg_atomic_op(op), 1111 pcg_mem_order(ord)); 1112 } 1113 pcg_drop_type(p); 1114 pcg_retag_top(p, ty); 1115 } 1116 1117 void pcg_atomic_cas(Parser* p, MemOrder succ, MemOrder fail) { 1118 const Type* ty = pcg_top2_type(p); 1119 if (pcg_emit_enabled(p)) { 1120 kit_cg_atomic_cmpxchg(p->cg, pcg_mem(p, ty), pcg_mem_order(succ), 1121 pcg_mem_order(fail), 0); 1122 } 1123 pcg_drop_type(p); /* desired */ 1124 pcg_drop_type(p); /* expected */ 1125 pcg_drop_type(p); /* pointer */ 1126 pcg_push_type(p, ty); 1127 pcg_push_type(p, type_prim(p->pool, TY_BOOL)); 1128 } 1129 1130 void pcg_fence(Parser* p, MemOrder ord) { 1131 if (pcg_emit_enabled(p)) kit_cg_atomic_fence(p->cg, pcg_mem_order(ord)); 1132 } 1133 1134 void pcg_intrinsic_unary_to_int(Parser* p, IntrinKind k) { 1135 KitCgIntrinsic ck = k == INTRIN_CLZ ? KIT_CG_INTRIN_CLZ 1136 : k == INTRIN_CTZ ? KIT_CG_INTRIN_CTZ 1137 : KIT_CG_INTRIN_POPCOUNT; 1138 const Type* ity = type_prim(p->pool, TY_INT); 1139 if (pcg_emit_enabled(p)) { 1140 kit_cg_intrinsic(p->cg, ck, 1, pcg_tid(p, ity)); 1141 } 1142 pcg_retag_top(p, ity); 1143 } 1144 1145 void pcg_intrinsic_void(Parser* p, IntrinKind k) { 1146 if (k == INTRIN_UNREACHABLE) { 1147 if (pcg_emit_enabled(p)) kit_cg_unreachable(p->cg); 1148 } else { 1149 if (pcg_emit_enabled(p)) { 1150 kit_cg_intrinsic(p->cg, KIT_CG_INTRIN_TRAP, 0, KIT_CG_TYPE_NONE); 1151 } 1152 } 1153 } 1154 1155 void pcg_syscall(Parser* p, u32 nargs, const Type* long_ty) { 1156 if (pcg_emit_enabled(p)) 1157 kit_cg_intrinsic(p->cg, KIT_CG_INTRIN_SYSCALL, nargs, pcg_tid(p, long_ty)); 1158 for (u32 i = 0; i < nargs; ++i) pcg_drop_type(p); 1159 pcg_push_type(p, long_ty); 1160 } 1161 1162 /* __builtin_return_address(level) / __builtin_frame_address(level): emit the 1163 * frame-pointer-chain intrinsic. The constant level rides as a single immediate 1164 * operand (kept as OPK_IMM by kit_cg_intrinsic); the result is void*. */ 1165 void pcg_frame_or_return_address(Parser* p, int is_return, u32 level) { 1166 const Type* void_ptr = type_ptr(p->pool, type_void(p->pool)); 1167 KitCgIntrinsic intrin = 1168 is_return ? KIT_CG_INTRIN_RETURN_ADDRESS : KIT_CG_INTRIN_FRAME_ADDRESS; 1169 pcg_push_int(p, (i64)level, type_prim(p->pool, TY_INT)); 1170 if (pcg_emit_enabled(p)) 1171 kit_cg_intrinsic(p->cg, intrin, 1, pcg_tid(p, void_ptr)); 1172 /* kit_cg_intrinsic popped the level operand and pushed the void* result; 1173 * retag the slot pcg_push_int added (also clears the level's value flags, 1174 * e.g. the null-pointer-constant tag set for level 0). */ 1175 pcg_retag_top(p, void_ptr); 1176 } 1177 1178 void pcg_inline_asm(Parser* p, const char* tmpl, const AsmConstraint* outs, 1179 u32 nout, const AsmConstraint* ins, u32 nin, 1180 const Sym* clobbers, u32 nclob) { 1181 KitCgInlineAsm a; 1182 KitCgAsmOperand* o = NULL; 1183 KitCgAsmOperand* in = NULL; 1184 KitSym* cl = NULL; 1185 memset(&a, 0, sizeof a); 1186 a.tmpl = kit_sym_intern(p->c, kit_slice_cstr(tmpl ? tmpl : "")); 1187 if (nout) { 1188 o = arena_zarray(p->pool->arena, KitCgAsmOperand, nout); 1189 for (u32 i = 0; i < nout; ++i) { 1190 o[i].constraint = 1191 kit_sym_intern(p->c, kit_slice_cstr(outs[i].str ? outs[i].str : "")); 1192 o[i].name = outs[i].name; 1193 o[i].type = pcg_tid(p, outs[i].type); 1194 o[i].reg = outs[i].reg; 1195 o[i].dir = KIT_CG_ASM_OUT; 1196 } 1197 } 1198 if (nin) { 1199 in = arena_zarray(p->pool->arena, KitCgAsmOperand, nin); 1200 for (u32 i = 0; i < nin; ++i) { 1201 in[i].constraint = 1202 kit_sym_intern(p->c, kit_slice_cstr(ins[i].str ? ins[i].str : "")); 1203 in[i].name = ins[i].name; 1204 in[i].type = pcg_tid(p, ins[i].type); 1205 in[i].reg = ins[i].reg; 1206 in[i].dir = (ins[i].dir == ASM_INOUT) ? KIT_CG_ASM_INOUT : KIT_CG_ASM_IN; 1207 } 1208 } 1209 if (nclob) { 1210 cl = arena_array(p->pool->arena, KitSym, nclob); 1211 for (u32 i = 0; i < nclob; ++i) cl[i] = clobbers[i]; 1212 } 1213 a.outputs = o; 1214 a.noutputs = nout; 1215 a.inputs = in; 1216 a.ninputs = nin; 1217 a.clobbers = cl; 1218 a.nclobbers = nclob; 1219 if (pcg_emit_enabled(p)) kit_cg_inline_asm(p->cg, a); 1220 /* Mirror kit_cg_inline_asm's stack effect on the parser's typed shadow stack. */ 1221 for (u32 i = 0; i < nin; ++i) pcg_drop_type(p); 1222 for (u32 i = 0; i < nout; ++i) pcg_push_type(p, outs[i].type); 1223 }