wcc/ww: store through a *tagged pointer widens, both stages (#17)

The N_UN/TK_STAR plain-deref assign arm fell to a single fldstoreop for
every pointee, so `*p = v` with p:*tagged wrote the rhs into the tag word
and never the payload -- identically in both stages, leaving the byte-id
gate green while the store corrupted the tag (#263-class, gate-blind).

Gate on TY_TAGGED and route through cg_widen_tagged_store into a scratch
slot, then word-copy to the destination -- the proven runtime-index arm.
Scalar pointees keep the single-store path unchanged.
This commit is contained in:
2026-06-13 23:54:12 +09:00
parent 728d86518e
commit 1074239859
6 changed files with 399 additions and 0 deletions

View File

@@ -512,6 +512,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_single_field_struct_zeroinit \
$(BIN)/test_structvariant_largeunion_return \
$(BIN)/test_narrow_alias_deref_store \
$(BIN)/test_taggedderefstore_run \
$(BIN)/test_bufio_vstream_run \
$(BIN)/test_log_vstream_run \
$(BIN)/test_use_promote_alias \
@@ -821,6 +822,23 @@ $(BIN)/test_structcopytail_run: test/wcc/989_structcopytail_run.c \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
# 989_taggedderefstore_run (#17): a deref-target store `*p = v` (p:*tagged)
# sized the write off the pointee and emitted ONE fldstoreop — rhs landed in
# the tag word, payload dropped, the union discriminant corrupted. BOTH-stage-
# wrong and byte-id-green (#263-class, gate-blind): cstage cmd/w6c/cgen.c #17
# deref else-branch + wwstage cgenexpr.ww #17 single-store tail emitted the
# SAME wrong asm. #17 routes the tagged-pointee deref store through the widener
# (cg_widen_tagged_store / cgwidentaggedstore) via the shared tag scratch, then
# word-copies scratch -> *p (mirror of the index-element tagged arm). Builds+
# runs on BOTH driver twins (rule-10), pinning the absolute 0; scalarctl pins
# the unchanged non-tagged single-store path.
$(BIN)/test_taggedderefstore_run: test/wcc/989_taggedderefstore_run.c \
$(BIN)/ww $(BIN)/ww_ww \
$(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
# 989_arrlit_tail_zero_run (#13): an under-length array literal zero-fills the
# unspecified tail, not the last value. Builds+runs on BOTH driver twins
# (rule-10), pinning the absolute value (pre-fix ww tail = last value).