selfhost+cstage+test: graduate alias-chain unwrap to transitive (#22)
Single-peel TY_NAMED.under bottoms out at the inner alias when chain length is 2+, surfaces in two stages with different mechanisms: cstage's gates inline `if (t->kind == TY_NAMED) t = t->under` at every callsite (cgreturn, cglet sizing, cgexpr N_DOT, cgassign N_DOT, cg_sret_retsize) — graduated to a while-loop via new type_chase_named helper across 11 sites. wwstage routes all field-walks through structlookup, which registers only direct struct definitions (not aliases) — missing the alias-recurse fallback. New structlookupchain helper mirrors slotsize's N_TARRAY arm precedent; sretretsize + 4 cgenexpr.ww sites route through it. Splitting would either land cstage without unblocking wwstage's strings.tokenize wrapper shape (rule 10 byte-id regression) or land wwstage without cstage gate parity (breaking 995 self-rebuild). 756 sentinel exercises 4 rows × cstage RC + wwstage RC + byte-id = 12 fixtures; pre-fix rows 2 + 4 (slice-fields single alias, i32 double alias) fail on both RC and byte-id. The ~67 cstage / ~26 wwstage candidate sibling sites are #17-style structural-close follow-up; this commit fixes the immediate strings.tokenize-wrapper blockers.
This commit is contained in:
@@ -1280,7 +1280,11 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
if (sname.len > 0) {
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
// structlookupchain walks the alias chain on
|
||||
// a miss so `*tokenizer` where tokenizer is
|
||||
// a transitively-aliased struct still
|
||||
// resolves to the underlying fieldinfo (#22).
|
||||
let si: *structinfo = structlookupchain(c, inner);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
@@ -1363,8 +1367,11 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
};
|
||||
// Direct struct local: field load at off+foff.
|
||||
if (lkind == nkind.N_TNAME) {
|
||||
let sname: str = tn.str;
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
// structlookupchain walks the alias chain on
|
||||
// miss so a transitively-aliased struct (`type
|
||||
// b = a; a = struct`) still resolves to the
|
||||
// underlying fieldinfo (#22).
|
||||
let si: *structinfo = structlookupchain(c, tn);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
@@ -4029,7 +4036,10 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
if (inner.kind == nkind.N_TNAME) { sname = inner.str; };
|
||||
};
|
||||
if (sname.len > 0) {
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
// structlookupchain (#22) handles the
|
||||
// alias-chain miss; same shape as the
|
||||
// cgdot pointer-to-struct read site.
|
||||
let si: *structinfo = structlookupchain(c, inner);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
@@ -4267,8 +4277,9 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
};
|
||||
// Direct struct local: store at off+foff.
|
||||
if (lkind == nkind.N_TNAME) {
|
||||
let sname: str = tn.str;
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
// structlookupchain (#22) — same shape
|
||||
// as the cgdot direct-local read site.
|
||||
let si: *structinfo = structlookupchain(c, tn);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
|
||||
Reference in New Issue
Block a user