cgen: wwstage fnretlookup resolves cross-module callee f64 return type (#98/#101)
exprfloatkind's N_CALL arm only set the callee name for an N_IDENT callee, so a module-qualified `mod.g()` callee never reached any return-type lookup and fell through to integer (kind 0). Both f64 consumers then took the integer path for an imported f64-returning fn: cgcast emitted MOVSXD instead of CVTTSD2SI (#101), and pushargsrev spilled the call result as a GPR PUSHQ/POPQ instead of the MOVSD float spill (#98) — one root, two symptoms. Route the N_DOT callee through fnretlookupmod with the module qualifier, mirroring nodeisslice / nodeisstr's #34 N_DOT arm, so a cross-module f64 call resolves to kind 2 exactly like same-module already does. This aligns wwstage UP to cstage, whose cg_isfloat reads the resolved call result type directly (cmd/w6c/cgen.c:117,155) and is correct for both cases. Consumers (cgcast, pushargsrev) unchanged.
This commit is contained in:
@@ -1889,18 +1889,35 @@ export fn exprfloatkind(c: *cgen, n: *node) i32 = {
|
||||
return 0;
|
||||
};
|
||||
if (k == nkind.N_CALL) {
|
||||
// Look up the callee's declared return type — fnretlookup
|
||||
// Look up the callee's declared return type — fnretlookupmod
|
||||
// returns the type-AST. Routes float-returning fns through
|
||||
// the X0 ABI so cglet / cgassign know to spill from X0.
|
||||
let nm: str;
|
||||
nm.ptr = nil; nm.len = 0;
|
||||
if (n.lhs != nil) {
|
||||
if (n.lhs.kind == nkind.N_IDENT) { nm = n.lhs.str; };
|
||||
};
|
||||
if (nm.len > 0) {
|
||||
let rtyp: *node = fnretlookup(c, nm);
|
||||
if (isf32type(c, rtyp)) { return 1; };
|
||||
if (isfloattype(c, rtyp)) { return 2; };
|
||||
// N_DOT (cross-module callee, #98/#101): without the explicit
|
||||
// arm a module-qualified `myf.g()` callee never reaches any
|
||||
// lookup, so an imported f64-returning fn fell through to
|
||||
// integer (0) — cgcast then emitted MOVSXD not CVTTSD2SI
|
||||
// (#101) and pushargsrev spilled the result as a GPR not
|
||||
// MOVSD (#98). Mirror nodeisslice / nodeisstr's #34 N_DOT arm
|
||||
// so cross-module resolves to kind 2 like same-module does.
|
||||
let callee: *node = n.lhs;
|
||||
if (callee != nil) {
|
||||
if (callee.kind == nkind.N_IDENT) {
|
||||
let rtyp: *node = fnretlookupmod(c, callee.str, c.curmod);
|
||||
if (isf32type(c, rtyp)) { return 1; };
|
||||
if (isfloattype(c, rtyp)) { return 2; };
|
||||
};
|
||||
if (callee.kind == nkind.N_DOT) {
|
||||
let cmod: str;
|
||||
cmod.ptr = nil; cmod.len = 0;
|
||||
if (callee.lhs != nil) {
|
||||
if (callee.lhs.kind == nkind.N_IDENT) {
|
||||
cmod = callee.lhs.str;
|
||||
};
|
||||
};
|
||||
let rtyp: *node = fnretlookupmod(c, callee.str, cmod);
|
||||
if (isf32type(c, rtyp)) { return 1; };
|
||||
if (isfloattype(c, rtyp)) { return 2; };
|
||||
};
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user