selfhost: cgmatch bsz for TY_STRUCT variant bind (closes #31)
Match-arm bind size in wwstage hardcoded str=16, []T=24, else=8 in both cgmatch (emit) and scanlocals (frame pre-scan). A TY_STRUCT variant fell into the 8B fallback: only the first quadword reached the bind, and the prologue SUBQ underbooked the frame so the emit-time localalloc(bsz=24+) wrote past SP. Replace the hand-rolled table with slotsize(c, pat) at both sites. slotsize already covers N_TNAME named structs (returns si.totsize), str (16), []T (24), tuples, aliases, and primitives (8). Mirrors cstage cgen.c cgmatch which falls through to bu->size for TY_STRUCT. Cstage is correct; no mirror needed. Test 695 covers seven shapes: the 3xi64 headline repro, a 4xi64 struct via let-init scrut (exercises >24B bind), a mixed-quadword struct (i32+i32+i64+i64), str/slice/i32 negative controls, and a direct let-init scrutinee variant. The wider 4xi64 row uses the let-init shape because the N_DOT spill path in cgmatch tops out at AX/DX/CX/R8 — a separate, unrelated gap from the bind size.
This commit is contained in:
@@ -150,9 +150,17 @@ fn scanlocals(c: *cgen, n: *node) i32 = {
|
||||
if (bn.len > 0) {
|
||||
let pat: *node = n.lhs;
|
||||
if (pat != nil) {
|
||||
if (isstrtype(c, pat)) { total += 16; }
|
||||
else { if (isslicetype(c, pat)) { total += 24; }
|
||||
else { total += 8; }; };
|
||||
// Must mirror cgmatch's bind-slot sizing in
|
||||
// cgenexpr.ww (`bsz = slotsize(c, pat)`):
|
||||
// hardcoding str/slice/8 here underbooked the
|
||||
// frame for TY_STRUCT variants — the emit-time
|
||||
// localalloc(bsz=24) then wrote past the SUBQ'd
|
||||
// SP, smashing whatever the OS put under it
|
||||
// (project #31).
|
||||
let psz: i32 = slotsize(c, pat);
|
||||
if (psz <= 0) { psz = 8; };
|
||||
if ((psz & 7) != 0) { psz = (psz + 7) & ~7; };
|
||||
total += psz;
|
||||
};
|
||||
};
|
||||
// Match arms get a fresh local scope at emission time
|
||||
|
||||
Reference in New Issue
Block a user