cgen: resolve chained-DOT fn-ptr field callees
fnptrcalleetfn's N_DOT arm required an N_IDENT base, so a.b.cb(...) fell to the name registry with an empty module hint and emitted CALL cb(SB) (undefined symbol; cstage calls the stamped ptr indirect). dotbasestructinfo resolves the base chain through the struct registry — each link a struct- or *struct-typed field — and the single-dot path routes through the same resolver unchanged. Closes the last open shape of the #59.8 name-keyed callee family. Fixture fnptrfield_chain; corpus pin 1487/2974.
This commit is contained in:
@@ -32,9 +32,9 @@ categories out of the ordinary developer target.
|
||||
| Fixed point and self-host | `test-bootstrap` |
|
||||
| Host linker/platform behavior | `test-platform` |
|
||||
|
||||
The live declarative compiler corpus has 1,486 fixtures and 2,972 C/WW cells:
|
||||
The live declarative compiler corpus has 1,487 fixtures and 2,974 C/WW cells:
|
||||
338 expected rejections (314 shared and 24 stage-specific), 17 compile-only
|
||||
successes, 191 exit-zero programs, and 940 explicit-exit programs.
|
||||
successes, 191 exit-zero programs, and 941 explicit-exit programs.
|
||||
|
||||
147 native C carriers remain. They are partitioned exactly once as five
|
||||
in-process units, 24 byte/artifact gates, six bootstrap gates, one platform
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package wwfixture;
|
||||
|
||||
def protocolversion: i32 = 1;
|
||||
def corpuscount: i32 = 1486;
|
||||
def corpuscount: i32 = 1487;
|
||||
def errorcount: i32 = 338;
|
||||
def compilecount: i32 = 17;
|
||||
def runcount: i32 = 191;
|
||||
def runexitcount: i32 = 940;
|
||||
def nativecount: i32 = 2972;
|
||||
def corpushash: str = "ab4b1d1ffc078b23de0a70911740511e873cd8d6f76009c4719d704bb36e6133";
|
||||
def runexitcount: i32 = 941;
|
||||
def nativecount: i32 = 2974;
|
||||
def corpushash: str = "2520ada0b1687fab6eed6073a263c620fa4cbab6dc8156f7d51bcf8b14a9ec4a";
|
||||
|
||||
type directive = enum i32 {
|
||||
ERROR = 0,
|
||||
|
||||
@@ -64,6 +64,53 @@ fn findvariadicparam(ps: *syntax.node, nfixed_out: *i32) *syntax.node = {
|
||||
// lookup missed entirely and the raw N_SPREAD leaked to pushargsrev
|
||||
// as a single $0 word). Cstage mirror: cgcall's callee_params from
|
||||
// the checker-stamped n->lhs->type (cmd/w6c/cgen.c TY_FN cu->params).
|
||||
// dotbasestructinfo — the struct registry entry for a DOT base: a
|
||||
// local ident (struct value or *struct), or a nested field chain
|
||||
// (`a.b.cb(...)` — each link a struct- or *struct-typed field). The
|
||||
// chained form previously fell to the name registry with an empty
|
||||
// module hint (the #59.8 family's last open shape) and emitted
|
||||
// CALL <leaf>(SB).
|
||||
fn dotbasestructinfo(c: *cgen, base: *syntax.node) *structinfo = {
|
||||
if (base == nil) { return nil; };
|
||||
if (base.kind == syntax.nkind.N_IDENT) {
|
||||
let lc: *local = localfindnode(c, base.str);
|
||||
if (lc == nil) { return nil; };
|
||||
let tn: *syntax.node = lc.tnode;
|
||||
if (tn == nil) { return nil; };
|
||||
let sname: str;
|
||||
sname.ptr = nil; sname.len = 0;
|
||||
if (tn.kind == syntax.nkind.N_TNAME) { sname = tn.str; };
|
||||
if (tn.kind == syntax.nkind.N_TPTR) {
|
||||
if (tn.lhs != nil) {
|
||||
if (tn.lhs.kind == syntax.nkind.N_TNAME) {
|
||||
sname = tn.lhs.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
if (sname.len == 0) { return nil; };
|
||||
return structlookup(c, sname);
|
||||
};
|
||||
if (base.kind != syntax.nkind.N_DOT) { return nil; };
|
||||
let outer: *structinfo = dotbasestructinfo(c, base.lhs);
|
||||
if (outer == nil) { return nil; };
|
||||
let fi: *fieldinfo = outer.fields;
|
||||
for (fi != nil) {
|
||||
if (syntax.streq(fi.fname, base.str)) {
|
||||
let ft: *syntax.node = fi.tnode;
|
||||
if (ft == nil) { return nil; };
|
||||
if (ft.kind == syntax.nkind.N_TPTR) {
|
||||
if (ft.lhs != nil) { ft = ft.lhs; };
|
||||
};
|
||||
if (ft.kind == syntax.nkind.N_TNAME) {
|
||||
return structlookup(c, ft.str);
|
||||
};
|
||||
return nil;
|
||||
};
|
||||
fi = fi.finext;
|
||||
};
|
||||
return nil;
|
||||
};
|
||||
|
||||
fn fnptrcalleetfn(c: *cgen, callee: *syntax.node) *syntax.node = {
|
||||
if (callee == nil) { return nil; };
|
||||
if (callee.kind == syntax.nkind.N_IDENT) {
|
||||
@@ -82,25 +129,7 @@ fn fnptrcalleetfn(c: *cgen, callee: *syntax.node) *syntax.node = {
|
||||
return nil;
|
||||
};
|
||||
if (callee.kind != syntax.nkind.N_DOT) { return nil; };
|
||||
let base: *syntax.node = callee.lhs;
|
||||
if (base == nil) { return nil; };
|
||||
if (base.kind != syntax.nkind.N_IDENT) { return nil; };
|
||||
let lc: *local = localfindnode(c, base.str);
|
||||
if (lc == nil) { return nil; };
|
||||
let tn: *syntax.node = lc.tnode;
|
||||
if (tn == nil) { return nil; };
|
||||
let sname: str;
|
||||
sname.ptr = nil; sname.len = 0;
|
||||
if (tn.kind == syntax.nkind.N_TNAME) { sname = tn.str; };
|
||||
if (tn.kind == syntax.nkind.N_TPTR) {
|
||||
if (tn.lhs != nil) {
|
||||
if (tn.lhs.kind == syntax.nkind.N_TNAME) {
|
||||
sname = tn.lhs.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
if (sname.len == 0) { return nil; };
|
||||
let si: *structinfo = structlookup(c, sname);
|
||||
let si: *structinfo = dotbasestructinfo(c, callee.lhs);
|
||||
if (si == nil) { return nil; };
|
||||
let fi: *fieldinfo = si.fields;
|
||||
for (fi != nil) {
|
||||
|
||||
27
test/wcc/data/fnptrfield_chain/case.ww
Normal file
27
test/wcc/data/fnptrfield_chain/case.ww
Normal file
@@ -0,0 +1,27 @@
|
||||
//ww:run-exit 36
|
||||
package main;
|
||||
|
||||
// A call through a chained-DOT fn-ptr field (a.b.cb(...)). The wwstage
|
||||
// callee resolver only accepted an N_IDENT base, so the chained shape
|
||||
// fell to the name registry with an empty module hint and emitted
|
||||
// CALL cb(SB) — the last open shape of the #59.8 name-keyed family.
|
||||
|
||||
type bstr = struct {
|
||||
cb: *fn(x: i32) i32,
|
||||
pad: i32,
|
||||
};
|
||||
|
||||
type astr = struct {
|
||||
n: i32,
|
||||
b: bstr,
|
||||
};
|
||||
|
||||
fn twice(x: i32) i32 = { return x * 2; };
|
||||
|
||||
fn main() i32 = {
|
||||
let a: astr;
|
||||
a.n = 1;
|
||||
a.b.cb = &twice;
|
||||
a.b.pad = 2;
|
||||
return a.b.cb(20) + a.n + a.b.pad - 7;
|
||||
};
|
||||
Reference in New Issue
Block a user