selfhost/cmd/wcc/cgenutil: collapse N_DOT arms onto n.type_ (#55, A.6.3g)
nodeisunsigned + exprfloatkind each manually walked base->struct->field on N_DOT, gated on `base.kind == nkind.N_IDENT` -- duplicating cstage's behaviour at the AST level while silently dropping the nested-N_DOT case (`a.b.c` returned the conservative default). After A.6.2 the checker stamps n.type_ on every N_DOT expression (check.ww:1973 struct-field arm of exprtype), and A.6.3a/b landed the tinfo helpers (typeisunsigned, isfloattype/isf32type) that the inner reads already use. Both arms collapse to one tinfo read. Polarity DOWN per rule 10: cstage was already aligned. cmd/w6c/cgen.c: 2330-2331 reads type_isunsigned(n->lhs->type) directly; cgen.c:152-156 node_isfloat = cg_isfloat(n->type); cgen.c:195-199 node_isf32 = type_isf32(n->type). No exprfloatkind-equivalent walker exists in cstage -- it is pre-A.6.2 wwstage scaffolding. Wwstage now reads the same shape as cstage on N_DOT. Nested N_DOT (a.b.c) now resolves to the field type instead of returning the conservative default. Byte-identity (994/995) confirms the codegen matches cstage on the test set -- cstage was already getting nested-dot right via checker-stamped n->type, wwstage was the laggard. make test 133/133 ok. Net cgenutil.ww -41 / +3.
This commit is contained in:
@@ -11587,10 +11587,10 @@ fn indexvaluetnode(c: *cgen, n: *node) *node = {
|
||||
};
|
||||
|
||||
// nodeisunsigned — best-effort cgen-time inference from the AST. We
|
||||
// don't have a typed AST yet, so we walk surface nodes:
|
||||
// walk surface nodes (N_DOT now reads n.type_ — #55 A.6.3g):
|
||||
// nkind.N_INTLIT — never marked unsigned (no tsuffix plumbing yet)
|
||||
// nkind.N_IDENT — look up the local's declared type
|
||||
// nkind.N_DOT — look up the field's declared type via struct reg
|
||||
// nkind.N_DOT — read the checker-stamped n.type_ (#55 A.6.3g)
|
||||
// nkind.N_BIN / nkind.N_UN — recurse: unsigned if either operand is unsigned
|
||||
// nkind.N_CAST — use the cast target type
|
||||
//
|
||||
@@ -11609,43 +11609,7 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = {
|
||||
return false;
|
||||
};
|
||||
if (k == nkind.N_DOT) {
|
||||
let base: *node = n.lhs;
|
||||
let fld: str = n.str;
|
||||
if (base != nil) {
|
||||
if (base.kind == nkind.N_IDENT) {
|
||||
let bn: str = base.str;
|
||||
let lc: *local = localfindnode(c, bn);
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
let lkind: nkind = nkind.N_NONE;
|
||||
if (tn != nil) { lkind = tn.kind; };
|
||||
let sname: str;
|
||||
sname.ptr = nil; sname.len = 0;
|
||||
if (lkind == nkind.N_TPTR) {
|
||||
let inner: *node = tn.lhs;
|
||||
if (inner != nil) {
|
||||
if (inner.kind == nkind.N_TNAME) { sname = inner.str; };
|
||||
};
|
||||
};
|
||||
if (lkind == nkind.N_TNAME) { sname = tn.str; };
|
||||
if (sname.len > 0) {
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
if (fi.tnode == nil) { return false; };
|
||||
return typeisunsigned(fi.tnode.type_: *tinfo);
|
||||
};
|
||||
fi = fi.finext;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
return false;
|
||||
return typeisunsigned(n.type_: *tinfo);
|
||||
};
|
||||
if (k == nkind.N_CAST) {
|
||||
if (n.rhs == nil) { return false; };
|
||||
@@ -12537,42 +12501,12 @@ export fn exprfloatkind(c: *cgen, n: *node) i32 = {
|
||||
// `p.field` where the struct field is f64/f32. Without this,
|
||||
// `v.fval: i64` lowers to CVTSI on an integer-load value
|
||||
// instead of CVTTSD2SI on the X0 the cgdot path actually
|
||||
// emits for an f64 field.
|
||||
let base: *node = n.lhs;
|
||||
let fld: str = n.str;
|
||||
if (base != nil) {
|
||||
let sname: str;
|
||||
sname.ptr = nil; sname.len = 0;
|
||||
if (base.kind == nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, base.str);
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
if (tn != nil) {
|
||||
if (tn.kind == nkind.N_TNAME) { sname = tn.str; };
|
||||
if (tn.kind == nkind.N_TPTR) {
|
||||
let pe: *node = tn.lhs;
|
||||
if (pe != nil) {
|
||||
if (pe.kind == nkind.N_TNAME) { sname = pe.str; };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
if (sname.len > 0) {
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
if (streq(fi.fname, fld)) {
|
||||
if (isf32type(c, fi.tnode)) { return 1; };
|
||||
if (isfloattype(c, fi.tnode)) { return 2; };
|
||||
return 0;
|
||||
};
|
||||
fi = fi.finext;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// emits for an f64 field. Read the checker-stamped tinfo on
|
||||
// the N_DOT itself (check.ww:1973 stamps the field type);
|
||||
// cstage cgen.c:2128 reads node_isfloat(n) the same way.
|
||||
// Collapsed per A.6.3g (#55).
|
||||
if (isf32type(c, n)) { return 1; };
|
||||
if (isfloattype(c, n)) { return 2; };
|
||||
return 0;
|
||||
};
|
||||
return 0;
|
||||
|
||||
@@ -1203,10 +1203,10 @@ fn indexvaluetnode(c: *cgen, n: *node) *node = {
|
||||
};
|
||||
|
||||
// nodeisunsigned — best-effort cgen-time inference from the AST. We
|
||||
// don't have a typed AST yet, so we walk surface nodes:
|
||||
// walk surface nodes (N_DOT now reads n.type_ — #55 A.6.3g):
|
||||
// nkind.N_INTLIT — never marked unsigned (no tsuffix plumbing yet)
|
||||
// nkind.N_IDENT — look up the local's declared type
|
||||
// nkind.N_DOT — look up the field's declared type via struct reg
|
||||
// nkind.N_DOT — read the checker-stamped n.type_ (#55 A.6.3g)
|
||||
// nkind.N_BIN / nkind.N_UN — recurse: unsigned if either operand is unsigned
|
||||
// nkind.N_CAST — use the cast target type
|
||||
//
|
||||
@@ -1225,43 +1225,7 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = {
|
||||
return false;
|
||||
};
|
||||
if (k == nkind.N_DOT) {
|
||||
let base: *node = n.lhs;
|
||||
let fld: str = n.str;
|
||||
if (base != nil) {
|
||||
if (base.kind == nkind.N_IDENT) {
|
||||
let bn: str = base.str;
|
||||
let lc: *local = localfindnode(c, bn);
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
let lkind: nkind = nkind.N_NONE;
|
||||
if (tn != nil) { lkind = tn.kind; };
|
||||
let sname: str;
|
||||
sname.ptr = nil; sname.len = 0;
|
||||
if (lkind == nkind.N_TPTR) {
|
||||
let inner: *node = tn.lhs;
|
||||
if (inner != nil) {
|
||||
if (inner.kind == nkind.N_TNAME) { sname = inner.str; };
|
||||
};
|
||||
};
|
||||
if (lkind == nkind.N_TNAME) { sname = tn.str; };
|
||||
if (sname.len > 0) {
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
if (fi.tnode == nil) { return false; };
|
||||
return typeisunsigned(fi.tnode.type_: *tinfo);
|
||||
};
|
||||
fi = fi.finext;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
return false;
|
||||
return typeisunsigned(n.type_: *tinfo);
|
||||
};
|
||||
if (k == nkind.N_CAST) {
|
||||
if (n.rhs == nil) { return false; };
|
||||
@@ -2153,42 +2117,12 @@ export fn exprfloatkind(c: *cgen, n: *node) i32 = {
|
||||
// `p.field` where the struct field is f64/f32. Without this,
|
||||
// `v.fval: i64` lowers to CVTSI on an integer-load value
|
||||
// instead of CVTTSD2SI on the X0 the cgdot path actually
|
||||
// emits for an f64 field.
|
||||
let base: *node = n.lhs;
|
||||
let fld: str = n.str;
|
||||
if (base != nil) {
|
||||
let sname: str;
|
||||
sname.ptr = nil; sname.len = 0;
|
||||
if (base.kind == nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, base.str);
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
if (tn != nil) {
|
||||
if (tn.kind == nkind.N_TNAME) { sname = tn.str; };
|
||||
if (tn.kind == nkind.N_TPTR) {
|
||||
let pe: *node = tn.lhs;
|
||||
if (pe != nil) {
|
||||
if (pe.kind == nkind.N_TNAME) { sname = pe.str; };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
if (sname.len > 0) {
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
if (streq(fi.fname, fld)) {
|
||||
if (isf32type(c, fi.tnode)) { return 1; };
|
||||
if (isfloattype(c, fi.tnode)) { return 2; };
|
||||
return 0;
|
||||
};
|
||||
fi = fi.finext;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// emits for an f64 field. Read the checker-stamped tinfo on
|
||||
// the N_DOT itself (check.ww:1973 stamps the field type);
|
||||
// cstage cgen.c:2128 reads node_isfloat(n) the same way.
|
||||
// Collapsed per A.6.3g (#55).
|
||||
if (isf32type(c, n)) { return 1; };
|
||||
if (isfloattype(c, n)) { return 2; };
|
||||
return 0;
|
||||
};
|
||||
return 0;
|
||||
|
||||
@@ -11587,10 +11587,10 @@ fn indexvaluetnode(c: *cgen, n: *node) *node = {
|
||||
};
|
||||
|
||||
// nodeisunsigned — best-effort cgen-time inference from the AST. We
|
||||
// don't have a typed AST yet, so we walk surface nodes:
|
||||
// walk surface nodes (N_DOT now reads n.type_ — #55 A.6.3g):
|
||||
// nkind.N_INTLIT — never marked unsigned (no tsuffix plumbing yet)
|
||||
// nkind.N_IDENT — look up the local's declared type
|
||||
// nkind.N_DOT — look up the field's declared type via struct reg
|
||||
// nkind.N_DOT — read the checker-stamped n.type_ (#55 A.6.3g)
|
||||
// nkind.N_BIN / nkind.N_UN — recurse: unsigned if either operand is unsigned
|
||||
// nkind.N_CAST — use the cast target type
|
||||
//
|
||||
@@ -11609,43 +11609,7 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = {
|
||||
return false;
|
||||
};
|
||||
if (k == nkind.N_DOT) {
|
||||
let base: *node = n.lhs;
|
||||
let fld: str = n.str;
|
||||
if (base != nil) {
|
||||
if (base.kind == nkind.N_IDENT) {
|
||||
let bn: str = base.str;
|
||||
let lc: *local = localfindnode(c, bn);
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
let lkind: nkind = nkind.N_NONE;
|
||||
if (tn != nil) { lkind = tn.kind; };
|
||||
let sname: str;
|
||||
sname.ptr = nil; sname.len = 0;
|
||||
if (lkind == nkind.N_TPTR) {
|
||||
let inner: *node = tn.lhs;
|
||||
if (inner != nil) {
|
||||
if (inner.kind == nkind.N_TNAME) { sname = inner.str; };
|
||||
};
|
||||
};
|
||||
if (lkind == nkind.N_TNAME) { sname = tn.str; };
|
||||
if (sname.len > 0) {
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
let fn_: str = fi.fname;
|
||||
if (streq(fn_, fld)) {
|
||||
if (fi.tnode == nil) { return false; };
|
||||
return typeisunsigned(fi.tnode.type_: *tinfo);
|
||||
};
|
||||
fi = fi.finext;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
return false;
|
||||
return typeisunsigned(n.type_: *tinfo);
|
||||
};
|
||||
if (k == nkind.N_CAST) {
|
||||
if (n.rhs == nil) { return false; };
|
||||
@@ -12537,42 +12501,12 @@ export fn exprfloatkind(c: *cgen, n: *node) i32 = {
|
||||
// `p.field` where the struct field is f64/f32. Without this,
|
||||
// `v.fval: i64` lowers to CVTSI on an integer-load value
|
||||
// instead of CVTTSD2SI on the X0 the cgdot path actually
|
||||
// emits for an f64 field.
|
||||
let base: *node = n.lhs;
|
||||
let fld: str = n.str;
|
||||
if (base != nil) {
|
||||
let sname: str;
|
||||
sname.ptr = nil; sname.len = 0;
|
||||
if (base.kind == nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, base.str);
|
||||
if (lc != nil) {
|
||||
let tn: *node = lc.tnode;
|
||||
if (tn != nil) {
|
||||
if (tn.kind == nkind.N_TNAME) { sname = tn.str; };
|
||||
if (tn.kind == nkind.N_TPTR) {
|
||||
let pe: *node = tn.lhs;
|
||||
if (pe != nil) {
|
||||
if (pe.kind == nkind.N_TNAME) { sname = pe.str; };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
if (sname.len > 0) {
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
if (si != nil) {
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
if (streq(fi.fname, fld)) {
|
||||
if (isf32type(c, fi.tnode)) { return 1; };
|
||||
if (isfloattype(c, fi.tnode)) { return 2; };
|
||||
return 0;
|
||||
};
|
||||
fi = fi.finext;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// emits for an f64 field. Read the checker-stamped tinfo on
|
||||
// the N_DOT itself (check.ww:1973 stamps the field type);
|
||||
// cstage cgen.c:2128 reads node_isfloat(n) the same way.
|
||||
// Collapsed per A.6.3g (#55).
|
||||
if (isf32type(c, n)) { return 1; };
|
||||
if (isfloattype(c, n)) { return 2; };
|
||||
return 0;
|
||||
};
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user