cgen: str chained-*struct field read -> 3-word -- Phase 2 C4.6 caseB (both stages)

The chained N_DOT path (o.p.f, depth>=2, base AX) still loaded a str-typed field as 2 words, dropping cap -- the C4.6 sibling deferred to caseB. Fold the str case onto the adjacent 3-word slice-field arm (widen kind-gate: cstage type_isstr, ww typeisstr; never size==24). Emits len->BX+8, cap->CX+16, ptr->AX+0 LAST (AX is the base). cstage==wwstage byte-identical; the slice arm is unchanged for slices.

test/wcc/934: table-driven runtime .cap-survives over the chained read; the row interposes a CX-clobbering call so a 2-word read cannot coincidentally pass on stale CX (per the 933 discriminator lesson). Verified fail-before/pass-after on both drivers.

main.combined.ww regenerated via the canonical make path (md5-stable).
This commit is contained in:
2026-05-24 13:57:20 +09:00
parent 90deeb3821
commit 634cbefc22
6 changed files with 199 additions and 52 deletions

View File

@@ -256,6 +256,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_str_abi_run \
$(BIN)/test_str_elem_cap_run \
$(BIN)/test_str_field_cap_run \
$(BIN)/test_str_chained_field_cap_run \
$(BIN)/test_composite_call_arg \
$(BIN)/test_composite_call_arg_run \
$(BIN)/test_letdecl_zeroinit \
@@ -634,6 +635,12 @@ $(BIN)/test_str_field_cap_run: test/wcc/933_str_field_cap_run.c \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_str_chained_field_cap_run: test/wcc/934_str_chained_field_cap_run.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_composite_call_arg: test/wcc/723_composite_call_arg.c \
$(BIN)/w6c $(BIN)/w6c_ww | $(BIN)
$(CC) $(CFLAGS) -o $@ $<