diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index e3842bfc..20b1fc08 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -8369,12 +8369,36 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // sum-type shapes through NAMED variants). r = newtype(tykind.TY_TAGGED); tinfocachebind(c.tc, n, r); + // #50 / A.6.3f phase 1: populate ti.params as a tparam linked + // list (head=first source variant) in lock-step with the + // size/align accumulator. Mirrors cstage check.c:374-396 — + // same Tparam shape ww reuses across struct-fields / tuple- + // fields / fn-params / tagged-variants (sea-of-stars per rule + // 12). Phase 2 (#50b) retires cgenutil's AST-keyed + // nullableptrtag onto the chain. + let head: *tparam = nil; + let tail: *tparam = nil; + let maxsz: u64 = 0u64; + let al: u64 = 8u64; + let v: *node = n.list; + for (v != nil) { + let vt: *tinfo = tinfofornode(c, v); + let tp: *tparam = alloc(tparam{name="", type_=vt, tnext=nil})!; + if (head == nil) { head = tp; } else { tail.tnext = tp; }; + tail = tp; + if (vt != nil) { + if (vt.size > maxsz) { maxsz = vt.size; }; + if (vt.align > al) { al = vt.align; }; + }; + v = v.next; + }; + r.params = head; // #61 A.3 nullable fold: `(*T | void)` collapses to a single // 8B pointer slot, null is the void variant. Mirrors // cmd/wcc/check.c:412-426 — bare TNAME("void"), not `!void`, - // and not NAMED — so wwstage slotsize fast-path can graduate - // TY_TAGGED off the AST-walker fallback. Match before counting - // variants so the 8B fold lands in tinfo.size directly. + // and not NAMED. AST-kind discrimination retained: wwstage + // tinfo carries no `iserror` field, so cstage's tinfo-level + // (kind==TY_VOID && !iserror) check doesn't port symmetrically. let a: *node = n.list; if (a != nil) { let b: *node = a.next; @@ -8393,22 +8417,10 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { r.align = 8u64; r.nullable = 1; r.slotsize = 8u64; - tinfocachebind(c.tc, n, r); return r; }; }; }; - let maxsz: u64 = 0u64; - let al: u64 = 8u64; - let v: *node = n.list; - for (v != nil) { - let vt: *tinfo = tinfofornode(c, v); - if (vt != nil) { - if (vt.size > maxsz) { maxsz = vt.size; }; - if (vt.align > al) { al = vt.align; }; - }; - v = v.next; - }; let pad: u64 = (maxsz + 7u64) & ~7u64; r.size = 8u64 + pad; r.align = al; diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index c6a39a79..711945ff 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -1299,12 +1299,36 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // sum-type shapes through NAMED variants). r = newtype(tykind.TY_TAGGED); tinfocachebind(c.tc, n, r); + // #50 / A.6.3f phase 1: populate ti.params as a tparam linked + // list (head=first source variant) in lock-step with the + // size/align accumulator. Mirrors cstage check.c:374-396 — + // same Tparam shape ww reuses across struct-fields / tuple- + // fields / fn-params / tagged-variants (sea-of-stars per rule + // 12). Phase 2 (#50b) retires cgenutil's AST-keyed + // nullableptrtag onto the chain. + let head: *tparam = nil; + let tail: *tparam = nil; + let maxsz: u64 = 0u64; + let al: u64 = 8u64; + let v: *node = n.list; + for (v != nil) { + let vt: *tinfo = tinfofornode(c, v); + let tp: *tparam = alloc(tparam{name="", type_=vt, tnext=nil})!; + if (head == nil) { head = tp; } else { tail.tnext = tp; }; + tail = tp; + if (vt != nil) { + if (vt.size > maxsz) { maxsz = vt.size; }; + if (vt.align > al) { al = vt.align; }; + }; + v = v.next; + }; + r.params = head; // #61 A.3 nullable fold: `(*T | void)` collapses to a single // 8B pointer slot, null is the void variant. Mirrors // cmd/wcc/check.c:412-426 — bare TNAME("void"), not `!void`, - // and not NAMED — so wwstage slotsize fast-path can graduate - // TY_TAGGED off the AST-walker fallback. Match before counting - // variants so the 8B fold lands in tinfo.size directly. + // and not NAMED. AST-kind discrimination retained: wwstage + // tinfo carries no `iserror` field, so cstage's tinfo-level + // (kind==TY_VOID && !iserror) check doesn't port symmetrically. let a: *node = n.list; if (a != nil) { let b: *node = a.next; @@ -1323,22 +1347,10 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { r.align = 8u64; r.nullable = 1; r.slotsize = 8u64; - tinfocachebind(c.tc, n, r); return r; }; }; }; - let maxsz: u64 = 0u64; - let al: u64 = 8u64; - let v: *node = n.list; - for (v != nil) { - let vt: *tinfo = tinfofornode(c, v); - if (vt != nil) { - if (vt.size > maxsz) { maxsz = vt.size; }; - if (vt.align > al) { al = vt.align; }; - }; - v = v.next; - }; let pad: u64 = (maxsz + 7u64) & ~7u64; r.size = 8u64 + pad; r.align = al; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index c6a3e8a4..5ac78ace 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -8369,12 +8369,36 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // sum-type shapes through NAMED variants). r = newtype(tykind.TY_TAGGED); tinfocachebind(c.tc, n, r); + // #50 / A.6.3f phase 1: populate ti.params as a tparam linked + // list (head=first source variant) in lock-step with the + // size/align accumulator. Mirrors cstage check.c:374-396 — + // same Tparam shape ww reuses across struct-fields / tuple- + // fields / fn-params / tagged-variants (sea-of-stars per rule + // 12). Phase 2 (#50b) retires cgenutil's AST-keyed + // nullableptrtag onto the chain. + let head: *tparam = nil; + let tail: *tparam = nil; + let maxsz: u64 = 0u64; + let al: u64 = 8u64; + let v: *node = n.list; + for (v != nil) { + let vt: *tinfo = tinfofornode(c, v); + let tp: *tparam = alloc(tparam{name="", type_=vt, tnext=nil})!; + if (head == nil) { head = tp; } else { tail.tnext = tp; }; + tail = tp; + if (vt != nil) { + if (vt.size > maxsz) { maxsz = vt.size; }; + if (vt.align > al) { al = vt.align; }; + }; + v = v.next; + }; + r.params = head; // #61 A.3 nullable fold: `(*T | void)` collapses to a single // 8B pointer slot, null is the void variant. Mirrors // cmd/wcc/check.c:412-426 — bare TNAME("void"), not `!void`, - // and not NAMED — so wwstage slotsize fast-path can graduate - // TY_TAGGED off the AST-walker fallback. Match before counting - // variants so the 8B fold lands in tinfo.size directly. + // and not NAMED. AST-kind discrimination retained: wwstage + // tinfo carries no `iserror` field, so cstage's tinfo-level + // (kind==TY_VOID && !iserror) check doesn't port symmetrically. let a: *node = n.list; if (a != nil) { let b: *node = a.next; @@ -8393,22 +8417,10 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { r.align = 8u64; r.nullable = 1; r.slotsize = 8u64; - tinfocachebind(c.tc, n, r); return r; }; }; }; - let maxsz: u64 = 0u64; - let al: u64 = 8u64; - let v: *node = n.list; - for (v != nil) { - let vt: *tinfo = tinfofornode(c, v); - if (vt != nil) { - if (vt.size > maxsz) { maxsz = vt.size; }; - if (vt.align > al) { al = vt.align; }; - }; - v = v.next; - }; let pad: u64 = (maxsz + 7u64) & ~7u64; r.size = 8u64 + pad; r.align = al;