diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index c8b9426e..e0301fde 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -8124,10 +8124,16 @@ fn enumvalfold(body: *node, until: *node, e: *node, out: *u64) bool = { // fallback arm). fn tupleelemslot(pt: *tinfo) u64 = { if (pt == nil) { return 8u64; }; - let pk: tykind = pt.kind; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + let t: *tinfo = pt; + for (t != nil && t.kind == tykind.TY_NAMED) { t = t.under; }; + if (t == nil) { return 8u64; }; + let pk: tykind = t.kind; if (pk == tykind.TY_VOID) { return 0u64; }; - if (pk == tykind.TY_STR) { return pt.size; }; - if (pk == tykind.TY_SLICE) { return pt.size; }; + if (pk == tykind.TY_STR) { return t.size; }; + if (pk == tykind.TY_SLICE) { return t.size; }; if (pk == tykind.TY_PTR || pk == tykind.TY_FN || pk == tykind.TY_CHAN || pk == tykind.TY_I64 || pk == tykind.TY_U64 || pk == tykind.TY_INT || @@ -8139,7 +8145,7 @@ fn tupleelemslot(pt: *tinfo) u64 = { pk == tykind.TY_U16 || pk == tykind.TY_U32 || pk == tykind.TY_F32 || pk == tykind.TY_ENUM) { return 8u64; }; // Composite — struct/tuple/array/tagged carry their own slot total. - return pt.slotsize; + return t.slotsize; }; // #61 A.5 helper: per-field slot size mirroring cgenutil.ww @@ -8149,17 +8155,23 @@ fn tupleelemslot(pt: *tinfo) u64 = { // pad-to-8); arrays use their slot-padded element-stride * elen. fn fieldslotsize(ft: *tinfo) u64 = { if (ft == nil) { return 8u64; }; - let fk: tykind = ft.kind; - if (fk == tykind.TY_STRUCT) { return ft.slotsize; }; - if (fk == tykind.TY_ARRAY) { return ft.slotsize; }; - if (fk == tykind.TY_TAGGED) { return ft.size; }; - // str / slice read ft.size so the typ.ww SSoT seed is the single + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + let t: *tinfo = ft; + for (t != nil && t.kind == tykind.TY_NAMED) { t = t.under; }; + if (t == nil) { return 8u64; }; + let fk: tykind = t.kind; + if (fk == tykind.TY_STRUCT) { return t.slotsize; }; + if (fk == tykind.TY_ARRAY) { return t.slotsize; }; + if (fk == tykind.TY_TAGGED) { return t.size; }; + // str / slice read t.size so the typ.ww SSoT seed is the single // source for #1 (str→24) / #34 (slice graduation) — no hardcoded // literal here to drift. - if (fk == tykind.TY_SLICE) { return ft.size; }; + if (fk == tykind.TY_SLICE) { return t.size; }; if (fk == tykind.TY_PTR || fk == tykind.TY_FN || fk == tykind.TY_CHAN) { return 8u64; }; - if (fk == tykind.TY_STR) { return ft.size; }; + if (fk == tykind.TY_STR) { return t.size; }; // Primitives keep natural width inside structs (matches // cgenutil fieldsize: primsize, not pad-to-8). TY_TUPLE inside a // struct currently defaults to 8 in cgenutil — preserve that @@ -8171,7 +8183,7 @@ fn fieldslotsize(ft: *tinfo) u64 = { fk == tykind.TY_U32 || fk == tykind.TY_U64 || fk == tykind.TY_INT || fk == tykind.TY_UINT || fk == tykind.TY_UINTPTR || fk == tykind.TY_F32 || - fk == tykind.TY_F64 || fk == tykind.TY_ENUM) { return ft.size; }; + fk == tykind.TY_F64 || fk == tykind.TY_ENUM) { return t.size; }; return 8u64; }; @@ -12148,6 +12160,11 @@ fn slotsize(c: *cgen, typn: *node) i32 = { if (typn == nil) { return 8; }; let ti: *tinfo = typn.type_: *tinfo; if (ti == nil) { return 8; }; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + for (ti != nil && ti.kind == tykind.TY_NAMED) { ti = ti.under; }; + if (ti == nil) { return 8; }; let kk: tykind = ti.kind; if (kk == tykind.TY_VOID) { return 0; }; if (kk == tykind.TY_PTR || kk == tykind.TY_SLICE || @@ -12180,6 +12197,11 @@ fn fieldsize(c: *cgen, tnode: *node) i32 = { if (tnode == nil) { return 8; }; let ti: *tinfo = tnode.type_: *tinfo; if (ti == nil) { return 8; }; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + for (ti != nil && ti.kind == tykind.TY_NAMED) { ti = ti.under; }; + if (ti == nil) { return 8; }; let k: tykind = ti.kind; if (k == tykind.TY_STRUCT) { return ti.slotsize: i32; }; if (k == tykind.TY_ARRAY) { return ti.slotsize: i32; }; @@ -12524,6 +12546,11 @@ export fn nullableptrtag(t: *node) i32 = { if (t == nil) { return 0; }; let ti: *tinfo = t.type_: *tinfo; if (ti == nil) { return 0; }; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + for (ti != nil && ti.kind == tykind.TY_NAMED) { ti = ti.under; }; + if (ti == nil) { return 0; }; if (ti.kind != tykind.TY_TAGGED) { return 0; }; let p: *tparam = ti.params; let i: i32 = 0; diff --git a/selfhost/cmd/wcc/cgenutil.ww b/selfhost/cmd/wcc/cgenutil.ww index 71866849..9fdd5147 100644 --- a/selfhost/cmd/wcc/cgenutil.ww +++ b/selfhost/cmd/wcc/cgenutil.ww @@ -1671,6 +1671,11 @@ fn slotsize(c: *cgen, typn: *node) i32 = { if (typn == nil) { return 8; }; let ti: *tinfo = typn.type_: *tinfo; if (ti == nil) { return 8; }; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + for (ti != nil && ti.kind == tykind.TY_NAMED) { ti = ti.under; }; + if (ti == nil) { return 8; }; let kk: tykind = ti.kind; if (kk == tykind.TY_VOID) { return 0; }; if (kk == tykind.TY_PTR || kk == tykind.TY_SLICE || @@ -1703,6 +1708,11 @@ fn fieldsize(c: *cgen, tnode: *node) i32 = { if (tnode == nil) { return 8; }; let ti: *tinfo = tnode.type_: *tinfo; if (ti == nil) { return 8; }; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + for (ti != nil && ti.kind == tykind.TY_NAMED) { ti = ti.under; }; + if (ti == nil) { return 8; }; let k: tykind = ti.kind; if (k == tykind.TY_STRUCT) { return ti.slotsize: i32; }; if (k == tykind.TY_ARRAY) { return ti.slotsize: i32; }; @@ -2047,6 +2057,11 @@ export fn nullableptrtag(t: *node) i32 = { if (t == nil) { return 0; }; let ti: *tinfo = t.type_: *tinfo; if (ti == nil) { return 0; }; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + for (ti != nil && ti.kind == tykind.TY_NAMED) { ti = ti.under; }; + if (ti == nil) { return 0; }; if (ti.kind != tykind.TY_TAGGED) { return 0; }; let p: *tparam = ti.params; let i: i32 = 0; diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index 6792fa16..91dc2947 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -1027,10 +1027,16 @@ fn enumvalfold(body: *node, until: *node, e: *node, out: *u64) bool = { // fallback arm). fn tupleelemslot(pt: *tinfo) u64 = { if (pt == nil) { return 8u64; }; - let pk: tykind = pt.kind; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + let t: *tinfo = pt; + for (t != nil && t.kind == tykind.TY_NAMED) { t = t.under; }; + if (t == nil) { return 8u64; }; + let pk: tykind = t.kind; if (pk == tykind.TY_VOID) { return 0u64; }; - if (pk == tykind.TY_STR) { return pt.size; }; - if (pk == tykind.TY_SLICE) { return pt.size; }; + if (pk == tykind.TY_STR) { return t.size; }; + if (pk == tykind.TY_SLICE) { return t.size; }; if (pk == tykind.TY_PTR || pk == tykind.TY_FN || pk == tykind.TY_CHAN || pk == tykind.TY_I64 || pk == tykind.TY_U64 || pk == tykind.TY_INT || @@ -1042,7 +1048,7 @@ fn tupleelemslot(pt: *tinfo) u64 = { pk == tykind.TY_U16 || pk == tykind.TY_U32 || pk == tykind.TY_F32 || pk == tykind.TY_ENUM) { return 8u64; }; // Composite — struct/tuple/array/tagged carry their own slot total. - return pt.slotsize; + return t.slotsize; }; // #61 A.5 helper: per-field slot size mirroring cgenutil.ww @@ -1052,17 +1058,23 @@ fn tupleelemslot(pt: *tinfo) u64 = { // pad-to-8); arrays use their slot-padded element-stride * elen. fn fieldslotsize(ft: *tinfo) u64 = { if (ft == nil) { return 8u64; }; - let fk: tykind = ft.kind; - if (fk == tykind.TY_STRUCT) { return ft.slotsize; }; - if (fk == tykind.TY_ARRAY) { return ft.slotsize; }; - if (fk == tykind.TY_TAGGED) { return ft.size; }; - // str / slice read ft.size so the typ.ww SSoT seed is the single + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + let t: *tinfo = ft; + for (t != nil && t.kind == tykind.TY_NAMED) { t = t.under; }; + if (t == nil) { return 8u64; }; + let fk: tykind = t.kind; + if (fk == tykind.TY_STRUCT) { return t.slotsize; }; + if (fk == tykind.TY_ARRAY) { return t.slotsize; }; + if (fk == tykind.TY_TAGGED) { return t.size; }; + // str / slice read t.size so the typ.ww SSoT seed is the single // source for #1 (str→24) / #34 (slice graduation) — no hardcoded // literal here to drift. - if (fk == tykind.TY_SLICE) { return ft.size; }; + if (fk == tykind.TY_SLICE) { return t.size; }; if (fk == tykind.TY_PTR || fk == tykind.TY_FN || fk == tykind.TY_CHAN) { return 8u64; }; - if (fk == tykind.TY_STR) { return ft.size; }; + if (fk == tykind.TY_STR) { return t.size; }; // Primitives keep natural width inside structs (matches // cgenutil fieldsize: primsize, not pad-to-8). TY_TUPLE inside a // struct currently defaults to 8 in cgenutil — preserve that @@ -1074,7 +1086,7 @@ fn fieldslotsize(ft: *tinfo) u64 = { fk == tykind.TY_U32 || fk == tykind.TY_U64 || fk == tykind.TY_INT || fk == tykind.TY_UINT || fk == tykind.TY_UINTPTR || fk == tykind.TY_F32 || - fk == tykind.TY_F64 || fk == tykind.TY_ENUM) { return ft.size; }; + fk == tykind.TY_F64 || fk == tykind.TY_ENUM) { return t.size; }; return 8u64; }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 9bf4859b..1080bbf9 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -8124,10 +8124,16 @@ fn enumvalfold(body: *node, until: *node, e: *node, out: *u64) bool = { // fallback arm). fn tupleelemslot(pt: *tinfo) u64 = { if (pt == nil) { return 8u64; }; - let pk: tykind = pt.kind; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + let t: *tinfo = pt; + for (t != nil && t.kind == tykind.TY_NAMED) { t = t.under; }; + if (t == nil) { return 8u64; }; + let pk: tykind = t.kind; if (pk == tykind.TY_VOID) { return 0u64; }; - if (pk == tykind.TY_STR) { return pt.size; }; - if (pk == tykind.TY_SLICE) { return pt.size; }; + if (pk == tykind.TY_STR) { return t.size; }; + if (pk == tykind.TY_SLICE) { return t.size; }; if (pk == tykind.TY_PTR || pk == tykind.TY_FN || pk == tykind.TY_CHAN || pk == tykind.TY_I64 || pk == tykind.TY_U64 || pk == tykind.TY_INT || @@ -8139,7 +8145,7 @@ fn tupleelemslot(pt: *tinfo) u64 = { pk == tykind.TY_U16 || pk == tykind.TY_U32 || pk == tykind.TY_F32 || pk == tykind.TY_ENUM) { return 8u64; }; // Composite — struct/tuple/array/tagged carry their own slot total. - return pt.slotsize; + return t.slotsize; }; // #61 A.5 helper: per-field slot size mirroring cgenutil.ww @@ -8149,17 +8155,23 @@ fn tupleelemslot(pt: *tinfo) u64 = { // pad-to-8); arrays use their slot-padded element-stride * elen. fn fieldslotsize(ft: *tinfo) u64 = { if (ft == nil) { return 8u64; }; - let fk: tykind = ft.kind; - if (fk == tykind.TY_STRUCT) { return ft.slotsize; }; - if (fk == tykind.TY_ARRAY) { return ft.slotsize; }; - if (fk == tykind.TY_TAGGED) { return ft.size; }; - // str / slice read ft.size so the typ.ww SSoT seed is the single + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + let t: *tinfo = ft; + for (t != nil && t.kind == tykind.TY_NAMED) { t = t.under; }; + if (t == nil) { return 8u64; }; + let fk: tykind = t.kind; + if (fk == tykind.TY_STRUCT) { return t.slotsize; }; + if (fk == tykind.TY_ARRAY) { return t.slotsize; }; + if (fk == tykind.TY_TAGGED) { return t.size; }; + // str / slice read t.size so the typ.ww SSoT seed is the single // source for #1 (str→24) / #34 (slice graduation) — no hardcoded // literal here to drift. - if (fk == tykind.TY_SLICE) { return ft.size; }; + if (fk == tykind.TY_SLICE) { return t.size; }; if (fk == tykind.TY_PTR || fk == tykind.TY_FN || fk == tykind.TY_CHAN) { return 8u64; }; - if (fk == tykind.TY_STR) { return ft.size; }; + if (fk == tykind.TY_STR) { return t.size; }; // Primitives keep natural width inside structs (matches // cgenutil fieldsize: primsize, not pad-to-8). TY_TUPLE inside a // struct currently defaults to 8 in cgenutil — preserve that @@ -8171,7 +8183,7 @@ fn fieldslotsize(ft: *tinfo) u64 = { fk == tykind.TY_U32 || fk == tykind.TY_U64 || fk == tykind.TY_INT || fk == tykind.TY_UINT || fk == tykind.TY_UINTPTR || fk == tykind.TY_F32 || - fk == tykind.TY_F64 || fk == tykind.TY_ENUM) { return ft.size; }; + fk == tykind.TY_F64 || fk == tykind.TY_ENUM) { return t.size; }; return 8u64; }; @@ -12148,6 +12160,11 @@ fn slotsize(c: *cgen, typn: *node) i32 = { if (typn == nil) { return 8; }; let ti: *tinfo = typn.type_: *tinfo; if (ti == nil) { return 8; }; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + for (ti != nil && ti.kind == tykind.TY_NAMED) { ti = ti.under; }; + if (ti == nil) { return 8; }; let kk: tykind = ti.kind; if (kk == tykind.TY_VOID) { return 0; }; if (kk == tykind.TY_PTR || kk == tykind.TY_SLICE || @@ -12180,6 +12197,11 @@ fn fieldsize(c: *cgen, tnode: *node) i32 = { if (tnode == nil) { return 8; }; let ti: *tinfo = tnode.type_: *tinfo; if (ti == nil) { return 8; }; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + for (ti != nil && ti.kind == tykind.TY_NAMED) { ti = ti.under; }; + if (ti == nil) { return 8; }; let k: tykind = ti.kind; if (k == tykind.TY_STRUCT) { return ti.slotsize: i32; }; if (k == tykind.TY_ARRAY) { return ti.slotsize: i32; }; @@ -12524,6 +12546,11 @@ export fn nullableptrtag(t: *node) i32 = { if (t == nil) { return 0; }; let ti: *tinfo = t.type_: *tinfo; if (ti == nil) { return 0; }; + // #63 Phase-N step 1: peel TY_NAMED before this structural query; + // wrappers are built in step 2 (#64). No-op today (tinfofornode + // still collapses aliases → no TY_NAMED), so byte-id is unchanged. + for (ti != nil && ti.kind == tykind.TY_NAMED) { ti = ti.under; }; + if (ti == nil) { return 0; }; if (ti.kind != tykind.TY_TAGGED) { return 0; }; let p: *tparam = ti.params; let i: i32 = 0;