wcc: chained-dot str leaf loads the cap word, both stages

A str field reached through a chained dot (o.i.s) emitted two loads
(ptr, len) and stored a stale CX as the cap — both stages, at any
non-zero chain depth. Emit the full header at the chained-dot leaf.
Review item #29.

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:07:55 +09:00
parent 0a6f500b8c
commit f00775759d
5 changed files with 75 additions and 119 deletions

View File

@@ -139,6 +139,36 @@ static const struct row rows[] = {
" if (ys.len == 6) { return 0; };\n"
" return 1;\n"
"};\n", 0, K_RUN, NULL },
/* #29 (#263 both-stages): chained-dot str leaf `o.i.s` (depth-2)
* dropped the cap word — a junk strlit before the chain left CX
* stale, so t.cap read 2 (the junk's cap) instead of 5. Now the
* str leaf loads all three header words like the slice arm. */
{ "chained_str_cap",
"package main;\n"
"type inner = struct { s: str, x: i64 };\n"
"type outer = struct { i: inner, y: i64 };\n"
"export fn main() i32 = {\n"
" let iv: inner = inner { s = \"hello\", x = 0 };\n"
" let o: outer = outer { i = iv, y = 0 };\n"
" let junk: str = \"ab\";\n"
" let t: str = o.i.s;\n"
" return t.cap: i32;\n"
"};\n", 5, K_RUN, NULL },
/* #29 sibling: the str leaf sits at a NON-ZERO field offset within the
* inner struct (a leading i64 pad pushes `s` to +8, so totaloff != 0).
* Exercises the chained-leaf offset arithmetic the offset-0 row leaves
* untested. Junk strlit before the chain; cap == len == 7. */
{ "chained_str_cap_offset",
"package main;\n"
"type inner = struct { pad: i64, s: str };\n"
"type outer = struct { i: inner, y: i64 };\n"
"export fn main() i32 = {\n"
" let iv: inner = inner { pad = 0, s = \"worldly\" };\n"
" let o: outer = outer { i = iv, y = 0 };\n"
" let junk: str = \"ab\";\n"
" let t: str = o.i.s;\n"
" return t.cap: i32;\n"
"};\n", 7, K_RUN, NULL },
};
static int