cgen: #38a chained-dot TAGGED leaf — cursor read + widen store, value-chain + ptr-chain, both stages
A tagged leaf at the end of a dot chain (depth >= 2) fell to the
one-word scalar tail in FOUR walkers — the value-chain read spine,
the value-chain assign walker, the chained-*struct read branch, and
the chained-*struct assign branch — in BOTH stages, byte-identical,
gate-blind:
READ: one MOVQ pulled the TAG word only; is-tests passed by
tag-luck while as/match/let consumers read stale DX/CX/R8
as payload (ken x5c: o.r.min as size added entry-zero DX —
want 28 got 20; ken b8 same through a mid-chain *rep).
ASSIGN: one sized store landed the rhs ON the tag slot, payload
kept its old bytes (ken x5d: `o.r.min = 8: size` made the
following is-test false).
The single-dot arms were already correct — each fix is that arm
verbatim at the chained site:
read: the tagged cursor (AX=tag, DX=val0, R8=val2 before
CX=val1 — the base may live in CX/AX; >32B box leaves its
ADDRESS in AX, the #37 mem-read convention). wwstage rides
the existing cgloadtaggedfield helper; the *struct-base
branches stage AX into BX first (cursor targets AX).
assign: full slot rewrite via the shared widener
(cg_widen_tagged_store / cgwidentaggedstore, base BX/BP),
plain `=` only — compound on tagged stays loud (#133).
The nested-LITERAL half of the old #38 filing dissolved: the
canonical fill's tagged-field widen delegation (#23, 413aafa) already
covers any depth — x5c's literal init emits a correct tag at HEAD;
only the chained READ/ASSIGN halves were live (probe-proven, asm at
/tmp/pB).
Probes converge byte-id and runtime-correct: x5c/d/e (28), depth-2
(b3/b9), (void|str) 32B box + match readback (b5), *outer root (b7),
mid-chain *rep (b8), non-tagged control (f38a). 938 rows chained_*
pin all six shapes. Residuals filed, not folded (rule 11): the
INDEX-spine sibling xs[i].min payload read (task #58); tagged-field
GLOBALS stay loud at DATA emit (#129 A.2), so the walkers'
global arms are mirror-only today.
Task #38.
This commit is contained in:
@@ -433,6 +433,102 @@ static const struct row rows[] = {
|
||||
* after void, arg widen, the bool-leading skip, and the signed
|
||||
* (void|i64) variant (ken hB3); the cast form rides alongside as
|
||||
* the no-drift control (it was always right). */
|
||||
/* #38a: chained-dot TAGGED leaf — the dot-spine walkers (value
|
||||
* chain + ptr chain, both stages) had no TY_TAGGED leaf arm, so
|
||||
* READS pulled one word (tag; as/match consumers read stale DX
|
||||
* payload, ken x5c want-28-got-20) and ASSIGNS stored the rhs
|
||||
* over the TAG slot (ken x5d). Six rows: literal-init read,
|
||||
* assign-then-read, depth-3 chain read-before-write (ken hB1),
|
||||
* (void|str) 32B box incl. void-over-str write (ken hB2),
|
||||
* *outer root, mid-chain *rep. The INDEX-spine sibling
|
||||
* (xs[i].min) is filed separately (task #58) — NOT a row here. */
|
||||
{ "chained_tagged_literal_read",
|
||||
"package main;\n"
|
||||
"type rep = struct { id: size, min: (void | size), name: (void | str) };\n"
|
||||
"type outer = struct { tag: size, r: rep };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let o = outer { tag = 4: size, r = rep { id = 6: size, min = 8: size, name = void } };\n"
|
||||
" if (o.tag != 4) { return 1; };\n"
|
||||
" if (o.r.id != 6) { return 2; };\n"
|
||||
" if (!(o.r.min is size)) { return 3; };\n"
|
||||
" if (o.r.min as size != 8) { return 4; };\n"
|
||||
" if (!(o.r.name is void)) { return 5; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0 },
|
||||
{ "chained_tagged_assign",
|
||||
"package main;\n"
|
||||
"type rep = struct { id: size, min: (void | size) };\n"
|
||||
"type outer = struct { tag: size, r: rep };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let o: outer = outer { tag = 4: size, r = rep { id = 6: size, min = void } };\n"
|
||||
" o.r.min = 8: size;\n"
|
||||
" if (!(o.r.min is size)) { return 1; };\n"
|
||||
" if (o.r.min as size != 8) { return 2; };\n"
|
||||
" o.r.min = 9;\n"
|
||||
" if (!(o.r.min is size)) { return 3; };\n"
|
||||
" if (o.r.min as size != 9) { return 4; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0 },
|
||||
{ "chained_tagged_depth2",
|
||||
"package main;\n"
|
||||
"type rep = struct { id: size, min: (void | size) };\n"
|
||||
"type mid = struct { m: size, r: rep };\n"
|
||||
"type outer = struct { tag: size, w: mid };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let o = outer { tag = 4: size, w = mid { m = 2: size, r = rep { id = 6: size, min = 5: size } } };\n"
|
||||
" if (!(o.w.r.min is size)) { return 5; };\n"
|
||||
" if (o.w.r.min as size != 5) { return 6; };\n"
|
||||
" o.w.r.min = 8: size;\n"
|
||||
" if (o.w.m != 2) { return 1; };\n"
|
||||
" if (o.w.r.id != 6) { return 2; };\n"
|
||||
" if (!(o.w.r.min is size)) { return 3; };\n"
|
||||
" if (o.w.r.min as size != 8) { return 4; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0 },
|
||||
{ "chained_tagged_strvariant",
|
||||
"package main;\n"
|
||||
"type rep = struct { id: size, nm: (void | str) };\n"
|
||||
"type outer = struct { tag: size, r: rep };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let o = outer { tag = 4: size, r = rep { id = 6: size, nm = void } };\n"
|
||||
" o.r.nm = \"hello\";\n"
|
||||
" if (!(o.r.nm is str)) { return 1; };\n"
|
||||
" if ((o.r.nm as str).len != 5) { return 2; };\n"
|
||||
" match (o.r.nm) {\n"
|
||||
" case let s: str => { if (s.len != 5) { return 3; }; };\n"
|
||||
" case void => { return 4; };\n"
|
||||
" };\n"
|
||||
" o.r.nm = void;\n"
|
||||
" if (!(o.r.nm is void)) { return 5; };\n"
|
||||
" if (o.r.id != 6) { return 6; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0 },
|
||||
{ "chained_tagged_ptrroot",
|
||||
"package main;\n"
|
||||
"type rep = struct { id: size, min: (void | size) };\n"
|
||||
"type outer = struct { tag: size, r: rep };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let o = outer { tag = 4: size, r = rep { id = 6: size, min = void } };\n"
|
||||
" let p: *outer = &o;\n"
|
||||
" p.r.min = 8: size;\n"
|
||||
" if (p.r.id != 6) { return 1; };\n"
|
||||
" if (!(p.r.min is size)) { return 2; };\n"
|
||||
" if (p.r.min as size != 8) { return 3; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0 },
|
||||
{ "chained_tagged_ptrmid",
|
||||
"package main;\n"
|
||||
"type rep = struct { id: size, min: (void | size) };\n"
|
||||
"type outer = struct { tag: size, p: *rep };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let r = rep { id = 6: size, min = void };\n"
|
||||
" let o = outer { tag = 4: size, p = &r };\n"
|
||||
" o.p.min = 8: size;\n"
|
||||
" if (o.p.id != 6) { return 1; };\n"
|
||||
" if (!(o.p.min is size)) { return 2; };\n"
|
||||
" if (o.p.min as size != 8) { return 3; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, 0 },
|
||||
{ "untyped_int_bare_widen",
|
||||
"package main;\n"
|
||||
"fn take(v: (void | size)) i32 = {\n"
|
||||
|
||||
Reference in New Issue
Block a user