wcc_ww/check: tuple size() fold reads the type table — packed-sum C-t0 escape (#22 commit 0)

The wwstage size()/align() fold walks the AST (astsize), and its
N_TTUPLE arm still summed PACKED element sizes — C-t0 flipped the
checker type table (tupleelemslot) and cstage's N_TTUPLE to the
ratified slot layout but missed this second wwstage sizer.
size((u32,u32)) folded to 16 on cstage and 8 on wwstage: a silent
cs≠ww in every folded tuple-size constant, plus the recursive
escapes (a tuple inside struct/array size computation under the
fold). Runtime-confirmed at 74767c7.

astsize N_TTUPLE now reads the tuple tinfo, making tupleelemslot
the single wwstage tuple sizer; the tagged-element slot fix (#22
22a) lands in that one place next. 941 gains c0_sizefold_slot +
c0_sizefold_recursive rows (exit-checked under both drivers +
byte-id).
This commit is contained in:
2026-06-04 23:40:31 +09:00
parent a2c2bbc6b1
commit ed62e8199f
4 changed files with 54 additions and 21 deletions

View File

@@ -11309,13 +11309,15 @@ fn astsize(c: *checker, t: *node) i64 = {
return astsize(c, t.lhs) * elen;
};
if (k == nkind.N_TTUPLE) {
let total: i64 = 0i64;
let p: *node = t.list;
for (p != nil) {
total += astsize(c, p.lhs);
p = p.next;
};
return total;
// Route through the type table, NOT a packed element-sum:
// slot layout is the tuple SSoT (C-t0, user-ratified) and
// tupleelemslot is its one wwstage answer. The packed walk
// this replaces was a C-t0 escape — size((u32,u32)) folded
// to 8 here while cstage (check.c N_TTUPLE) and the wwstage
// type table both said 16 (task #22 commit 0).
let ti: *tinfo = tinfofornode(c, t);
if (ti != nil) { return ti.size: i64; };
return 0i64;
};
if (k == nkind.N_TSTRUCT) {
let off: i64 = 0i64;

View File

@@ -1045,13 +1045,15 @@ fn astsize(c: *checker, t: *node) i64 = {
return astsize(c, t.lhs) * elen;
};
if (k == nkind.N_TTUPLE) {
let total: i64 = 0i64;
let p: *node = t.list;
for (p != nil) {
total += astsize(c, p.lhs);
p = p.next;
};
return total;
// Route through the type table, NOT a packed element-sum:
// slot layout is the tuple SSoT (C-t0, user-ratified) and
// tupleelemslot is its one wwstage answer. The packed walk
// this replaces was a C-t0 escape — size((u32,u32)) folded
// to 8 here while cstage (check.c N_TTUPLE) and the wwstage
// type table both said 16 (task #22 commit 0).
let ti: *tinfo = tinfofornode(c, t);
if (ti != nil) { return ti.size: i64; };
return 0i64;
};
if (k == nkind.N_TSTRUCT) {
let off: i64 = 0i64;

View File

@@ -11309,13 +11309,15 @@ fn astsize(c: *checker, t: *node) i64 = {
return astsize(c, t.lhs) * elen;
};
if (k == nkind.N_TTUPLE) {
let total: i64 = 0i64;
let p: *node = t.list;
for (p != nil) {
total += astsize(c, p.lhs);
p = p.next;
};
return total;
// Route through the type table, NOT a packed element-sum:
// slot layout is the tuple SSoT (C-t0, user-ratified) and
// tupleelemslot is its one wwstage answer. The packed walk
// this replaces was a C-t0 escape — size((u32,u32)) folded
// to 8 here while cstage (check.c N_TTUPLE) and the wwstage
// type table both said 16 (task #22 commit 0).
let ti: *tinfo = tinfofornode(c, t);
if (ti != nil) { return ti.size: i64; };
return 0i64;
};
if (k == nkind.N_TSTRUCT) {
let off: i64 = 0i64;

View File

@@ -182,6 +182,33 @@ static const struct row rows[] = {
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* ---- #22 commit 0: the wwstage size()/align() fold (astsize)
* summed PACKED element sizes for N_TTUPLE — a C-t0 escape. The
* type table (tupleelemslot) and cstage both said slot-sum;
* size((u32,u32)) folded to 16 on cstage and 8 on wwstage —
* silent cs≠ww in any folded constant. astsize now reads the
* tuple tinfo, so the slot SSoT has ONE wwstage answer. The
* recursive escapes (tuple inside struct/array sizing) ride the
* same arm. ---- */
{ "c0_sizefold_slot",
"package main;\n"
"export fn main() i32 = {\n"
" if (size((u32, u32)) != 16) { return 1; };\n"
" if (size((size, size)) != 16) { return 2; };\n"
" if (size((u32, str)) != 32) { return 3; };\n"
" if (size((str, str)) != 48) { return 4; };\n"
" if (align((u32, u32)) != 4) { return 5; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
{ "c0_sizefold_recursive",
"package main;\n"
"type holder = struct { t: (u32, u32), x: i64 };\n"
"export fn main() i32 = {\n"
" if (size(holder) != 24) { return 1; };\n"
" if (size([4](u32, u32)) != 64) { return 2; };\n"
" return 0;\n"
"};\n", 0, K_RUN, NULL },
/* ---- C-t1 (#33): the let RECEIVE re-keyed onto the declared
* type's register classify. Pre-C-t1 wwstage keyed on producer
* SHAPE (mixed-str syntactic / rettupleof N_CALL) so a