diff --git a/lib/ww/typ.ww b/lib/ww/typ.ww index f426503d..a0aa6ee5 100644 --- a/lib/ww/typ.ww +++ b/lib/ww/typ.ww @@ -74,6 +74,19 @@ type tparam = struct { tnext: *tparam, }; +// #57 A.6.3i-phase-1: tuple positional element. Distinct from tfield +// (named, struct member) per harec's split at ref/harec/include/types.h +// :109-115 (struct_field) vs :122-126 (type_tuple) — tuple positionals +// carry no name (positional only) and a separate next-link. Rule-12 +// sea-of-stars mirrors Hare's structural choice; the empty-name idiom +// from #50's TTAGGED-on-tparam would conflate two semantic axes +// (variants can be named; positionals never can). +type ttupleelem = struct { + type_: *tinfo, + offset: u64, + tnext: *ttupleelem, +}; + type tinfo = struct { kind: tykind, size: u64, @@ -82,6 +95,11 @@ type tinfo = struct { alen: u64, fields: *tfield, params: *tparam, + tupleelems: *ttupleelem, // #57 A.6.3i-phase-1: TY_TUPLE + // positional chain (harec types.h:122-126 + // `struct type_tuple`). Distinct slot from + // .fields so struct-member vs tuple- + // positional stay axis-separated. ret: *tinfo, variadic: i32, nullable: i32, // #61 A.3: TY_TAGGED `(*T | void)` fold collapses to @@ -148,7 +166,7 @@ type tctx = struct { // ---- constructors ----------------------------------------------------- export fn newtype(k: tykind) *tinfo = { - let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64})!; + let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, tupleelems=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64})!; return t; }; diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index 15973d00..dae51232 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -6404,6 +6404,19 @@ type tparam = struct { tnext: *tparam, }; +// #57 A.6.3i-phase-1: tuple positional element. Distinct from tfield +// (named, struct member) per harec's split at ref/harec/include/types.h +// :109-115 (struct_field) vs :122-126 (type_tuple) — tuple positionals +// carry no name (positional only) and a separate next-link. Rule-12 +// sea-of-stars mirrors Hare's structural choice; the empty-name idiom +// from #50's TTAGGED-on-tparam would conflate two semantic axes +// (variants can be named; positionals never can). +type ttupleelem = struct { + type_: *tinfo, + offset: u64, + tnext: *ttupleelem, +}; + type tinfo = struct { kind: tykind, size: u64, @@ -6412,6 +6425,11 @@ type tinfo = struct { alen: u64, fields: *tfield, params: *tparam, + tupleelems: *ttupleelem, // #57 A.6.3i-phase-1: TY_TUPLE + // positional chain (harec types.h:122-126 + // `struct type_tuple`). Distinct slot from + // .fields so struct-member vs tuple- + // positional stay axis-separated. ret: *tinfo, variadic: i32, nullable: i32, // #61 A.3: TY_TAGGED `(*T | void)` fold collapses to @@ -6478,7 +6496,7 @@ type tctx = struct { // ---- constructors ----------------------------------------------------- export fn newtype(k: tykind) *tinfo = { - let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64})!; + let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, tupleelems=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64})!; return t; }; @@ -8289,12 +8307,33 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // composites contribute their own ti.slotsize. r = newtype(tykind.TY_TUPLE); tinfocachebind(c.tc, n, r); + // #57 A.6.3i-phase-1: populate r.tupleelems as a ttupleelem + // linked list (head=positional 0) in lock-step with the + // size/align accumulator. Harec analog ref/harec/src/type_ + // store.c:532-589 tuple_init_from_atype — {type, offset, next} + // per member onto type->tuple.next chain. Diverges from cstage + // cmd/wcc/check.c:329-345 which stores tuple positionals on + // t->params (Tparam, no offset, consumer recomputes by walking + // at cgen.c:5723-5750); the offset-stored shape lets Phase + // 2/J/K consumers (dotchainresolve, indexbaseesz) read offsets + // directly per the A.6 stamp-once-read-many arc. Direct analog + // 26724fe (#50 phase 1, A.6.3f-a) for the head/tail append + // pattern. Offset matches cstage's raw-sum layout (no per- + // element padding) — rule 10 aligns wwstage tuple layout down + // to cstage, distinct from harec's add_padding(&offset, + // memb.align) at type_store.c:561. + let teh: *ttupleelem = nil; + let tet: *ttupleelem = nil; let total: u64 = 0u64; let slottotal: u64 = 0u64; let maxal: u64 = 1u64; let p: *node = n.list; for (p != nil) { let pt: *tinfo = tinfofornode(c, p.lhs); + let elemoff: u64 = total; + let te: *ttupleelem = alloc(ttupleelem{type_=pt, offset=elemoff, tnext=nil})!; + if (teh == nil) { teh = te; } else { tet.tnext = te; }; + tet = te; if (pt != nil) { if (pt.align > maxal) { maxal = pt.align; }; total += pt.size; @@ -8302,6 +8341,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { }; p = p.next; }; + r.tupleelems = teh; r.size = total; r.align = maxal; r.slotsize = slottotal; @@ -8327,6 +8367,18 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // graduate TY_STRUCT off the AST walker. r = newtype(tykind.TY_STRUCT); tinfocachebind(c.tc, n, r); + // #57 A.6.3i-phase-1: populate r.fields as a tfield linked + // list (head=first declared field) in lock-step with the + // natural-layout offset accumulator. Mirrors cstage cmd/wcc/ + // check.c:468-527 (Tfield {name, type, offset, next} per + // member onto t->fields). Direct analog 26724fe (#50 phase 1, + // A.6.3f-a) for the head/tail append pattern. Harec cite: + // ref/harec/include/types.h:109-115 struct_field and + // ref/harec/src/type_store.c:314-347 struct_init_from_atype. + // Anonymous-embed promotion not populated here (#13 per + // the cstage cite at check.ww:1263). + let fh: *tfield = nil; + let ft_: *tfield = nil; let off: u64 = 0u64; let maxalign: u64 = 1u64; let soff: u64 = 0u64; @@ -8339,6 +8391,10 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { if (ft.align > 0u64) { off = (off + ft.align - 1u64) & ~(ft.align - 1u64); }; + let fldoff: u64 = off; + let tf: *tfield = alloc(tfield{name=f.str, type_=ft, offset=fldoff, tnext=nil})!; + if (fh == nil) { fh = tf; } else { ft_.tnext = tf; }; + ft_ = tf; off += ft.size; // Slot-padded layout (mirror of cgenutil // fieldsize + registerstruct align rules). @@ -8355,6 +8411,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { }; f = f.next; }; + r.fields = fh; if (maxalign > 0u64) { r.size = (off + maxalign - 1u64) & ~(maxalign - 1u64); }; diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index 711945ff..b6cae1b6 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -1219,12 +1219,33 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // composites contribute their own ti.slotsize. r = newtype(tykind.TY_TUPLE); tinfocachebind(c.tc, n, r); + // #57 A.6.3i-phase-1: populate r.tupleelems as a ttupleelem + // linked list (head=positional 0) in lock-step with the + // size/align accumulator. Harec analog ref/harec/src/type_ + // store.c:532-589 tuple_init_from_atype — {type, offset, next} + // per member onto type->tuple.next chain. Diverges from cstage + // cmd/wcc/check.c:329-345 which stores tuple positionals on + // t->params (Tparam, no offset, consumer recomputes by walking + // at cgen.c:5723-5750); the offset-stored shape lets Phase + // 2/J/K consumers (dotchainresolve, indexbaseesz) read offsets + // directly per the A.6 stamp-once-read-many arc. Direct analog + // 26724fe (#50 phase 1, A.6.3f-a) for the head/tail append + // pattern. Offset matches cstage's raw-sum layout (no per- + // element padding) — rule 10 aligns wwstage tuple layout down + // to cstage, distinct from harec's add_padding(&offset, + // memb.align) at type_store.c:561. + let teh: *ttupleelem = nil; + let tet: *ttupleelem = nil; let total: u64 = 0u64; let slottotal: u64 = 0u64; let maxal: u64 = 1u64; let p: *node = n.list; for (p != nil) { let pt: *tinfo = tinfofornode(c, p.lhs); + let elemoff: u64 = total; + let te: *ttupleelem = alloc(ttupleelem{type_=pt, offset=elemoff, tnext=nil})!; + if (teh == nil) { teh = te; } else { tet.tnext = te; }; + tet = te; if (pt != nil) { if (pt.align > maxal) { maxal = pt.align; }; total += pt.size; @@ -1232,6 +1253,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { }; p = p.next; }; + r.tupleelems = teh; r.size = total; r.align = maxal; r.slotsize = slottotal; @@ -1257,6 +1279,18 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // graduate TY_STRUCT off the AST walker. r = newtype(tykind.TY_STRUCT); tinfocachebind(c.tc, n, r); + // #57 A.6.3i-phase-1: populate r.fields as a tfield linked + // list (head=first declared field) in lock-step with the + // natural-layout offset accumulator. Mirrors cstage cmd/wcc/ + // check.c:468-527 (Tfield {name, type, offset, next} per + // member onto t->fields). Direct analog 26724fe (#50 phase 1, + // A.6.3f-a) for the head/tail append pattern. Harec cite: + // ref/harec/include/types.h:109-115 struct_field and + // ref/harec/src/type_store.c:314-347 struct_init_from_atype. + // Anonymous-embed promotion not populated here (#13 per + // the cstage cite at check.ww:1263). + let fh: *tfield = nil; + let ft_: *tfield = nil; let off: u64 = 0u64; let maxalign: u64 = 1u64; let soff: u64 = 0u64; @@ -1269,6 +1303,10 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { if (ft.align > 0u64) { off = (off + ft.align - 1u64) & ~(ft.align - 1u64); }; + let fldoff: u64 = off; + let tf: *tfield = alloc(tfield{name=f.str, type_=ft, offset=fldoff, tnext=nil})!; + if (fh == nil) { fh = tf; } else { ft_.tnext = tf; }; + ft_ = tf; off += ft.size; // Slot-padded layout (mirror of cgenutil // fieldsize + registerstruct align rules). @@ -1285,6 +1323,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { }; f = f.next; }; + r.fields = fh; if (maxalign > 0u64) { r.size = (off + maxalign - 1u64) & ~(maxalign - 1u64); }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 89b2b74e..d76f17e9 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -6404,6 +6404,19 @@ type tparam = struct { tnext: *tparam, }; +// #57 A.6.3i-phase-1: tuple positional element. Distinct from tfield +// (named, struct member) per harec's split at ref/harec/include/types.h +// :109-115 (struct_field) vs :122-126 (type_tuple) — tuple positionals +// carry no name (positional only) and a separate next-link. Rule-12 +// sea-of-stars mirrors Hare's structural choice; the empty-name idiom +// from #50's TTAGGED-on-tparam would conflate two semantic axes +// (variants can be named; positionals never can). +type ttupleelem = struct { + type_: *tinfo, + offset: u64, + tnext: *ttupleelem, +}; + type tinfo = struct { kind: tykind, size: u64, @@ -6412,6 +6425,11 @@ type tinfo = struct { alen: u64, fields: *tfield, params: *tparam, + tupleelems: *ttupleelem, // #57 A.6.3i-phase-1: TY_TUPLE + // positional chain (harec types.h:122-126 + // `struct type_tuple`). Distinct slot from + // .fields so struct-member vs tuple- + // positional stay axis-separated. ret: *tinfo, variadic: i32, nullable: i32, // #61 A.3: TY_TAGGED `(*T | void)` fold collapses to @@ -6478,7 +6496,7 @@ type tctx = struct { // ---- constructors ----------------------------------------------------- export fn newtype(k: tykind) *tinfo = { - let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64})!; + let t: *tinfo = alloc(tinfo{kind=k, size=0u64, align=0u64, sub=nil, alen=0u64, fields=nil, params=nil, tupleelems=nil, ret=nil, variadic=0, nullable=0, name="", under=nil, slotsize=0u64})!; return t; }; @@ -8289,12 +8307,33 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // composites contribute their own ti.slotsize. r = newtype(tykind.TY_TUPLE); tinfocachebind(c.tc, n, r); + // #57 A.6.3i-phase-1: populate r.tupleelems as a ttupleelem + // linked list (head=positional 0) in lock-step with the + // size/align accumulator. Harec analog ref/harec/src/type_ + // store.c:532-589 tuple_init_from_atype — {type, offset, next} + // per member onto type->tuple.next chain. Diverges from cstage + // cmd/wcc/check.c:329-345 which stores tuple positionals on + // t->params (Tparam, no offset, consumer recomputes by walking + // at cgen.c:5723-5750); the offset-stored shape lets Phase + // 2/J/K consumers (dotchainresolve, indexbaseesz) read offsets + // directly per the A.6 stamp-once-read-many arc. Direct analog + // 26724fe (#50 phase 1, A.6.3f-a) for the head/tail append + // pattern. Offset matches cstage's raw-sum layout (no per- + // element padding) — rule 10 aligns wwstage tuple layout down + // to cstage, distinct from harec's add_padding(&offset, + // memb.align) at type_store.c:561. + let teh: *ttupleelem = nil; + let tet: *ttupleelem = nil; let total: u64 = 0u64; let slottotal: u64 = 0u64; let maxal: u64 = 1u64; let p: *node = n.list; for (p != nil) { let pt: *tinfo = tinfofornode(c, p.lhs); + let elemoff: u64 = total; + let te: *ttupleelem = alloc(ttupleelem{type_=pt, offset=elemoff, tnext=nil})!; + if (teh == nil) { teh = te; } else { tet.tnext = te; }; + tet = te; if (pt != nil) { if (pt.align > maxal) { maxal = pt.align; }; total += pt.size; @@ -8302,6 +8341,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { }; p = p.next; }; + r.tupleelems = teh; r.size = total; r.align = maxal; r.slotsize = slottotal; @@ -8327,6 +8367,18 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { // graduate TY_STRUCT off the AST walker. r = newtype(tykind.TY_STRUCT); tinfocachebind(c.tc, n, r); + // #57 A.6.3i-phase-1: populate r.fields as a tfield linked + // list (head=first declared field) in lock-step with the + // natural-layout offset accumulator. Mirrors cstage cmd/wcc/ + // check.c:468-527 (Tfield {name, type, offset, next} per + // member onto t->fields). Direct analog 26724fe (#50 phase 1, + // A.6.3f-a) for the head/tail append pattern. Harec cite: + // ref/harec/include/types.h:109-115 struct_field and + // ref/harec/src/type_store.c:314-347 struct_init_from_atype. + // Anonymous-embed promotion not populated here (#13 per + // the cstage cite at check.ww:1263). + let fh: *tfield = nil; + let ft_: *tfield = nil; let off: u64 = 0u64; let maxalign: u64 = 1u64; let soff: u64 = 0u64; @@ -8339,6 +8391,10 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { if (ft.align > 0u64) { off = (off + ft.align - 1u64) & ~(ft.align - 1u64); }; + let fldoff: u64 = off; + let tf: *tfield = alloc(tfield{name=f.str, type_=ft, offset=fldoff, tnext=nil})!; + if (fh == nil) { fh = tf; } else { ft_.tnext = tf; }; + ft_ = tf; off += ft.size; // Slot-padded layout (mirror of cgenutil // fieldsize + registerstruct align rules). @@ -8355,6 +8411,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = { }; f = f.next; }; + r.fields = fh; if (maxalign > 0u64) { r.size = (off + maxalign - 1u64) & ~(maxalign - 1u64); };