From 36bf60350cba4d67aebed44802457a0bede2385b Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Tue, 26 May 2026 21:28:14 +0900 Subject: [PATCH] wcc: nodeisunsigned N_INDEX reads stamped type_ (#134) wwstage cgenutil nodeisunsigned N_INDEX arm now reads typeisunsigned(n.type_) directly, mirroring the N_DOT arm at line 1007 and cstage cgen.c:2541 which reads type_isunsigned on the stamped operand. Embodies the #121 principle (collapse structural onto stamp). Byte-id-neutral at master (no current N_INDEX-of-non- IDENT-base unsigned compare sites in bootstrap); fix is for forward consumers in strconv decimal.ha (>= 5u8 on d.digits[nd] with N_DOT base) and similar Hare idioms. Closes #134. --- selfhost/cmd/w6c/main.combined.ww | 35 +++++++++------------------- selfhost/cmd/wcc/cgenutil.ww | 35 +++++++++------------------- selfhost/cmd/wwdump/main.combined.ww | 35 +++++++++------------------- 3 files changed, 33 insertions(+), 72 deletions(-) diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index c98ab225..9b6a5fea 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -12028,31 +12028,18 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = { return nodeisunsigned(c, n.rhs); }; if (k == nkind.N_UN) { return nodeisunsigned(c, n.lhs); }; - // nkind.N_INDEX: `p[i]` is unsigned iff p's element type is unsigned. - // Walks the base local's declared type and pulls the element - // out — *u8 → u8, [N]u32 → u32, []u64 → u64. Without this the - // compare-codegen for `p[i] >= 48u8` falls back to signed JGE - // instead of JAE, diverging from C w6c on byte indexing. + // nkind.N_INDEX: `p[i]` is unsigned iff its element type is + // unsigned. Read the checker-stamped result type directly, + // mirroring the N_DOT arm above and cstage cgen.c:2541 + // (`type_isunsigned(n->lhs->type)` on operand's stamped tinfo). + // Replaces the prior structural base-walk that only fired for + // N_IDENT base — fell through to `return false` for N_DOT base + // (e.g. `d.digits[nd]` where d is a *struct), making + // `d.digits[nd] >= 5u8` pick signed JGE instead of unsigned JAE. + // Embodies the #121 principle (collapse structural onto stamp). + // #134. if (k == nkind.N_INDEX) { - let base: *node = n.lhs; - if (base != nil) { - if (base.kind == nkind.N_IDENT) { - let lc: *local = localfindnode(c, base.str); - if (lc != nil) { - let tn: *node = lc.tnode; - if (tn != nil) { - let elem: *node = nil; - if (tn.kind == nkind.N_TPTR) { elem = tn.lhs; }; - if (tn.kind == nkind.N_TARRAY) { elem = tn.lhs; }; - if (tn.kind == nkind.N_TSLICE) { elem = tn.lhs; }; - if (elem != nil) { - return typeisunsigned(elem.type_: *tinfo); - }; - }; - }; - }; - }; - return false; + return typeisunsigned(n.type_: *tinfo); }; return false; }; diff --git a/selfhost/cmd/wcc/cgenutil.ww b/selfhost/cmd/wcc/cgenutil.ww index 1384dab4..bfeb1cfb 100644 --- a/selfhost/cmd/wcc/cgenutil.ww +++ b/selfhost/cmd/wcc/cgenutil.ww @@ -1015,31 +1015,18 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = { return nodeisunsigned(c, n.rhs); }; if (k == nkind.N_UN) { return nodeisunsigned(c, n.lhs); }; - // nkind.N_INDEX: `p[i]` is unsigned iff p's element type is unsigned. - // Walks the base local's declared type and pulls the element - // out — *u8 → u8, [N]u32 → u32, []u64 → u64. Without this the - // compare-codegen for `p[i] >= 48u8` falls back to signed JGE - // instead of JAE, diverging from C w6c on byte indexing. + // nkind.N_INDEX: `p[i]` is unsigned iff its element type is + // unsigned. Read the checker-stamped result type directly, + // mirroring the N_DOT arm above and cstage cgen.c:2541 + // (`type_isunsigned(n->lhs->type)` on operand's stamped tinfo). + // Replaces the prior structural base-walk that only fired for + // N_IDENT base — fell through to `return false` for N_DOT base + // (e.g. `d.digits[nd]` where d is a *struct), making + // `d.digits[nd] >= 5u8` pick signed JGE instead of unsigned JAE. + // Embodies the #121 principle (collapse structural onto stamp). + // #134. if (k == nkind.N_INDEX) { - let base: *node = n.lhs; - if (base != nil) { - if (base.kind == nkind.N_IDENT) { - let lc: *local = localfindnode(c, base.str); - if (lc != nil) { - let tn: *node = lc.tnode; - if (tn != nil) { - let elem: *node = nil; - if (tn.kind == nkind.N_TPTR) { elem = tn.lhs; }; - if (tn.kind == nkind.N_TARRAY) { elem = tn.lhs; }; - if (tn.kind == nkind.N_TSLICE) { elem = tn.lhs; }; - if (elem != nil) { - return typeisunsigned(elem.type_: *tinfo); - }; - }; - }; - }; - }; - return false; + return typeisunsigned(n.type_: *tinfo); }; return false; }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 42f9e4ac..2fdd2de6 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -12028,31 +12028,18 @@ fn nodeisunsigned(c: *cgen, n: *node) bool = { return nodeisunsigned(c, n.rhs); }; if (k == nkind.N_UN) { return nodeisunsigned(c, n.lhs); }; - // nkind.N_INDEX: `p[i]` is unsigned iff p's element type is unsigned. - // Walks the base local's declared type and pulls the element - // out — *u8 → u8, [N]u32 → u32, []u64 → u64. Without this the - // compare-codegen for `p[i] >= 48u8` falls back to signed JGE - // instead of JAE, diverging from C w6c on byte indexing. + // nkind.N_INDEX: `p[i]` is unsigned iff its element type is + // unsigned. Read the checker-stamped result type directly, + // mirroring the N_DOT arm above and cstage cgen.c:2541 + // (`type_isunsigned(n->lhs->type)` on operand's stamped tinfo). + // Replaces the prior structural base-walk that only fired for + // N_IDENT base — fell through to `return false` for N_DOT base + // (e.g. `d.digits[nd]` where d is a *struct), making + // `d.digits[nd] >= 5u8` pick signed JGE instead of unsigned JAE. + // Embodies the #121 principle (collapse structural onto stamp). + // #134. if (k == nkind.N_INDEX) { - let base: *node = n.lhs; - if (base != nil) { - if (base.kind == nkind.N_IDENT) { - let lc: *local = localfindnode(c, base.str); - if (lc != nil) { - let tn: *node = lc.tnode; - if (tn != nil) { - let elem: *node = nil; - if (tn.kind == nkind.N_TPTR) { elem = tn.lhs; }; - if (tn.kind == nkind.N_TARRAY) { elem = tn.lhs; }; - if (tn.kind == nkind.N_TSLICE) { elem = tn.lhs; }; - if (elem != nil) { - return typeisunsigned(elem.type_: *tinfo); - }; - }; - }; - }; - }; - return false; + return typeisunsigned(n.type_: *tinfo); }; return false; };