mirror of
https://github.com/justinethier/cyclone.git
synced 2025-07-11 23:07:36 +02:00
Starting to check for over/under flow
This commit is contained in:
parent
14956ea58f
commit
a9f45d8fb5
2 changed files with 52 additions and 14 deletions
|
@ -660,6 +660,7 @@ typedef union {
|
||||||
primitive_type primitive_t;
|
primitive_type primitive_t;
|
||||||
integer_type integer_t;
|
integer_type integer_t;
|
||||||
double_type double_t;
|
double_type double_t;
|
||||||
|
bignum_type bignum_t;
|
||||||
} common_type;
|
} common_type;
|
||||||
|
|
||||||
/* Utility functions */
|
/* Utility functions */
|
||||||
|
|
65
runtime.c
65
runtime.c
|
@ -2445,7 +2445,26 @@ object __halt(object obj)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define declare_num_op(FUNC, FUNC_OP, FUNC_APPLY, OP, NO_ARG, ONE_ARG, DIV) \
|
static int Cyc_checked_add(int x, int y, int *result)
|
||||||
|
{
|
||||||
|
*result = x + y;
|
||||||
|
return ((((*result ^ x) & (*result ^ y)) >> 30) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Cyc_checked_sub(int x, int y, int *result)
|
||||||
|
{
|
||||||
|
*result = x - y;
|
||||||
|
return ((((*result ^ x) & ~(*result ^ y)) >> 30) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: overflow checking
|
||||||
|
static int Cyc_checked_mul(int x, int y, int *result)
|
||||||
|
{
|
||||||
|
*result = x * y;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define declare_num_op(FUNC, FUNC_OP, FUNC_APPLY, OP, INT_OP, NO_ARG, ONE_ARG, DIV) \
|
||||||
object FUNC_OP(void *data, common_type *x, object y) { \
|
object FUNC_OP(void *data, common_type *x, object y) { \
|
||||||
int tx, ty; \
|
int tx, ty; \
|
||||||
tx = type_of(x); \
|
tx = type_of(x); \
|
||||||
|
@ -2463,7 +2482,13 @@ object FUNC_OP(void *data, common_type *x, object y) { \
|
||||||
Cyc_rt_raise_msg(data, "Divide by zero"); \
|
Cyc_rt_raise_msg(data, "Divide by zero"); \
|
||||||
} \
|
} \
|
||||||
if (tx == integer_tag && ty == -1) { \
|
if (tx == integer_tag && ty == -1) { \
|
||||||
x->integer_t.value = (x->integer_t.value) OP (obj_obj2int(y)); \
|
int result; \
|
||||||
|
if (INT_OP(x->integer_t.value, obj_obj2int(y), &result) == 0) { \
|
||||||
|
x->integer_t.value = result; \
|
||||||
|
} else { \
|
||||||
|
fprintf(stderr, "integer overflow or underflow detected\n"); \
|
||||||
|
exit(1); \
|
||||||
|
} \
|
||||||
} else if (tx == double_tag && ty == -1) { \
|
} else if (tx == double_tag && ty == -1) { \
|
||||||
x->double_t.value = x->double_t.value OP (obj_obj2int(y)); \
|
x->double_t.value = x->double_t.value OP (obj_obj2int(y)); \
|
||||||
} else if (tx == integer_tag && ty == integer_tag) { \
|
} else if (tx == integer_tag && ty == integer_tag) { \
|
||||||
|
@ -2515,12 +2540,15 @@ object Cyc_fast_sum(void *data, object ptr, object x, object y) {
|
||||||
if (obj_is_int(y)){
|
if (obj_is_int(y)){
|
||||||
int xx = obj_obj2int(x),
|
int xx = obj_obj2int(x),
|
||||||
yy = obj_obj2int(y),
|
yy = obj_obj2int(y),
|
||||||
z = xx + yy;
|
z;
|
||||||
//if((((z ^ xx) & (z ^ yy)) >> 30) != 0) { // overflow
|
|
||||||
// assign_double(ptr, (double)xx + (double)yy);
|
if (Cyc_checked_add(xx, yy, &z) == 0) {
|
||||||
// return ptr;
|
return obj_int2obj(z);
|
||||||
//}
|
} else {
|
||||||
return obj_int2obj(z);
|
// TODO: no, use bignum instead
|
||||||
|
assign_double(ptr, (double)xx + (double)yy);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
} else if (is_object_type(y) && type_of(y) == double_tag) {
|
} else if (is_object_type(y) && type_of(y) == double_tag) {
|
||||||
assign_double(ptr, (double)(obj_obj2int(x)) + double_value(y));
|
assign_double(ptr, (double)(obj_obj2int(x)) + double_value(y));
|
||||||
return ptr;
|
return ptr;
|
||||||
|
@ -2549,8 +2577,18 @@ object Cyc_fast_sub(void *data, object ptr, object x, object y) {
|
||||||
// x is int (assume value types for integers)
|
// x is int (assume value types for integers)
|
||||||
if (obj_is_int(x)){
|
if (obj_is_int(x)){
|
||||||
if (obj_is_int(y)){
|
if (obj_is_int(y)){
|
||||||
int z = obj_obj2int(x) - obj_obj2int(y);
|
int xx = obj_obj2int(x),
|
||||||
return obj_int2obj(z);
|
yy = obj_obj2int(y),
|
||||||
|
z;
|
||||||
|
if (Cyc_checked_sub(xx, yy, &z) == 0) {
|
||||||
|
return obj_int2obj(z);
|
||||||
|
} else {
|
||||||
|
// TODO: no, use bignum instead
|
||||||
|
assign_double(ptr, (double)xx - (double)yy);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
// int z = obj_obj2int(x) - obj_obj2int(y);
|
||||||
|
// return obj_int2obj(z);
|
||||||
} else if (is_object_type(y) && type_of(y) == double_tag) {
|
} else if (is_object_type(y) && type_of(y) == double_tag) {
|
||||||
assign_double(ptr, (double)(obj_obj2int(x)) - double_value(y));
|
assign_double(ptr, (double)(obj_obj2int(x)) - double_value(y));
|
||||||
return ptr;
|
return ptr;
|
||||||
|
@ -2707,10 +2745,9 @@ void dispatch_div(void *data, int argc, object clo, object cont, object n, ...)
|
||||||
return_closcall1(data, cont, result);
|
return_closcall1(data, cont, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_num_op(Cyc_sum, Cyc_sum_op, dispatch_sum, +, 0, 0, 0);
|
declare_num_op(Cyc_sum, Cyc_sum_op, dispatch_sum, +, Cyc_checked_add, 0, 0, 0);
|
||||||
declare_num_op(Cyc_sub, Cyc_sub_op, dispatch_sub, -, -1, 0, 0);
|
declare_num_op(Cyc_sub, Cyc_sub_op, dispatch_sub, -, Cyc_checked_sub, -1, 0, 0);
|
||||||
declare_num_op(Cyc_mul, Cyc_mul_op, dispatch_mul, *, 1, 1, 0);
|
declare_num_op(Cyc_mul, Cyc_mul_op, dispatch_mul, *, Cyc_checked_mul, 1, 1, 0);
|
||||||
//declare_num_op(Cyc_div, Cyc_div_op2, dispatch_div, /, -1, 1, 1);
|
|
||||||
|
|
||||||
object Cyc_num_op_va_list(void *data, int argc,
|
object Cyc_num_op_va_list(void *data, int argc,
|
||||||
object(fn_op(void *, common_type *, object)),
|
object(fn_op(void *, common_type *, object)),
|
||||||
|
|
Loading…
Add table
Reference in a new issue