cgen: fix unsigned/signed integer comparisons
parent
02f9b5d0e4
commit
ddb1770af2
|
@ -41,6 +41,8 @@ const (
|
||||||
'class',
|
'class',
|
||||||
'typename'
|
'typename'
|
||||||
]
|
]
|
||||||
|
cmp_str = ['eq', 'ne', 'gt', 'lt', 'ge', 'le'] // same order as in token.Kind
|
||||||
|
cmp_rev = ['eq', 'ne', 'le', 'ge', 'lt', 'gt'] // when operands are switched
|
||||||
)
|
)
|
||||||
|
|
||||||
struct Gen {
|
struct Gen {
|
||||||
|
@ -1688,11 +1690,21 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
// g.infix_op = node.op
|
// g.infix_op = node.op
|
||||||
left_type := if node.left_type == table.t_type { g.cur_generic_type } else { node.left_type }
|
left_type := if node.left_type == table.t_type { g.cur_generic_type } else { node.left_type }
|
||||||
left_sym := g.table.get_type_symbol(left_type)
|
left_sym := g.table.get_type_symbol(left_type)
|
||||||
|
unaliased_left := if left_sym.kind == .alias {
|
||||||
|
(left_sym.info as table.Alias).parent_typ
|
||||||
|
} else {
|
||||||
|
left_type
|
||||||
|
}
|
||||||
if node.op in [.key_is, .not_is] {
|
if node.op in [.key_is, .not_is] {
|
||||||
g.is_expr(node)
|
g.is_expr(node)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
right_sym := g.table.get_type_symbol(node.right_type)
|
right_sym := g.table.get_type_symbol(node.right_type)
|
||||||
|
unaliased_right := if right_sym.kind == .alias {
|
||||||
|
(right_sym.info as table.Alias).parent_typ
|
||||||
|
} else {
|
||||||
|
node.right_type
|
||||||
|
}
|
||||||
if left_type == table.ustring_type_idx && node.op != .key_in && node.op != .not_in {
|
if left_type == table.ustring_type_idx && node.op != .key_in && node.op != .not_in {
|
||||||
fn_name := match node.op {
|
fn_name := match node.op {
|
||||||
.plus {
|
.plus {
|
||||||
|
@ -1837,6 +1849,20 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
}
|
}
|
||||||
g.write(' }))')
|
g.write(' }))')
|
||||||
}
|
}
|
||||||
|
} else if unaliased_left.idx() in [table.u32_type_idx, table.u64_type_idx] && unaliased_right.is_signed() && node.op in [.eq, .ne, .gt, .lt, .ge, .le] {
|
||||||
|
bitsize := if unaliased_left.idx() == table.u32_type_idx && unaliased_right.idx() != table.i64_type_idx { 32 } else { 64 }
|
||||||
|
g.write('_us${bitsize}_${cmp_str[int(node.op)-int(token.Kind.eq)]}(')
|
||||||
|
g.expr(node.left)
|
||||||
|
g.write(',')
|
||||||
|
g.expr(node.right)
|
||||||
|
g.write(')')
|
||||||
|
} else if unaliased_right.idx() in [table.u32_type_idx, table.u64_type_idx] && unaliased_left.is_signed() && node.op in [.eq, .ne, .gt, .lt, .ge, .le] {
|
||||||
|
bitsize := if unaliased_right.idx() == table.u32_type_idx && unaliased_left.idx() != table.i64_type_idx { 32 } else { 64 }
|
||||||
|
g.write('_us${bitsize}_${cmp_rev[int(node.op)-int(token.Kind.eq)]}(')
|
||||||
|
g.expr(node.right)
|
||||||
|
g.write(',')
|
||||||
|
g.expr(node.left)
|
||||||
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
a := left_sym.name[0].is_capital() || left_sym.name.contains('.')
|
a := left_sym.name[0].is_capital() || left_sym.name.contains('.')
|
||||||
b := left_sym.kind != .alias
|
b := left_sym.kind != .alias
|
||||||
|
|
|
@ -211,6 +211,21 @@ void* g_live_info = NULL;
|
||||||
#define _IN(typ, val, arr) array_##typ##_contains(arr, val)
|
#define _IN(typ, val, arr) array_##typ##_contains(arr, val)
|
||||||
#define _IN_MAP(val, m) map_exists(m, val)
|
#define _IN_MAP(val, m) map_exists(m, val)
|
||||||
|
|
||||||
|
// unsigned/signed comparisons
|
||||||
|
|
||||||
|
static inline bool _us32_gt(uint32_t a, int32_t b) { return a > INT32_MAX || (int32_t)a > b; }
|
||||||
|
static inline bool _us32_ge(uint32_t a, int32_t b) { return a >= INT32_MAX || (int32_t)a >= b; }
|
||||||
|
static inline bool _us32_eq(uint32_t a, int32_t b) { return a <= INT32_MAX && (int32_t)a == b; }
|
||||||
|
static inline bool _us32_ne(uint32_t a, int32_t b) { return a > INT32_MAX || (int32_t)a != b; }
|
||||||
|
static inline bool _us32_le(uint32_t a, int32_t b) { return a <= INT32_MAX && (int32_t)a <= b; }
|
||||||
|
static inline bool _us32_lt(uint32_t a, int32_t b) { return a < INT32_MAX && (int32_t)a < b; }
|
||||||
|
static inline bool _us64_gt(uint64_t a, int64_t b) { return a > INT64_MAX || (int64_t)a > b; }
|
||||||
|
static inline bool _us64_ge(uint64_t a, int64_t b) { return a >= INT64_MAX || (int64_t)a >= b; }
|
||||||
|
static inline bool _us64_eq(uint64_t a, int64_t b) { return a <= INT64_MAX && (int64_t)a == b; }
|
||||||
|
static inline bool _us64_ne(uint64_t a, int64_t b) { return a > INT64_MAX || (int64_t)a != b; }
|
||||||
|
static inline bool _us64_le(uint64_t a, int64_t b) { return a <= INT64_MAX && (int64_t)a <= b; }
|
||||||
|
static inline bool _us64_lt(uint64_t a, int64_t b) { return a < INT64_MAX && (int64_t)a < b; }
|
||||||
|
|
||||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||||
#undef PRId64
|
#undef PRId64
|
||||||
#undef PRIi64
|
#undef PRIi64
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
fn test_cmp_signed() {
|
||||||
|
assert i8(3) > i16(-10)
|
||||||
|
assert i16(-9) > int(-11)
|
||||||
|
assert i64(-12) <= i8(-12)
|
||||||
|
assert i64(-43232554) < i8(-126)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_cmp_unsigned() {
|
||||||
|
assert byte(3) < u16(10)
|
||||||
|
assert u16(40000) > u32(200)
|
||||||
|
assert u64(18161419857654944321) >= byte(12)
|
||||||
|
assert u64(40000) < u16(40001)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_cmp_unsigned_signed() {
|
||||||
|
assert byte(12) > i8(-12)
|
||||||
|
assert i16(-27) < u32(65463356)
|
||||||
|
assert u32(8543) > int(-7523)
|
||||||
|
assert i64(-89) <= u64(567)
|
||||||
|
assert int(-1) != u32(0xffffffff)
|
||||||
|
assert !(u64(0xfffffffffffffffe) == i64(-2))
|
||||||
|
}
|
Loading…
Reference in New Issue