commit 3f7e8cab087bf4c20a993c64707c65affe22aa54
parent 9f93e8e0c21f5d6359a19015ea431fb420e6e750
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Fri, 1 May 2026 17:49:56 -0700
cc/cg: cg-arith-conv casts to common type, not relabel-only
Same-size cross-signedness conversions (i32→u32, u32→i32, etc.)
need a real zext/sext to bring the canonical 64-bit slot form into
line with the new type. The previous arith-conv just rewrote the
opnd type tag, so an i32 -3 relabeled to u32 kept its sign-extended
slot bits (0xFFFFFFFFFFFFFFFD) and a subsequent compare against a
u32 literal 4294967293 (loaded as 0x00000000FFFFFFFD by %li) saw
mismatched upper bits.
Route both operands through cg-cast against the common type. cg-cast
already short-circuits no-op widenings, so the fix only emits real
work for the conversions that change canonical form.
New cc-cg fixture 85-i32-u32-eq locks in -3 == 4294967293u after
the usual arithmetic conversions.
Diffstat:
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/cc/cc.scm b/cc/cc.scm
@@ -3510,8 +3510,18 @@
((%ctype-unsigned? ta) ta)
((%ctype-unsigned? tb) tb)
(else ta))))
- (cg-push cg (%opnd (opnd-kind a) common (opnd-ext a) (opnd-lval? a)))
- (cg-push cg (%opnd (opnd-kind b) common (opnd-ext b) (opnd-lval? b))))))))
+ ;; Route through cg-cast (rather than relabel only) so the
+ ;; canonical 64-bit slot form lines up with COMMON. Same-size
+ ;; cross-signedness conversions (i32→u32, u32→i32, …) need an
+ ;; actual zext/sext to canonicalize; otherwise an i32 -3
+ ;; relabeled to u32 keeps its sign-extended slot bits and
+ ;; compares unequal to a u32 imm with the same C value.
+ (cg-push cg a) (cg-cast cg common)
+ (let ((a* (cg-pop cg)))
+ (cg-push cg b) (cg-cast cg common)
+ (let ((b* (cg-pop cg)))
+ (cg-push cg a*)
+ (cg-push cg b*))))))))
;; --------------------------------------------------------------------
;; Operators