From ed62e8199f60fe1de1af507b1e12c98b4f3c5048 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Thu, 4 Jun 2026 23:40:31 +0900 Subject: [PATCH] =?UTF-8?q?wcc=5Fww/check:=20tuple=20size()=20fold=20reads?= =?UTF-8?q?=20the=20type=20table=20=E2=80=94=20packed-sum=20C-t0=20escape?= =?UTF-8?q?=20(#22=20commit=200)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- selfhost/cmd/w6c/main.combined.ww | 16 +++++++++------- selfhost/cmd/wcc/check.ww | 16 +++++++++------- selfhost/cmd/wwdump/main.combined.ww | 16 +++++++++------- test/wcc/941_tuple_slot_layout_run.c | 27 +++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index f64bfbfe..560cc90d 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -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; diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index 4424529c..8020727d 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -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; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 1e732119..b2c4e737 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -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; diff --git a/test/wcc/941_tuple_slot_layout_run.c b/test/wcc/941_tuple_slot_layout_run.c index 41de90e7..26c80a83 100644 --- a/test/wcc/941_tuple_slot_layout_run.c +++ b/test/wcc/941_tuple_slot_layout_run.c @@ -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