Add proper checks for fits-in-small-int. Make it reusable.
We likely should make mp_obj_new_int() inline, and rely on its encapsulated check rather than inline checks everywhere explicitly. Also, parser for big small int values is still broken.
This commit is contained in:
parent
c260bc58e6
commit
757ac81a69
2
py/obj.h
2
py/obj.h
@ -34,6 +34,8 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
|
||||
// - xxxx...xx10: a qstr, bits 2 and above are the value
|
||||
// - xxxx...xx00: a pointer to an mp_obj_base_t
|
||||
|
||||
// In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range
|
||||
#define MP_OBJ_FITS_SMALL_INT(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0)
|
||||
#define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0)
|
||||
#define MP_OBJ_IS_QSTR(o) ((((mp_small_int_t)(o)) & 3) == 2)
|
||||
#define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 3) == 0)
|
||||
|
17
py/runtime.c
17
py/runtime.c
@ -268,10 +268,6 @@ void rt_assign_inline_asm_code(int unique_code_id, void *fun, uint len, int n_ar
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool fit_small_int(mp_small_int_t o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int rt_is_true(mp_obj_t arg) {
|
||||
DEBUG_OP_printf("is true %p\n", arg);
|
||||
if (MP_OBJ_IS_SMALL_INT(arg)) {
|
||||
@ -436,13 +432,10 @@ mp_obj_t rt_unary_op(int op, mp_obj_t arg) {
|
||||
case RT_UNARY_OP_INVERT: val = ~val; break;
|
||||
default: assert(0); val = 0;
|
||||
}
|
||||
if (fit_small_int(val)) {
|
||||
if (MP_OBJ_FITS_SMALL_INT(val)) {
|
||||
return MP_OBJ_NEW_SMALL_INT(val);
|
||||
} else {
|
||||
// TODO make a bignum
|
||||
assert(0);
|
||||
return mp_const_none;
|
||||
}
|
||||
return mp_obj_new_int(val);
|
||||
} else { // will be an object (small ints are caught in previous if)
|
||||
mp_obj_base_t *o = arg;
|
||||
if (o->type->unary_op != NULL) {
|
||||
@ -551,11 +544,11 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
|
||||
default: assert(0);
|
||||
}
|
||||
if (fit_small_int(lhs_val)) {
|
||||
// TODO: We just should make mp_obj_new_int() inline and use that
|
||||
if (MP_OBJ_FITS_SMALL_INT(lhs_val)) {
|
||||
return MP_OBJ_NEW_SMALL_INT(lhs_val);
|
||||
}
|
||||
// TODO: return long int
|
||||
assert(0);
|
||||
return mp_obj_new_int(lhs_val);
|
||||
} else if (MP_OBJ_IS_TYPE(rhs, &float_type)) {
|
||||
return mp_obj_float_binary_op(op, lhs_val, rhs);
|
||||
} else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) {
|
||||
|
26
tests/basics/tests/int-small.py
Normal file
26
tests/basics/tests/int-small.py
Normal file
@ -0,0 +1,26 @@
|
||||
# This test small int range for 32-bit machine
|
||||
|
||||
a = 0x3fffff
|
||||
print(a)
|
||||
a *= 0x10
|
||||
print(a)
|
||||
a *= 0x10
|
||||
print(a)
|
||||
a += 0xff
|
||||
print(a)
|
||||
# This would overflow
|
||||
#a += 1
|
||||
|
||||
a = -0x3fffff
|
||||
print(a)
|
||||
a *= 0x10
|
||||
print(a)
|
||||
a *= 0x10
|
||||
print(a)
|
||||
a -= 0xff
|
||||
print(a)
|
||||
# This still doesn't overflow
|
||||
a -= 1
|
||||
print(a)
|
||||
# This would overflow
|
||||
#a -= 1
|
Loading…
x
Reference in New Issue
Block a user