A `let t: [N][]u8 = [a, b]` / `[N]str` literal init lowered each
element's {ptr,len,cap} header into AX/BX/CX (cgexpr) but stored only
some words: a slice element fell through to the scalar 1-word MOVQ
(dropping .len AND .cap), a str element stored 2 words (dropping .cap,
latent). Each element is 24B (post-#1) and must be copied whole.
wwstage was worse — a slice element matched no esz branch, so esz
stayed the 8 sentinel: the per-element stride collapsed (element i+1
overwrote element i's tail), the -96-vs-80 cs!=ww frame divergence.
This is the str/slice arm of the #270 aggregate-element-store family.
struct/array/tuple already copy correctly via the #270-1c is_agg
multi-word path; str/slice were the documented follow-up (cgen.c:9037,
cgenstmt.ww deferral). They can't join is_agg (that path word-copies
from a source slot and rejects non-ident/structlit elements, whereas
str/slice elements are commonly exprs cgexpr lowers into registers) —
the correct mechanism is the existing register header store, extended.
Fix (BOTH stages, converged byte-identical): cstage adds
is_slice_el = type_isslice(esub) and stores 3 words (incl CX->base+16,
the cap) for `is_str_el || is_slice_el`, in the main loop and the
repeat-fill. wwstage adds isslicel (esubti.kind == TY_SLICE -> esz =
esubti.size, fixing the stride) and the matching 3-word store. Closes
[N][]u8 (the bug) and the latent [N]str cap-drop in one branch.
The latent str cap-drop is now stored, but the indexed-element `.cap`
READ (`t[i].cap`) stays broken — a distinct cgindex/dot-selector bug,
cs!=ww divergent, filed as task #13. The new test validates the stored
cap via a whole-element copy (`let q = t[i]; q.cap`), which reads
through the correct ident-load path. [N]tagged literal init is the
remaining sibling (is_agg excludes TY_TAGGED), task #12.
Test 683_arr_strslice_elem: table-driven, dual-stage runtime + asm
byte-id; slice/str .len, 3-element stride-24, cap-via-copy, .ptr deref,
plus a [N]struct regression pin proving the is_agg path is untouched.
This commit is contained in:
7
Makefile
7
Makefile
@@ -240,6 +240,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
|
||||
$(BIN)/test_amp_dot $(BIN)/test_arr_elem_field \
|
||||
$(BIN)/test_arr_elem_field_write \
|
||||
$(BIN)/test_arr_enum_elem \
|
||||
$(BIN)/test_arr_strslice_elem \
|
||||
$(BIN)/test_dot_str_chained_arg \
|
||||
$(BIN)/test_dot_slice_arg \
|
||||
$(BIN)/test_dot_tagged_source \
|
||||
@@ -554,6 +555,12 @@ $(BIN)/test_arr_enum_elem: test/wcc/682_arr_enum_elem.c $(BIN)/ww \
|
||||
$(LIB)/libwwrt.a | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
$(BIN)/test_arr_strslice_elem: test/wcc/683_arr_strslice_elem.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 \
|
||||
|
||||
Reference in New Issue
Block a user