wcc/ww: typeeqast identity fast-path for shared type nodes (#36)

wwstage's typeeqast lacked the identity short-circuit cstage type_eq
opens with (cmd/wcc/type.c:250 `if (a == b) return 1`). Enum/struct/
array type nodes are shared from their decl, so two references to the
same type resolve to one node; without the fast-path the catch-all
returns false. Exposed by #26's integer-mismatch reject, which fired
on a same-enum binop like w6l's `os.flag.WRONLY|CREATE|TRUNC` that
cstage accepts via this check. Corpus output unchanged (the w6c_ww/
wwdump_ww binaries move because check.ww regenerates combined.ww).
This commit is contained in:
2026-06-15 01:46:16 +09:00
parent cab85f5bc9
commit 391ef61d42
3 changed files with 24 additions and 0 deletions

View File

@@ -11424,6 +11424,14 @@ fn typeeqast(c: *checker, a: *node, b: *node) bool = {
let bb: *node = unwrapbang(b);
if (aa == nil) { return bb == nil; };
if (bb == nil) { return false; };
// Identity fast-path, mirroring cstage type_eq's first line
// (cmd/wcc/type.c:250 `if (a == b) return 1`). Enum (and struct/
// array) type nodes are shared from their decl, so two references to
// the SAME `os.flag` resolve to one N_TENUM node; without this the
// catch-all below returns false and the #26 reject fires on a
// same-enum binop like `os.flag.WRONLY | os.flag.CREATE` (w6l), which
// cstage accepts via this identity check.
if (aa == bb) { return true; };
if (aa.kind != bb.kind) { return false; };
let k: nkind = aa.kind;
if (k == nkind.N_TNAME) {

View File

@@ -954,6 +954,14 @@ fn typeeqast(c: *checker, a: *node, b: *node) bool = {
let bb: *node = unwrapbang(b);
if (aa == nil) { return bb == nil; };
if (bb == nil) { return false; };
// Identity fast-path, mirroring cstage type_eq's first line
// (cmd/wcc/type.c:250 `if (a == b) return 1`). Enum (and struct/
// array) type nodes are shared from their decl, so two references to
// the SAME `os.flag` resolve to one N_TENUM node; without this the
// catch-all below returns false and the #26 reject fires on a
// same-enum binop like `os.flag.WRONLY | os.flag.CREATE` (w6l), which
// cstage accepts via this identity check.
if (aa == bb) { return true; };
if (aa.kind != bb.kind) { return false; };
let k: nkind = aa.kind;
if (k == nkind.N_TNAME) {

View File

@@ -11424,6 +11424,14 @@ fn typeeqast(c: *checker, a: *node, b: *node) bool = {
let bb: *node = unwrapbang(b);
if (aa == nil) { return bb == nil; };
if (bb == nil) { return false; };
// Identity fast-path, mirroring cstage type_eq's first line
// (cmd/wcc/type.c:250 `if (a == b) return 1`). Enum (and struct/
// array) type nodes are shared from their decl, so two references to
// the SAME `os.flag` resolve to one N_TENUM node; without this the
// catch-all below returns false and the #26 reject fires on a
// same-enum binop like `os.flag.WRONLY | os.flag.CREATE` (w6l), which
// cstage accepts via this identity check.
if (aa == bb) { return true; };
if (aa.kind != bb.kind) { return false; };
let k: nkind = aa.kind;
if (k == nkind.N_TNAME) {