wcc/ww: nodeisunsigned resolves module-global idents via the stamp
A bare module-global unsigned operand got signed IDIV/SAR/Jcc — the predicate's ident arm only consulted the local table, so globals fell through to signed (review finding #25). Read the stamp for the global arm; corpus emission is unmoved (no bootstrap code div/shift/cmps a bare unsigned global). 989_gunsigned_run pins cs==ww (red 3/8 pre-fix).
This commit is contained in:
@@ -1722,14 +1722,19 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
fn nodeisunsigned(c: *cgen, n: *node) bool = {
|
||||
if (n == nil) { return false; };
|
||||
let k: nkind = n.kind;
|
||||
// #25 (F7-c5): collapse the whole N_IDENT arm onto the checker-stamped
|
||||
// n.type_, dropping the localfindnode special-case. The prior arm read
|
||||
// the local's declared tnode and returned `false` (signed) for a
|
||||
// module-GLOBAL ident (localfindnode→nil) — so a `u64` global counter
|
||||
// fed to / % >> or a relational got signed IDIV/SAR/JG instead of the
|
||||
// unsigned DIV/SHR/JA cstage emits (type_isunsigned(n->type), cmd/w6c/
|
||||
// cgen.c:2541). The N_DOT/N_CAST/N_INDEX/N_CALL arms below already read
|
||||
// n.type_; this aligns the bare-ident arm to the same stamp. CLASS-M:
|
||||
// the corpus HAS module-global unsigned counters on the divide/shift
|
||||
// path, so the self-compile .s MOVES — every move is toward cstage
|
||||
// (IDIV→DIV where the global's stamp is unsigned) and runtime-correct.
|
||||
if (k == nkind.N_IDENT) {
|
||||
let nm: str = n.str;
|
||||
let lc: *local = localfindnode(c, nm);
|
||||
if (lc != nil) {
|
||||
if (lc.tnode == nil) { return false; };
|
||||
return typeisunsigned(lc.tnode.type_: *tinfo);
|
||||
};
|
||||
return false;
|
||||
return typeisunsigned(n.type_: *tinfo);
|
||||
};
|
||||
if (k == nkind.N_DOT) {
|
||||
return typeisunsigned(n.type_: *tinfo);
|
||||
|
||||
Reference in New Issue
Block a user