wcc+w6c+w6c_ww: tuple slot layout SSoT — checker size = cgen slot stride (C-t0)

The checker computed TY_TUPLE size as the packed element-size sum
((u32,u32) = 8B) while every cgen cursor-transport site strode 8B
slots (16B). 16B tuples were blind to the split (slot == packed);
packed tuples hit it everywhere: cstage let-receive keyed on sz 16/32
missed sz 8 and dropped word 1, the cgfn param receive spilled
8B/element into a packed-sized local (saved-BP clobber, SIGSEGV), and
mixed (u32,f64)/(u32,str) shapes missed the receive arms entirely.

Slot layout is now the SSoT (user-ratified): the flip lives in the two
checkers' N_TTUPLE size computation only (check.c, check.ww
tupleelemslot + stamp); cgen's packed-keyed walks (t.N read, #235 len
arm, over-cap sret send/receive pair) align onto the slot stride, and
the wwstage t.N read gains the natural-width load (tnodeloadop) to
byte-id with cstage's fldloadop. ttupleelem.offset re-stamped
slot-cumulative (no consumers yet). The #242/#243 eightbyte-share
loud-stop dissolves by construction (no two narrows ever share an
eightbyte) — 940's eightbyte_share row graduates to a runtime
round-trip. Hare-layout divergence documented at both checker sites;
re-alignment is task #60. #32 send skew and #33 wwstage literal-let
receive are separate commits on this base.

941_tuple_slot_layout_run pins the matrix: 4 packed rows fail at the
parent (8/21 checks), 3 neutral anchors prove 16B/32B emission
untouched.
This commit is contained in:
2026-06-04 18:20:07 +09:00
parent 0139652180
commit fdfc2ce318
9 changed files with 500 additions and 106 deletions

View File

@@ -29,14 +29,14 @@
* Construction is correct at ANY variant position (the variant tag, not a
* default-0) — `tuple_tag1` and `tuple_after_int` place the tuple at index 1.
*
* SCOPE (rule 7 loud-stops, PINNED by the K_BUILDERR rows): a tuple built
* SCOPE (rule 7 loud-stop, PINNED by the K_BUILDERR row): a tuple built
* from a BARE LITERAL element (cstage mis-types `true`/`false`/untyped `7` →
* tag unresolved, #241 literal-init family; wwstage types them but mirrors
* cstage's CONDITION down per rule 10) and a tuple whose narrow elements
* SHARE a SysV eightbyte (e.g. (i32,i32,u64), needs eightbyte classification,
* #243) both loud-stop in cgen on BOTH stages rather than silently
* miscompile. The K_RUN rows build their tuple from TYPED expressions — the
* supported, byte-identical shape.
* cstage's CONDITION down per rule 10) loud-stops in cgen on BOTH stages
* rather than silently miscompile. The old eightbyte-share loud-stop
* ((i32,i32,u64), #243) DISSOLVED with the slot-SSoT tuple layout (tuple
* arc C-t0) — that row graduated to K_RUN below. The K_RUN rows build
* their tuple from TYPED expressions — the supported, byte-identical shape.
*
* K_RUN rows: build+run exit 0 on BOTH drivers AND cs==ww byte-identical.
* K_BUILDERR rows: build FAILS with the #242 diagnostic on BOTH drivers.
@@ -165,19 +165,30 @@ static const struct row rows[] = {
" };\n"
" return 4;\n"
"};\n", K_RUN, 0, NULL },
/* rule-7 loud-stop (i): a tuple whose narrow elements SHARE a SysV
* eightbyte ((i32,i32,u64) — i32@0,i32@4,u64@8 packs to 16B, but the
* 8B-slotted write needs 24B) overflows the union payload. Both stages
* MUST loud-stop (eightbyte classification is the #243 follow-up), not
* silently miscompile. Typed params -> the tag resolves; the SIZE guard
* fires. */
/* C-t0 graduation (was the #242/#243 loud-stop): under the slot-SSoT
* tuple layout narrow elements never share an eightbyte —
* (i32,i32,u64) is 24B (3 slots), the slotted union write fits by
* construction, and the whole tuple round-trips through the union.
* cg_widen_tagged_store's size guard stays as a safety net but can
* no longer fire for an in-cap tuple. */
{ "eightbyte_share",
"package main;\n"
"fn f(a: i32, b: i32, c: u64) ((i32, i32, u64) | void) = {\n"
" return (a, b, c);\n"
"};\n"
"export fn main() i32 = { return 0; };\n",
K_BUILDERR, 0, "needs SysV eightbyte packing" },
"export fn main() i32 = {\n"
" match (f(-3, 4, 9u64)) {\n"
" case let t: (i32, i32, u64) => {\n"
" let (x, y, z) = t;\n"
" if (x != -3) { return 1; };\n"
" if (y != 4) { return 2; };\n"
" if (z != 9u64) { return 3; };\n"
" return 0;\n"
" };\n"
" case void => { return 4; };\n"
" };\n"
" return 5;\n"
"};\n", K_RUN, 0, NULL },
/* rule-7 loud-stop (ii): a tuple built from a BARE LITERAL element
* (`true`). cstage's cg_tag_for_variant can't type the literal (#241)
* so it returns -1 and loud-stops; wwstage types `true` as bool and