w6c: keep nested unwrap destinations distinct

This commit is contained in:
2026-08-09 04:52:43 +09:00
parent 7ab080fe2a
commit a2faa8b071
3 changed files with 103 additions and 15 deletions

View File

@@ -39,11 +39,6 @@ static int *cg_frame;
* semantics for synthetic scratches). 0 means "not yet allocated";
* negative offsets returned by local_alloc are the live value. */
static int cg_retscr;
/* The aggregate-unwrap receiver must survive its producer call without
* perturbing SP: an outstanding PUSHQ at CALL violates SysV alignment.
* One BP-relative address spill per function mirrors wwstage's @-prefix
* scratch reuse. */
static int cg_unwrapdst;
/* Per-fn @tupfscr offset (single-slot SSoT). A multi-float tuple return
* (#164/#107) spills each float out of X0 to this scratch as the L→R
* element walk clobbers X0, then reloads X0/X1 by SSE index after the
@@ -5367,14 +5362,12 @@ cgexpr(Cg *c, Node *n, Local *locals)
fatal("#16: global/chained aggregate "
"unwrap field dest unresolved "
"(cgplaceaddr)");
int dstscr;
if (cg_unwrapdst != 0) {
dstscr = cg_unwrapdst;
} else {
dstscr = local_alloc(c, &locals, "@unwrapdst",
8, cg_frame);
cg_unwrapdst = dstscr;
}
/* Fresh per lowering: cgexpr(rhs) may recursively
* emit another #16 assignment while this address is
* live. Sharing one per-fn slot would let the inner
* assignment overwrite the outer receiver. */
int dstscr = local_alloc(c, &locals, "@unwrapdst",
8, cg_frame);
ins2(c, A_MOVQ, areg(D_BX), amem(D_BP, dstscr));
cgexpr(c, n->rhs, locals);
ins2(c, A_MOVQ, amem(D_BP, dstscr), areg(D_BX));
@@ -15803,7 +15796,6 @@ cgfn(Cg *c, FILE *out, Node *fn)
nloops = 0;
cg_ret_type = fn->type ? fn->type->ret : NULL;
cg_retscr = 0;
cg_unwrapdst = 0;
cg_tupfscr = 0;
cg_tupargscr = 0;
cg_tupargscr_sz = 0;