w6c+wwstage: len() of tuple-element slice reads .len not .ptr (#235)

len() special-cased only a plain N_IDENT slice operand (load .len at
BP+off+8) and an array operand (fold $alen); every other shape fell back
to a bare cgexpr(operand), which for a slice leaves AX=.ptr. A tuple-
element read (t.N) loads only AX=.ptr, so len(t.N) on a slice/str tuple
element returned the slice's .ptr word AS its length — a silent
miscompile, gate-blind because the bootstrap never does len() on a
slice-typed tuple element (sibling of the #234/#237 tuple-sret cluster).

Both stages: detect a slice/str tuple-element len() operand and load the
element's .len word directly at BP + element_off + 8, mirroring the
N_IDENT slice arm and the tuple-field-offset walk (element_off sums
preceding element sizes through the type table). Byte-identical asm
(rule 10). The separate tuple-element-read full-header gap is #238; a
leading-scalar mixed-tuple has its own pre-existing sret-layout cs/ww
divergence, filed apart from #235.

Test 903_tuple_elem_slice_len_run: 4 slice/str-only tuple rows (two/
three slices, str+slice, slice+str; distinct lengths), build+run both
drivers + cs==ww byte-id. 12/12 ok.
This commit is contained in:
2026-06-01 18:17:07 +09:00
parent 20fe5419d2
commit 6acddc3a82
6 changed files with 428 additions and 0 deletions

View File

@@ -290,6 +290,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_deref_slice_store_run \
$(BIN)/test_tuple_nary_destructure_run \
$(BIN)/test_overcap_tuple_field_store_run \
$(BIN)/test_tuple_elem_slice_len_run \
$(BIN)/test_str_forrange_loopvar_run \
$(BIN)/test_composite_call_arg \
$(BIN)/test_composite_call_arg_run \
@@ -1169,6 +1170,13 @@ $(BIN)/test_overcap_tuple_field_store_run: test/wcc/940_overcap_tuple_field_stor
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
# #235: len() of a tuple-element slice/str reads .len (+8) not .ptr.
$(BIN)/test_tuple_elem_slice_len_run: test/wcc/903_tuple_elem_slice_len_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 $@ $<