wwstage: classify tagged call-source by stamped result type, not callee leaf name (#211)

rhstaggedabicall keyed the tagged-vs-scalar call-source decision off the
callee result type looked up by leaf NAME (fnretlookupmod), with the
receiver variable used as the "module". A value-receiver fn-ptr field
call s.f(...) whose leaf collides with a same-named global fn then
mis-bound the global's register shape, so the source was misclassified
as scalar and widened wrong: silent cs/ww asm divergence and wrong
runtime. Read the checker-stamped N_CALL result type (src.type_)
instead, mirroring the N_DOT sister branch. cstage already reads u->ret
off the typed callee (cmd/wcc/check.c:1490) and harec selects by
interned type id, not name (ref/harec/src/types.c:714).

Graduates test/wcc/782 to STAGE_WW + byte_id.
This commit is contained in:
2026-05-31 23:34:16 +09:00
parent 1995d8e43a
commit db9edb7c39
5 changed files with 143 additions and 122 deletions

View File

@@ -2514,31 +2514,17 @@ fn rhstaggedident(c: *cgen, src: *node) *node = {
fn rhstaggedabicall(c: *cgen, src: *node) bool = {
if (src == nil) { return false; };
if (src.kind == nkind.N_CALL) {
let callee: *node = src.lhs;
if (callee != nil) {
let calleename: str;
calleename.ptr = nil; calleename.len = 0;
let cmod: str;
cmod.ptr = nil; cmod.len = 0;
if (callee.kind == nkind.N_IDENT) {
calleename = callee.str;
cmod = c.curmod;
};
if (callee.kind == nkind.N_DOT) {
calleename = callee.str;
if (callee.lhs != nil) {
if (callee.lhs.kind == nkind.N_IDENT) {
cmod = callee.lhs.str;
};
};
};
if (calleename.len > 0) {
let rtyp: *node = fnretlookupmod(c, calleename, cmod);
if (rtyp != nil) {
if (istaggedtype(c, rtyp)) { return true; };
};
};
};
// #211: a call's result type is the CALLEE's fn-type ret, which
// the checker stamps onto this N_CALL node (check.ww N_CALL: both
// the SK_FN path and the fn-VALUE/field path set e.type_ = the
// result tinfo). Read it directly — a value-receiver fn-ptr FIELD
// call `s.f(...)` keyed by the field leaf `f` with the receiver
// VARIABLE name as the "module" otherwise mis-binds a same-named
// GLOBAL fn of different register shape (silent cs≠ww). cstage's
// sister reads u->ret off the callee type (cmd/wcc/check.c:1433,
// :1490); harec selects by interned type id, not name (ref/harec/
// src/types.c:714). Mirrors the N_DOT branch below.
if (typeistagged(src.type_: *tinfo)) { return true; };
return false;
};
if (src.kind == nkind.N_INDEX) {