w6c+w6c_ww: store full slice header for struct-literal slice fields (fix #24)

cg_structlit_fill / cgstructlitfill had a TY_STR arm that stored all
three header words (ptr@+0, len@+8, cap@+16) but no TY_SLICE arm, so a
slice field in a struct literal `cl{ items = b, n = .. }` fell through to
the generic scalar tail and stored only the ptr word — the field's .len
and .cap read 0. str fields (the same 24B {ptr,len,cap} shape) worked;
slice fields silently dropped two words.

Both stages emitted IDENTICAL wrong asm, so the 990-997 byte-id gate was
green on both-wrong; runtime readback is the only correctness net. Same
is_str/is_slice discrimination gap as #10 part-b, here in the
struct-literal field-init path.

A slice is the same 24B header shape as str, so widen the str arm's
guard to TY_STR || TY_SLICE (cstage) / isstrtype || isslicetype
(wwstage) and let a slice ride the already-correct 3-word store. The
TAGGED arm stays ordered before it, so a nullable/tagged slice
(TY_TAGGED) still routes to the widener, not the 3-word store.

Test 689 (table-driven, runtime readback + dual-stage asm byte-id):
slice .len/.cap/.ptr, a scalar field beside/before the slice, a slice at
a non-zero field offset, two slice fields, and a str field beside a
slice (str-arm regression pin). 33/33 ok.
This commit is contained in:
2026-06-03 23:51:28 +09:00
parent b6a41ae063
commit c490ed3ec1
6 changed files with 374 additions and 8 deletions

View File

@@ -246,6 +246,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_slice_str_global_zero \
$(BIN)/test_slice_literal_global \
$(BIN)/test_global_arr_elem_field \
$(BIN)/test_structlit_slice_field \
$(BIN)/test_dot_str_chained_arg \
$(BIN)/test_dot_slice_arg \
$(BIN)/test_dot_tagged_source \
@@ -597,6 +598,12 @@ $(BIN)/test_global_arr_elem_field: test/wcc/688_global_arr_elem_field.c $(BIN)/w
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_structlit_slice_field: test/wcc/689_structlit_slice_field.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_dot_str_chained_arg: test/wcc/692_dot_str_chained_arg.c $(BIN)/ww \
$(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \