wcc+w6c_ww: append through pointer-to-slice place via cgplaceaddr (FA1)

Re-key the append() lowering from BP-displacement assumptions onto a
resolver-provided header PLACE (task #15, the add_thread hard-blocker;
cgplaceaddr's third consumer after C1/C1.25). One mirrored choke-point,
two failure modes: cstage 0-defaulted sn_off for any non-ident target,
so 0(BP)/8(BP) became the "slice header" and rt_ensure corrupted the
CALLER frame (SIGSEGV); wwstage cgappend silently emitted nothing
(gate-blind cs!=ww).

cg_append_grow/cg_append_slot (mirror cgappendgrow/cgappendslot) factor
the 5 grow + 5 slot header-access sites. Ident-local targets keep the
legacy BP-disp emission byte-identical (probed across all 9 existing
source shapes, before/after .s). Non-ident targets resolve once through
cgplaceaddr and spill the header address to an @apphdrscr slot:
rt_ensure may realloc .ptr but never moves the header, so the slot
stays valid; every access reloads from it. The slot is allocated fresh
per append SITE, not cached per fn: a nested append-through-pointer
inside a value expression (match-yield arm) spills its own resolve, and
a shared slot would hand the outer grow/slot reloads the inner target's
header — silent cross-slice corruption (pinned by the reentrant_value
row). Indirect mode keys esz/element-kind/load-op off the
checker-stamped target tinfo (no declared tnode behind `*p`; the
#209/#211 discipline). Unwired target places die LOUD "#15: append()
target place unsupported (rule-7)" on BOTH stages — the
silent-corruption class is closed by construction.

The FA4/#35 boundary is unchanged: non-ident spread SOURCES stay loud
(pinned by a reject row). Surfaced pre-existing checker divergence
filed as task #34 (wwstage rejects global slice-lit let).

test/wcc/806: 14 runtime rows (element kinds x target shapes, spread,
narrow-signed spread load, cap-crossing realloc loop with branched
callee + caller-frame sentinels, deref-spine target, nested-append
reentrancy, direct-arm neutrality pin) + 2 exact-text reject rows,
both drivers + per-row cs==ww asm byte-id.
This commit is contained in:
2026-06-04 10:25:56 +09:00
parent 48df04a8ca
commit b630a7cf20
6 changed files with 1186 additions and 463 deletions

View File

@@ -392,6 +392,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_delete_elem \
$(BIN)/test_placeaddr_store \
$(BIN)/test_tryprop_multisuccess \
$(BIN)/test_append_place \
$(BIN)/test_struct_tuple_field_slot \
$(BIN)/test_widen_pad_zero_run \
$(BIN)/test_named_ptr_alias_variant_widen \
@@ -1035,6 +1036,16 @@ $(BIN)/test_tryprop_multisuccess: test/wcc/806_tryprop_multisuccess.c \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
# FA1 (task #15, regex fold-2b): append(*p, v) / append(*p, xs...)
# through a pointer-to-slice place via the cgplaceaddr resolver —
# runtime rows across element kinds + spread + realloc/frame-integrity
# + loud-tail reject rows w/ exact diagnostic text + cs==ww asm byte-id.
$(BIN)/test_append_place: test/wcc/806_append_place.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6c_ww $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
# #237: a tuple-typed struct field must contribute its real slot width to
# the enclosing struct's slotsize — pure cs==ww .s byte-id (frame size).
$(BIN)/test_struct_tuple_field_slot: test/wcc/930_struct_tuple_field_slot.c \