Skip to content

Commit 37ea474

Browse files
committed
Fix comparison with different signedness
1 parent 4832128 commit 37ea474

5 files changed

Lines changed: 26 additions & 20 deletions

File tree

src/cc/arch/aarch64/ir_aarch64.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -703,8 +703,7 @@ static void ei_cast(IR *ir) {
703703
}
704704
} else {
705705
// fix->fix
706-
assert(ir->dst->vsize != ir->opr1->vsize);
707-
if (ir->dst->vsize < ir->opr1->vsize) {
706+
if (ir->dst->vsize <= ir->opr1->vsize) {
708707
if (ir->dst->phys != ir->opr1->phys) {
709708
int pow = ir->dst->vsize;
710709
assert(0 <= pow && pow < 4);

src/cc/arch/riscv64/ir_riscv64.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -620,28 +620,30 @@ static void ei_cast(IR *ir) {
620620
}
621621
} else {
622622
// fix->fix
623-
assert(ir->dst->vsize != ir->opr1->vsize);
624623
int pows = ir->opr1->vsize;
625624
int powd = ir->dst->vsize;
626625
assert(0 <= pows && pows < 4);
627626
assert(0 <= powd && powd < 4);
628627
int pow = MIN(powd, pows);
629628
const char *dst = kReg64s[ir->dst->phys], *src = kReg64s[ir->opr1->phys];
630-
631-
if (ir->flag & IRF_UNSIGNED) {
632-
switch (pow) {
633-
case 0: ZEXT_B(dst, src); break;
634-
case 1: ZEXT_H(dst, src); break;
635-
case 2: ZEXT_W(dst, src); break;
636-
default: assert(false); break;
637-
}
638-
} else {
639-
switch (pow) {
640-
case 0: SEXT_B(dst, src); break;
641-
case 1: SEXT_H(dst, src); break;
642-
case 2: SEXT_W(dst, src); break;
643-
default: assert(false); break;
629+
if (pow < 3) {
630+
if (((ir->flag & IRF_UNSIGNED) != 0) == (powd > pows)) {
631+
switch (pow) {
632+
case 0: ZEXT_B(dst, src); break;
633+
case 1: ZEXT_H(dst, src); break;
634+
case 2: ZEXT_W(dst, src); break;
635+
default: assert(false); break;
636+
}
637+
} else {
638+
switch (pow) {
639+
case 0: SEXT_B(dst, src); break;
640+
case 1: SEXT_H(dst, src); break;
641+
case 2: SEXT_W(dst, src); break;
642+
default: assert(false); break;
643+
}
644644
}
645+
} else if (ir->dst->phys != ir->opr1->phys) {
646+
MV(dst, src);
645647
}
646648
}
647649
}

src/cc/arch/x64/ir_x64.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,8 +727,7 @@ static void ei_cast(IR *ir) {
727727
}
728728
} else {
729729
// fix->fix
730-
assert(ir->dst->vsize != ir->opr1->vsize);
731-
if (ir->dst->vsize < ir->opr1->vsize) {
730+
if (ir->dst->vsize <= ir->opr1->vsize) {
732731
if (ir->dst->phys != ir->opr1->phys) {
733732
int pow = ir->dst->vsize;
734733
assert(0 <= pow && pow < 4);

src/cc/backend/codegen_expr.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ static VReg *gen_cast(Expr *expr) {
206206

207207
size_t src_size = 1U << vreg->vsize;
208208
if (dst_size == src_size &&
209-
is_flonum(dst_type) == ((vreg->flag & VRF_FLONUM) != 0))
209+
is_flonum(dst_type) == ((vreg->flag & VRF_FLONUM) != 0) &&
210+
(is_flonum(dst_type) || is_unsigned(dst_type) == is_unsigned(src->type)))
210211
return vreg;
211212

212213
IR *ir = new_ir_cast(vreg, to_vsize(dst_type), to_vflag(dst_type));

tests/valtest.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,11 @@ TEST(all) {
335335
EXPECT("compare with different sign1", 1, minus > uone); // !!!
336336
EXPECT("compare with different sign2", 1, uone < minus); // !!!
337337
EXPECT("compare with hex literal", 1, minus < 0xf6); // Hex literal is signed.
338+
339+
int32_t x = -20;
340+
uint32_t y = -10;
341+
EXPECT_TRUE(y > x);
342+
EXPECT("compare with different sign3", 111, y > x ? 111 : -111);
338343
}
339344
EXPECT("condition is true", true, (x = 3, (x != 0) == true));
340345
EXPECT("condition is not true", false, (x = 4, (x > 0) != true));

0 commit comments

Comments
 (0)