w6c/cgen: #71 chained-dot walks chase alias-typed hops — direct offsets, byte-id graduation

rob probe-ruled F1 enrollment (fold-or-file decided by the dispatch
test): the chained-dot STORE walk, its READ twin, and the addr-of
sibling each single-peeled every hop's type, so an alias-typed field
(type fa = inner; outer{x: fa}) aborted the offset-folding fast arm and
fell to the generic address spine — store via cgplaceaddr
(PUSHQ/LEAQ/ADDQ/POPQ), read via ADDQ-per-hop. Runtime-correct BOTH
stages; byte-id NO vs wwstage's folded direct MOVQ offsets
(reviewer-62r diamond find). Chasing the walk hops (+ the read arm's
leaf gate and the two ptr-root sub peels) flips cs onto the fast arm =
wwstage's asm exactly.

Blast radius measured per rob's caution: bootstrap asm cmp-identical
vs the pristine 738d7f4 scratch on all five main.combined.ww, 989
lib_byteid pins unchanged (31/9/3), every control row byte-id — the
flip moves ONLY the #71 shapes.

test: 944_alias_accept_run +2 rows, both decl orders: nested store +
last-field readback; the fwd row adds the &v.y.b addr-of + deref-write
leg. Mutation-checked at the 738d7f4 scratch: both rows byte-id-diff
there; 70/70 green here.

Also graduates the reviewer-F1 slicefield rows: their `.len` readbacks
ride this walk, so the 7 K_RUN_CS rows from commit 1 flip to K_RUN
(byte-id) here.
This commit is contained in:
2026-06-05 11:43:35 +09:00
parent c138605563
commit ac63951d54
2 changed files with 66 additions and 22 deletions

View File

@@ -50,6 +50,10 @@
* | store/push word0-only; CS-ONLY until |
* | F2 lands the wwstage half; base ctl |
* | + the #54-bound `as` row pinned loud | 0(cs)
* nested_alias_field_* | task #71: alias-typed nested-field |
* | store/read/addr-of walks fold to |
* | direct offsets (byte-id graduation, |
* | both decl orders) | 0
*
* K_RUN rows also assert cstage/wwstage asm byte-id (acceptance
* graduations land byte-identical — F0's accept side was wwstage).
@@ -275,10 +279,9 @@ static const struct row rows[] = {
* noise() call clobbers BX/CX so stale-register luck can't pass a
* word0-only header. Unprobed sibling gates are LOUD-tripwired,
* pinned by the #73 row at the end of this block. Rows whose
* `.len` readback rides the chained-dot READ walk are K_RUN_CS
* here (runtime-correct both stages; cs takes the generic spine
* pre-#71) and flip to K_RUN at the #71 walk-chase commit, which
* graduates their byte-id. */
* `.len` readback rides the chained-dot READ walk entered as
* K_RUN_CS (runtime-correct both stages; cs took the generic
* spine) and graduated to K_RUN with the #71 walk chase. */
{ "slicefield_store_2lvl",
"package main;\n"
"type sl = []int;\n"
@@ -294,7 +297,7 @@ static const struct row rows[] = {
" if (b.s[2] != 900) { return 2; };\n"
" if (b.s.len != 3) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN_CS, NULL }, /* ->K_RUN at the #71 walk-chase commit */
"};\n", 0, K_RUN, NULL },
{ "slicefield_range_2lvl",
"package main;\n"
"type sl = []int;\n"
@@ -311,7 +314,7 @@ static const struct row rows[] = {
" if (x < 700) { return 3; };\n"
" };\n"
" return 0;\n"
"};\n", 0, K_RUN_CS, NULL }, /* ->K_RUN at the #71 walk-chase commit */
"};\n", 0, K_RUN, NULL },
{ "strfield_store_2lvl",
"package main;\n"
"type s1t = str;\n"
@@ -323,7 +326,7 @@ static const struct row rows[] = {
" b.n = 5;\n"
" if (b.s.len != 5) { return 1; };\n"
" return 0;\n"
"};\n", 0, K_RUN_CS, NULL }, /* ->K_RUN at the #71 walk-chase commit */
"};\n", 0, K_RUN, NULL },
{ "slicefield_structlit_2lvl",
"package main;\n"
"type sl = []int;\n"
@@ -336,7 +339,7 @@ static const struct row rows[] = {
" if (b.s.len != 3) { return 2; };\n"
" if (b.s[2] != 900) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN_CS, NULL }, /* ->K_RUN at the #71 walk-chase commit */
"};\n", 0, K_RUN, NULL },
{ "slicefield_viaptr_2lvl",
"package main;\n"
"type sl = []int;\n"
@@ -350,7 +353,7 @@ static const struct row rows[] = {
" if (p.s.len != 3) { return 1; };\n"
" if (p.s[2] != 900) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN_CS, NULL }, /* ->K_RUN at the #71 walk-chase commit */
"};\n", 0, K_RUN, NULL },
{ "slicefield_chainstore_2lvl",
"package main;\n"
"type sl = []int;\n"
@@ -364,7 +367,7 @@ static const struct row rows[] = {
" if (v.i.s.len != 3) { return 1; };\n"
" if (v.i.s[2] != 900) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN_CS, NULL }, /* ->K_RUN at the #71 walk-chase commit */
"};\n", 0, K_RUN, NULL },
{ "slicefield_ptrchain_2lvl",
"package main;\n"
"type sl = []int;\n"
@@ -381,7 +384,7 @@ static const struct row rows[] = {
" if (i.s.len != 3) { return 1; };\n"
" if (i.s[2] != 900) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN_CS, NULL }, /* ->K_RUN at the #71 walk-chase commit */
"};\n", 0, K_RUN, NULL },
{ "slicefield_chainread_2lvl",
"package main;\n"
"type sl = []int;\n"
@@ -749,6 +752,42 @@ static const struct row rows[] = {
" };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* ---- task #71 (rob probe-ruled F1 enrollment): nested fields
* whose TYPES are aliases. The chained-dot store/read/addr-of
* walks single-peeled each hop, aborted on the alias, and fell
* to the generic PUSHQ/LEAQ/ADDQ/POPQ address spine — runtime-
* correct but byte-id NO vs wwstage's folded direct offsets.
* Chasing the walks converges cs onto the direct arm = ww's asm.
* Distinct values; the LAST field of the SECOND member checked. */
{ "nested_alias_field_norm",
"package main;\n"
"type fa = inner;\n"
"type inner = struct { a: size, b: size };\n"
"type outer = struct { x: fa, y: fa };\n"
"export fn main() i32 = {\n"
" let v: outer;\n"
" v.x.a = 4; v.x.b = 9;\n"
" v.y.a = 7; v.y.b = 3;\n"
" if (v.x.b != 9) { return 1; };\n"
" if (v.y.b != 3) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "nested_alias_field_fwd",
"package main;\n"
"type outer = struct { x: fa, y: fa };\n"
"type fa = inner;\n"
"type inner = struct { a: size, b: size };\n"
"export fn main() i32 = {\n"
" let v: outer;\n"
" v.x.a = 4; v.x.b = 9;\n"
" v.y.a = 7; v.y.b = 3;\n"
" if (v.x.b != 9) { return 1; };\n"
" if (v.y.b != 3) { return 2; };\n"
" let pa = &v.y.b;\n"
" *pa = 11;\n"
" if (v.y.b != 11) { return 3; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* banked row L2-3 (`v as ali` readback) trips task #54's as-binding
* aggregate-init bound — LOUD both stages today; fold the row into
* #54's pin set on its fold (do not drop). Pinned here as the