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:
2026-05-15 02:07:34 +09:00
parent 19fb3a3b3c
commit df74d9c429
6 changed files with 405 additions and 30 deletions

View File

@@ -223,6 +223,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_dot_slice_arg \
$(BIN)/test_dot_tagged_source \
$(BIN)/test_tagged_store_intlit \
$(BIN)/test_match_bind_struct \
$(BIN)/test_field_signed $(BIN)/test_frame_argcount \
$(BIN)/test_selfhost $(BIN)/test_w6a_ww $(BIN)/test_w6l_ww \
$(BIN)/test_w6c_ww $(BIN)/test_ww_ww $(BIN)/test_self_rebuild \
@@ -340,6 +341,12 @@ $(BIN)/test_tagged_store_intlit: test/wcc/694_tagged_store_intlit.c $(BIN)/ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_match_bind_struct: test/wcc/695_match_bind_struct.c $(BIN)/ww \
$(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_field_signed: test/wcc/660_field_signed.c $(BIN)/ww \
$(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \