selfhost/cmd/wcc: drop indexvaluetnode from cgassign + delete 3 retired AST-walkers (#69, #61d)
cgassign's two element-store sites (N_DOT and N_INDEX index targets) fed the index node into indexvaluetnode to recover the element type. The tagged-store machinery reads tinfo directly post-#68, so both sites now read the checker- stamped element tinfo via lhs.type_: esz from .size (mirror #60), tagged gate via the shared istaggedtype/slotsize/cgwidentaggedstore path (all NAMED- peeling). cstage parity: cgen.c:3507-3523 (idx_eff(base->type)->sub->size). The new esz reads the element's natural .size, where the old elemsizeofc routed struct elements through slotsize -- so a padded-struct chained-index store (`[][]Point`) now matches cstage's ->size instead of diverging; that shape is untested (#7 indexbaseesz territory), so this is faithfulness, not a corpus change. With cgassign migrated, indexvaluetnode has zero external callers; dotfieldtnode's sole caller was indexvaluetnode; rhstargetname is self-recursive only -- all three retired (-132 LOC). This closes the A.6.3 AST-walker arc: the *node type-resolvers that existed because tinfo was lossy on nominal identity are gone, now that Phase-N (#63-#68) built the TY_NAMED layer and every consumer reads the stamped tinfo. make test 134/134, byte-id 950+990-997 hold.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
// - index helpers: indexbaseesz, dotinnerstructptr, elemsizeof
|
||||
// - slot sizing: structlookup, primsize, slotsize, fieldsize,
|
||||
// registerstruct, collectstructs
|
||||
// - rhs helpers: rhstargetname, taggedvariantindex
|
||||
// - rhs helpers: taggedvariantindex
|
||||
//
|
||||
// Bundler pulls this in transitively via cgen.ww; consumers don't
|
||||
// need to `use cgenutil;` directly.
|
||||
@@ -1060,36 +1060,6 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
return slotsize(c, elem);
|
||||
};
|
||||
|
||||
// indexvaluetnode — type node of the value produced by an N_INDEX
|
||||
// expression. Walks base's type and returns its element. Recurses
|
||||
// through chained N_INDEX so `names[i][k]` (names: **u8) resolves
|
||||
// the outer base type to *u8 (the post-inner-index value type), so
|
||||
// cgindex can compute the outer element size honestly. Mirrors
|
||||
// cstage's `n->lhs->type` via typed-AST (cmd/w6c/cgen.c idx_eff).
|
||||
// N_DOT base graduated (tasks #28/#30) so `obj.mat[i][k]` reads
|
||||
// and `obj.arr[i] = v` tagged-element writes route through the
|
||||
// same helper as the N_IDENT/N_INDEX bases #24/#27 graduated.
|
||||
fn indexvaluetnode(c: *cgen, n: *node) *node = {
|
||||
if (n == nil) { return nil; };
|
||||
if (n.kind != nkind.N_INDEX) { return nil; };
|
||||
let base: *node = n.lhs;
|
||||
if (base == nil) { return nil; };
|
||||
let bt: *node = nil;
|
||||
if (base.kind == nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, base.str);
|
||||
if (lc != nil) { bt = lc.tnode; }
|
||||
else { bt = letvartnode(c, base.str); };
|
||||
};
|
||||
if (base.kind == nkind.N_INDEX) { bt = indexvaluetnode(c, base); };
|
||||
if (base.kind == nkind.N_DOT) { bt = dotfieldtnode(c, base); };
|
||||
if (bt == nil) { return nil; };
|
||||
let k: nkind = bt.kind;
|
||||
if (k == nkind.N_TPTR) { return bt.lhs; };
|
||||
if (k == nkind.N_TSLICE) { return bt.lhs; };
|
||||
if (k == nkind.N_TARRAY) { return bt.lhs; };
|
||||
return nil;
|
||||
};
|
||||
|
||||
// nodeisunsigned — best-effort cgen-time inference from the AST. We
|
||||
// walk surface nodes (N_DOT now reads n.type_ — #55 A.6.3g):
|
||||
// nkind.N_INTLIT — never marked unsigned (no tsuffix plumbing yet)
|
||||
@@ -2115,72 +2085,6 @@ fn voidvariantindex(tagged: *node) i32 = {
|
||||
return -1;
|
||||
};
|
||||
|
||||
// rhstargetname — for a returned value, what's its declared (or
|
||||
// surface-inferred) type name? `expr: T` casts dictate T directly;
|
||||
// bare strlit/intlit fall back to a primitive name.
|
||||
fn rhstargetname(c: *cgen, rhs: *node) str = {
|
||||
let nm: str;
|
||||
nm.ptr = nil; nm.len = 0;
|
||||
if (rhs == nil) { return nm; };
|
||||
// Unary `-` / `+` / `~` inherit the inner expression's type:
|
||||
// cstage's checker stamps N_UN's type from cunop's inner walk,
|
||||
// so `-42i64` is ty_i64 there. Wwstage has no checker stage —
|
||||
// peel the operator here so a typed-int literal under a sign
|
||||
// reaches its tsuffix branch below instead of falling into
|
||||
// taggedvariantindex's "first non-str variant" fallback. Mirror
|
||||
// of cmd/wcc/check.c cunop TK_MINUS/PLUS/TILDE returning t.
|
||||
if (rhs.kind == nkind.N_UN) {
|
||||
let op: tkind = rhs.op;
|
||||
if (op == tkind.TK_MINUS || op == tkind.TK_PLUS
|
||||
|| op == tkind.TK_TILDE) {
|
||||
if (rhs.lhs != nil) {
|
||||
return rhstargetname(c, rhs.lhs);
|
||||
};
|
||||
};
|
||||
};
|
||||
if (rhs.kind == nkind.N_CAST) {
|
||||
let t: *node = rhs.rhs;
|
||||
if (t != nil) {
|
||||
if (t.kind == nkind.N_TNAME) { return t.str; };
|
||||
};
|
||||
return nm;
|
||||
};
|
||||
if (rhs.kind == nkind.N_STRLIT) { return "str"; };
|
||||
if (rhs.kind == nkind.N_TRUE) { return "bool"; };
|
||||
if (rhs.kind == nkind.N_FALSE) { return "bool"; };
|
||||
if (rhs.kind == nkind.N_RUNELIT) { return "rune"; };
|
||||
if (rhs.kind == nkind.N_INTLIT) {
|
||||
// Typed int literal (`42i64`, `3u8`): suffix names the
|
||||
// concrete variant so flatvariantidx finds it. Untyped
|
||||
// literals (tsuffix=="") fall through to the isstr scan.
|
||||
let s: str = rhs.tsuffix;
|
||||
if (s.len > 0) { return s; };
|
||||
};
|
||||
// `T{}` carries its type name on the lhs N_IDENT — the parser
|
||||
// builds `N_STRUCTLIT{ lhs = N_IDENT("T"), list = fields }`.
|
||||
// Needed so `return eof{};` (variant of a tagged union) resolves
|
||||
// to the `eof` variant index rather than falling through to the
|
||||
// "first non-str variant" fallback in taggedvariantindex.
|
||||
if (rhs.kind == nkind.N_STRUCTLIT) {
|
||||
let tref: *node = rhs.lhs;
|
||||
if (tref != nil) {
|
||||
if (tref.kind == nkind.N_IDENT) { return tref.str; };
|
||||
if (tref.kind == nkind.N_TNAME) { return tref.str; };
|
||||
};
|
||||
return nm;
|
||||
};
|
||||
if (rhs.kind == nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, rhs.str);
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
if (tn != nil) {
|
||||
if (tn.kind == nkind.N_TNAME) { return tn.str; };
|
||||
};
|
||||
};
|
||||
};
|
||||
return nm;
|
||||
};
|
||||
|
||||
// taggedvariantindex — given the tagged-union type expr and the
|
||||
// returned value's surface type, find the matching variant's 0-based
|
||||
// index. Compare by exact type name first; if no match, fall back to
|
||||
@@ -2432,44 +2336,6 @@ fn rhstaggedident(c: *cgen, src: *node) *node = {
|
||||
return resolvetagged(c, tn);
|
||||
};
|
||||
|
||||
// dotfieldtnode — for an N_DOT src whose base is a local ident or
|
||||
// *struct, return the declared type node of the named field, or nil
|
||||
// if the shape doesn't resolve (e.g. enum-member access, pseudo-
|
||||
// field `.len`, top-level global). Used by rhstaggedabicall and
|
||||
// related predicates to walk into the field's tagged type.
|
||||
fn dotfieldtnode(c: *cgen, n: *node) *node = {
|
||||
if (n == nil) { return nil; };
|
||||
if (n.kind != nkind.N_DOT) { return nil; };
|
||||
let base: *node = n.lhs;
|
||||
let fld: str = n.str;
|
||||
if (base == nil) { return nil; };
|
||||
if (base.kind != nkind.N_IDENT) { return nil; };
|
||||
let lc: *local = localfindnode(c, base.str);
|
||||
let btn: *node = nil;
|
||||
if (lc != nil) { btn = lc.tnode; }
|
||||
else { btn = letvartnode(c, base.str); };
|
||||
if (btn == nil) { return nil; };
|
||||
let bk: nkind = btn.kind;
|
||||
let sname: str;
|
||||
sname.ptr = nil; sname.len = 0;
|
||||
if (bk == nkind.N_TPTR) {
|
||||
let inner: *node = btn.lhs;
|
||||
if (inner != nil) {
|
||||
if (inner.kind == nkind.N_TNAME) { sname = inner.str; };
|
||||
};
|
||||
};
|
||||
if (bk == nkind.N_TNAME) { sname = btn.str; };
|
||||
if (sname.len == 0) { return nil; };
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
if (si == nil) { return nil; };
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
if (streq(fi.fname, fld)) { return fi.tnode; };
|
||||
fi = fi.finext;
|
||||
};
|
||||
return nil;
|
||||
};
|
||||
|
||||
// rhstaggedabicall — does `src` produce a tagged value via the AX/DX/CX
|
||||
// return ABI? True for N_CALL of a tagged-returning fn, N_INDEX of a
|
||||
// tagged-element base, and N_DOT of a tagged-typed struct field (after
|
||||
|
||||
Reference in New Issue
Block a user