diff --git a/Makefile.am b/Makefile.am index 4640292..9784828 100644 --- a/Makefile.am +++ b/Makefile.am @@ -213,9 +213,12 @@ GenNavAST_SOURCES = pregen/GenNavAST.hs $(pregen_sources) GenOrdAST_SOURCES = pregen/GenOrdAST.hs $(pregen_sources) GenTagAST_SOURCES = pregen/GenTagAST.hs $(pregen_sources) +rangetest_SOURCES = rangetest.c +rangetest_LDFLAGS = -lm + #The programs to actually build: bin_PROGRAMS = tock -noinst_PROGRAMS = tocktest GenNavAST GenOrdAST GenTagAST +noinst_PROGRAMS = tocktest GenNavAST GenOrdAST GenTagAST rangetest TESTS = tocktest pkginclude_HEADERS = support/tock_support.h diff --git a/configure.ac b/configure.ac index 080dfbc..8d7454e 100644 --- a/configure.ac +++ b/configure.ac @@ -157,6 +157,14 @@ AC_CHECK_SIZEOF(int) AC_COMPUTE_INT(C_INT_SIZE,SIZEOF_INT) AC_SUBST(C_INT_SIZE) +CFLAGS="$CFLAGS -fno-strict-overflow -fno-tree-vrp" +# The reason for -fno-strict-overflow and -fno-tree-vrp above is that with the way I have implemented +# range checking, on GCC 4.3.2 (and probably other versions), GCC has +# a bug triggered that causes invalid behaviour (spurious overflows can happen) +# when compiled with -O2. One mitigation I have found is to turn off these +# particular optimisations. Since GCC 4.3.2 will be around for a long time, +# we have to leave in -fno-tree-vrp and -fno-strict-overflow for a long time too. + common_cflags="-Wall -ggdb3 -Isupport -fno-strict-aliasing" TOCK_CFLAGS="$gnu89_inline $CPPFLAGS $CFLAGS $common_cflags $CCSP_CFLAGS $GLIB_CFLAGS" diff --git a/rangetest.c b/rangetest.c new file mode 100644 index 0000000..df47951 --- /dev/null +++ b/rangetest.c @@ -0,0 +1,102 @@ +int g_stopped; + +#define occam_stop(pos, nargs, format, args...) do { g_stopped = 1; } while (0) + +#include "support/tock_support.h" + +#define report_failure(msg, args...) { printf(msg, ##args); } + +#define testf(call) do { \ + g_stopped = 0; \ + call; \ + if (g_stopped == 1) { \ + passes++; \ + } else { \ + failures++; \ + report_failure(#call " failed, expected to stop\n"); \ + } \ + } while(0) + +#define testp(exp, call) do { \ + g_stopped = 0; \ + if (exp == call) { \ + if (g_stopped == 0) { \ + passes++; \ + } else { \ + failures++; \ + report_failure(#call "failed, unexpectedly stopped\n"); \ + } \ + } else { \ + failures++; \ + if (g_stopped == 1) { \ + report_failure(#call "failed, unexpectedly stopped\n"); \ + } else { \ + report_failure(#call " failed, expected %d, got %d\n", exp, call); \ + } \ + } \ + } while (0) + +#define test_commutative(t,f) \ + do {int done_x = 0; for (t x = 0; !(x == 0 && done_x == 1);x++) { done_x = 1;\ + int done_y = 0; for (t y = 0; !(y == x && done_y == 1);y++) { done_y = 1;\ + g_stopped = 0; \ + const t r0 = f(x,y,""); \ + const int stopped_earlier = g_stopped; \ + g_stopped = 0; \ + const t r1 = f(y,x,""); \ + const int stopped_later = g_stopped; \ + if ((stopped_later == 1 && stopped_earlier == 1) || \ + (stopped_earlier == 0 && stopped_later == 0 && r0 == r1)) { \ + \ + } else { \ + failures++; \ + report_failure(#f " failed, non-commutative with %d, %d (stop: %d, %d) (res: %d, %d)\n", \ + (int)x, (int)y, stopped_earlier, stopped_later, r0, r1); \ + goto comm_label_##f; \ + } \ + } \ + }passes++; comm_label_##f:;} while (0) + + + +int main(int argc, char** argv) +{ + int passes = 0; + int failures = 0; + + //Since we test commutativity (at least for 8- and 16-bits), + //we only need to test one arrangement of each addition + //and multiplication test + + testp(2,occam_add_int8_t(1,1,"")); + testp(127,occam_add_int8_t(64,63,"")); + testf(occam_add_int8_t(64,64,"")); + testp(-1,occam_add_int8_t(127,-128,"")); + testp(-1,occam_add_int8_t(-1,0,"")); + testp(-128,occam_add_int8_t(-128,0,"")); + + testf(occam_mul_int8_t(127,127,"")); + testf(occam_mul_int8_t(2,127,"")); + testf(occam_mul_int8_t(127,127,"")); + testf(occam_mul_int8_t(127,-128,"")); + testf(occam_mul_int8_t(-128,-128,"")); + testf(occam_mul_int8_t(-1,-128,"")); + testp(-128,occam_mul_int8_t(1,-128,"")); + + + test_commutative(int8_t,occam_add_int8_t); + test_commutative(int8_t,occam_mul_int8_t); + + testp(-32768,occam_add_int16_t(-32768,0,"")); + testf(occam_add_int16_t(-1,-32768,"")); + testp(32767,occam_add_int16_t(0,32767,"")); + + test_commutative(int16_t,occam_add_int16_t); + test_commutative(int16_t,occam_mul_int16_t); + + //TODO test uint8_t as well + + printf("Tests complete, passed: %d, failed: %d\n", passes, failures); + + return -failures; +}