selfhost+test: size match-spill slot by scrutinee, not 24B (#9)
wwstage cgmatch hardcoded `spillsz = 24` + unconditional CX write
where cstage emits `slot_size = (su->kind == TY_TAGGED) ? su->size
: 16` with `if (slot_size > 16)` gating. For 1-word-payload variants
like `(*u8 | oserror)` the slot is 16B; wwstage over-allocated and
over-wrote past the receiver's read window.
Factor cgmatch's non-ident scrutinee-type resolution + spill sizing
into matchscrutt + matchspillsz in cgenutil.ww. cgmatch gates CX
write on `spillsz > 16`; R8 gate `> 24` already correct. scanlocals
N_MATCH branch uses the same helpers — scan+emit lockstep.
Test 716: 4 rows × {cstage runtime, wwstage runtime, asm-byte-id}.
Aliased (*u8 | oserror) ok/err arms, raw (*u8 | i64) for hypothesis
breadth, (str | i64) 24B regression guard.
This commit is contained in:
@@ -168,14 +168,19 @@ fn scanlocals(c: *cgen, n: *node) i32 = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// `match (non-ident)` needs a 24B `@match_spill` scratch slot for
|
||||
// cgmatch to land the AX:DX:CX return triple. Mirrors C cgen's
|
||||
// localoff("@match_spill", ...). N_IDENT scrutinees read the slot
|
||||
// `match (non-ident)` needs an `@match_spill` scratch slot sized
|
||||
// to the scrutinee's tagged-union slot (16/24/32 for 1/2/3-word
|
||||
// payload). Mirrors cstage's `slot_size = su->size` default 16
|
||||
// in cmd/w6c/cgen.c cgmatch (task #9 align-down to cstage).
|
||||
// matchspillsz must agree with cgmatch's emit-time computation
|
||||
// for scan+emit lockstep. N_IDENT scrutinees read the slot
|
||||
// directly off the local — no spill needed.
|
||||
if (n.kind == nkind.N_MATCH) {
|
||||
let sc: *node = n.lhs;
|
||||
if (sc != nil) {
|
||||
if (sc.kind != nkind.N_IDENT) { total += 24; };
|
||||
if (sc.kind != nkind.N_IDENT) {
|
||||
total += matchspillsz(c, matchscrutt(c, sc));
|
||||
};
|
||||
};
|
||||
};
|
||||
// Match-arm binding (`case let v: T => ...`) gets a slot too.
|
||||
|
||||
Reference in New Issue
Block a user