wcc: tuple slice-element read loads the full 24B header, both stages

Reading a slice-typed tuple element (t.0) loaded only the pointer
word; len and cap took whatever was left in BX/CX — silent garbage in
BOTH stages once anything clobbered the registers between build and
read. Load all three header words at the tuple-element arm. Review
item #28.

Both stages move in one commit: one emission contract; splitting
would leave the byte-id gates red between the halves.
This commit is contained in:
2026-06-12 21:04:35 +09:00
parent 850746cfa8
commit 0a6f500b8c
5 changed files with 73 additions and 12 deletions

View File

@@ -100,6 +100,45 @@ static const struct row rows[] = {
" let v: []u8 = s: []u8;\n"
" return v.cap: i32;\n"
"};\n", 4, K_RUN, NULL },
/* #28 (#263 both-stages): tuple slice-element read `t.0` over a
* ([]u8, i64). A clobber() call between the tuple build and the
* read leaves junk in BX/CX; pre-fix the str-only arm fell to the
* scalar tail (ptr word only), so ys.len read stale BX. Reads len
* == 5 (distinct from any stale value) → 0. */
{ "tuple_slice_elem",
"package main;\n"
"fn clobber() i64 = {\n"
" let a: i64 = 111;\n"
" let b: i64 = 222;\n"
" return a + b;\n"
"};\n"
"export fn main() i32 = {\n"
" let xs: []u8 = [1u8, 2u8, 3u8, 4u8, 5u8];\n"
" let t: ([]u8, i64) = (xs, 7);\n"
" let junk: i64 = clobber();\n"
" let ys: []u8 = t.0;\n"
" if (ys.len == 5) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_RUN, NULL },
/* #28 sibling: the slice element sits at tuple position 1 (foff != 0:
* an i64 occupies slot 0, the []u8 header starts at +8). Exercises the
* widened arm's offset arithmetic, which the position-0 row leaves
* untested. Same clobber()-between-build-and-read trigger; len == 6. */
{ "tuple_slice_elem_pos1",
"package main;\n"
"fn clobber() i64 = {\n"
" let a: i64 = 111;\n"
" let b: i64 = 222;\n"
" return a + b;\n"
"};\n"
"export fn main() i32 = {\n"
" let xs: []u8 = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8];\n"
" let t: (i64, []u8) = (9, xs);\n"
" let junk: i64 = clobber();\n"
" let ys: []u8 = t.1;\n"
" if (ys.len == 6) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_RUN, NULL },
};
static int