wcc/ww: match on a tagged struct-field scrutinee reads it in place (#25)

wwstage cgmatch unconditionally spilled any non-ident match scrutinee
-- including an addressable BP-relative N_DOT struct field -- into
@match_spill and dispatched off the copy (frame $48); cstage reads
such a field in place at its BP offset ($32). Both stages were already
runtime-correct (latent rule-10 leanness, not a miscompile); this
aligns wwstage down to cstage so the asm is byte-identical.

The new in-place arm mirrors cstage cgen.c:10241-10296 verbatim: an
N_DOT scrutinee with a bare N_IDENT base whose type chases to a value
TY_STRUCT and whose field is found by name reads tag/payload at
localfind(base)+field.offset. The *ptr-field and call-result cases
stay on the spill path by construction (their base does not chase to
TY_STRUCT) -- no extra guard. A global value-struct base mis-resolves
identically in both stages (localfind returns 0); left untouched as a
shared latent (#29), since a ww-only guard would break byte-id.

Regenerates the w6c and wwdump combined.ww. Table-driven 831 test:
6 rows (local-field, *ptr-field, plain-ident, call-result, payload
remap, str payload) x runtime-both-stages + cs-vs-ww byte-id.
This commit is contained in:
2026-06-14 11:59:11 +09:00
parent 851915e6fe
commit 533333bd1a
5 changed files with 415 additions and 0 deletions

View File

@@ -341,6 +341,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_tagged_return_scratch \
$(BIN)/test_tagged_widen_f64 \
$(BIN)/test_match_spill_pointer_payload \
$(BIN)/test_match_field_inplace \
$(BIN)/test_struct_byval_param \
$(BIN)/test_struct_multi_return_scratch \
$(BIN)/test_signed_data_emit \
@@ -2113,6 +2114,12 @@ $(BIN)/test_match_spill_pointer_payload: test/wcc/716_match_spill_pointer_payloa
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_match_field_inplace: test/wcc/831_match_field_inplace.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_struct_byval_param: test/wcc/717_struct_byval_param.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \