[MLton-devel] cvs commit: overflow detection in C codegen
Stephen Weeks
sweeks@users.sourceforge.net
Thu, 21 Nov 2002 18:48:20 -0800
sweeks 02/11/21 18:48:20
Modified: include ccodegen.h
mlton/codegen/c-codegen c-codegen.fun
Log:
Put in place four different ways of implementing arithmetic ops in the
C codegen, controlled by a -D switch to mlton:
-DINT_JO
jo to MLton_overflow after each arithop, just like the old
-DFAST_INT
-DINT_NO_CHECK
no overflow checking, like -detect-overflow false
-DINT_LONG
use static inline functions that work with long longs
-DINT_TEST
use 32-bit compares and arithops to check for overflow
INT_JO and INT_NO_CHECK do not follow the spec, while INT_LONG and
INT_TEST do.
In terms of running time of generated code,
INT_NO_CHECK <= INT_JO <= INT_TEST <= INT_LONG
I'll send benchmarks later.
The default is to use INT_TEST.
Revision Changes Path
1.40 +150 -48 mlton/include/ccodegen.h
Index: ccodegen.h
===================================================================
RCS file: /cvsroot/mlton/mlton/include/ccodegen.h,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- ccodegen.h 7 Nov 2002 19:15:05 -0000 1.39
+++ ccodegen.h 22 Nov 2002 02:48:20 -0000 1.40
@@ -375,45 +375,171 @@
/* Int */
/* ------------------------------------------------- */
-#define Int_add(n1, n2) ((n1) + (n2))
-#define Int_mul(n1, n2) ((n1) * (n2))
-#define Int_sub(n1, n2) ((n1) - (n2))
+/* The old -DFAST_INT has been renamed to -DINT_JO. */
+#if (defined (FAST_INT))
+#define INT_JO
+#endif
+
+/* The default is to use INT_TEST. */
+#if (! defined (INT_NO_CHECK) && ! defined (INT_JO) && ! defined (INT_TEST) && ! defined (INT_LONG))
+#define INT_TEST
+#endif
+
+enum {
+ MAXINT = 0x7FFFFFFF,
+ MININT = (int)0x80000000,
+ MAXWORD = 0xFFFFFFFF,
+};
+
+#if (defined (INT_NO_CHECK))
+#define Int_addCheck(dst, n1, n2, l) dst = n1 + n2
+#define Int_mulCheck(dst, n1, n2, l) dst = n1 * n2
+#define Int_negCheck(dst, n, l) dst = -n
+#define Int_subCheck(dst, n1, n2, l) dst = n1 - n2
+#define Word32_addCheck(dst, n1, n2, l) dst = n1 + n2
+#define Word32_mulCheck(dst, n1, n2, l) dst = n1 * n2
+#endif
+
+#if (defined (INT_TEST))
+#define Int_addCheckXC(dst, x, c, l) \
+ do { \
+ if (c >= 0) { \
+ if (x > MAXINT - c) \
+ goto l; \
+ } else if (x < MININT - c) \
+ goto l; \
+ dst = x + c; \
+ } while (0)
+#define Int_addCheckCX(dst, c, x, l) Int_addCheckXC(dst, x, c, l)
+#define Int_subCheckCX(dst, c, x, l) \
+ do { \
+ if (c >= 0) { \
+ if (x < c - MAXINT) \
+ goto l; \
+ } else if (x > c - MININT) \
+ goto l; \
+ dst = c - x; \
+ } while (0)
+#define Int_subCheckXC(dst, x, c, l) \
+ do { \
+ if (c <= 0) { \
+ if (x > MAXINT + c) \
+ goto l; \
+ } else if (x < MININT + c) \
+ goto l; \
+ dst = x - c; \
+ } while (0)
+#define Word32_addCheckXC(dst, x, c, l) \
+ do { \
+ if (x > MAXWORD - c) \
+ goto l; \
+ dst = x + c; \
+ } while (0)
+#define Word32_addCheckCX(dst, c, x, l) Word32_addCheckXC(dst, x, c, l)
+
+#define Int_addCheck Int_addCheckXC
+#define Int_subCheck Int_subCheckXC
+#define Word32_addCheck Word32_addCheckXC
+
+#endif
-#ifdef FAST_INT
+static inline Int Int_addOverflow(Int lhs, Int rhs, Bool *overflow) {
+ long long tmp;
+
+ tmp = (long long)lhs + rhs;
+ *overflow = (tmp != (int)tmp);
+ return tmp;
+}
+static inline Int Int_mulOverflow(Int lhs, Int rhs, Bool *overflow) {
+ long long tmp;
+
+ tmp = (long long)lhs * rhs;
+ *overflow = (tmp != (int)tmp);
+ return tmp;
+}
+static inline Int Int_subOverflow(Int lhs, Int rhs, Bool *overflow) {
+ long long tmp;
+
+ tmp = (long long)lhs - rhs;
+ *overflow = (tmp != (int)tmp);
+ return tmp;
+}
+
+#if (defined (INT_TEST) || defined (INT_LONG))
+#define check(dst, n1, n2, l, f); \
+ do { \
+ int overflow; \
+ dst = f(n1, n2, &overflow); \
+ if (FALSE) \
+ fprintf(stderr, #f "(%d, %d) = %d\n", n1, n2, dst); \
+ if (overflow) { \
+ if (FALSE) \
+ fprintf(stderr, "overflow\n"); \
+ goto l; \
+ } \
+ } while (0)
+#define Int_mulCheck(dst, n1, n2, l) \
+ check(dst, n1, n2, l, Int_mulOverflow)
+#define Int_negCheck(dst, n, l) \
+ do { \
+ if (n == MININT) \
+ goto l; \
+ dst = -n; \
+ } while (0)
+#define Word32_mulCheck(dst, n1, n2, l) \
+ check(dst, n1, n2, l, Word32_mulOverflow)
+#endif
-static void MLton_overflow() {
+#if (defined (INT_LONG))
+#define Int_addCheck(dst, n1, n2, l) \
+ check(dst, n1, n2, l, Int_addOverflow)
+#define Int_subCheck(dst, n1, n2, l) \
+ check(dst, n1, n2, l, Int_subOverflow)
+#define Word32_addCheck(dst, n1, n2, l) \
+ check(dst, n1, n2, l, Word32_addOverflow)
+#endif
+
+#if (defined (INT_JO))
+
+static void MLton_overflow () {
die("Internal overflow detected. Halt.");
}
-static inline Int Int_addCheckFast(Int n1, Int n2) {
+static inline Int Int_addCheckFast (Int n1, Int n2) {
__asm__ __volatile__ ("addl %1, %0\n\tjo MLton_overflow"
: "+r" (n1) : "g" (n2) : "cc");
return n1;
}
-static inline Int Int_mulCheckFast(Int n1, Int n2) {
+static inline Int Int_mulCheckFast (Int n1, Int n2) {
__asm__ __volatile__ ("imull %1, %0\n\tjo MLton_overflow"
: "+r" (n1) : "g" (n2) : "cc");
return n1;
}
-static inline Int Int_subCheckFast(Int n1, Int n2) {
+static inline Int Int_negCheckFast (Int n) {
+ __asm__ __volatile__ ("negl %1\n\tjo MLton_overflow"
+ : "+r" (n) : : "cc" );
+ return n;
+}
+
+static inline Int Int_subCheckFast (Int n1, Int n2) {
__asm__ __volatile__ ("subl %1, %0\n\tjo MLton_overflow"
: "+r" (n1) : "g" (n2) : "cc" );
return n1;
}
-static inline Word Word32_addCheckFast(Word n1, Word n2) {
+static inline Word Word32_addCheckFast (Word n1, Word n2) {
__asm__ __volatile__ ("addl %1, %0\n\tjc MLton_overflow"
: "+r" (n1) : "g" (n2) : "cc");
return n1;
}
-static inline Word Word32_mulCheckFast(Word n1, Word n2) {
+static inline Word Word32_mulCheckFast (Word n1, Word n2) {
__asm__ __volatile__ ("imull %1, %0\n\tjc MLton_overflow"
: "+r" (n1) : "g" (n2) : "cc");
@@ -426,6 +552,8 @@
check(dst, n1, n2, l, Int_addCheckFast)
#define Int_mulCheck(dst, n1, n2, l) \
check(dst, n1, n2, l, Int_mulCheckFast)
+#define Int_negCheck(dst, n, l) \
+ dst = Int_negCheckFast(n)
#define Int_subCheck(dst, n1, n2, l) \
check(dst, n1, n2, l, Int_subCheckFast)
#define Word32_addCheck(dst, n1, n2, l) \
@@ -433,46 +561,20 @@
#define Word32_mulCheck(dst, n1, n2, l) \
check(dst, n1, n2, l, Word32_mulCheckFast)
-static inline Int Int_negCheckFast(Int n) {
- __asm__ __volatile__ ("negl %1\n\tjo MLton_overflow"
- : "+r" (n) : : "cc" );
- return n;
-}
-#define Int_negCheck(dst, n, l) dst = Int_negCheckFast(n)
-#define Int_rem(x, y) ((x)%(y))
+#endif
-#else /* no FAST_INT */
+#if (defined (INT_NO_CHECK) || defined (INT_JO) || defined (INT_LONG))
+#define Int_addCheckCX Int_addCheck
+#define Int_addCheckXC Int_addCheck
+#define Int_subCheckCX Int_subCheck
+#define Int_subCheckXC Int_subCheck
+#define Word32_addCheckCX Word32_addCheck
+#define Word32_addCheckXC Word32_addCheck
+#endif
-int Int_bogus;
-#define check(dst, n1, n2, l, f); \
- do { \
- int overflow; \
- dst = f(n1, n2, &overflow); \
- if (FALSE) \
- fprintf(stderr, #f "(%d, %d) = %d\n", n1, n2, dst); \
- if (overflow) { \
- if (FALSE) \
- fprintf(stderr, "overflow\n"); \
- goto l; \
- } \
- } while (0)
-#define Int_addCheck(dst, n1, n2, l) \
- check(dst, n1, n2, l, Int_addOverflow)
-#define Int_mulCheck(dst, n1, n2, l) \
- check(dst, n1, n2, l, Int_mulOverflow)
-#define Int_subCheck(dst, n1, n2, l) \
- check(dst, n1, n2, l, Int_subOverflow)
-#define Word32_addCheck(dst, n1, n2, l) \
- check(dst, n1, n2, l, Word32_addOverflow)
-#define Word32_mulCheck(dst, n1, n2, l) \
- check(dst, n1, n2, l, Word32_mulOverflow)
-#define Int_negCheck(dst, n, l) \
- do { \
- int overflow; \
- dst = Int_negOverflow(n, &overflow); \
- if (overflow) goto l; \
- } while (0)
-#endif /* FAST_INT */
+#define Int_add(n1, n2) ((n1) + (n2))
+#define Int_mul(n1, n2) ((n1) * (n2))
+#define Int_sub(n1, n2) ((n1) - (n2))
#define Int_lt(n1, n2) ((n1) < (n2))
#define Int_le(n1, n2) ((n1) <= (n2))
#define Int_gt(n1, n2) ((n1) > (n2))
1.33 +24 -3 mlton/mlton/codegen/c-codegen/c-codegen.fun
Index: c-codegen.fun
===================================================================
RCS file: /cvsroot/mlton/mlton/mlton/codegen/c-codegen/c-codegen.fun,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- c-codegen.fun 2 Nov 2002 03:37:39 -0000 1.32
+++ c-codegen.fun 22 Nov 2002 02:48:20 -0000 1.33
@@ -616,13 +616,34 @@
val prim =
let
datatype z = datatype Prim.Name.t
+ fun const i =
+ case Vector.sub (args, i) of
+ Operand.Int _ => true
+ | _ => false
+ fun const0 () = const 0
+ fun const1 () = const 1
in
case Prim.name prim of
- Int_addCheck => "\tInt_addCheck"
+ Int_addCheck =>
+ if const0 ()
+ then "\tInt_addCheckCX"
+ else if const1 ()
+ then "\tInt_addCheckXC"
+ else "\tInt_addCheck"
| Int_mulCheck => "\tInt_mulCheck"
| Int_negCheck => "\tInt_negCheck"
- | Int_subCheck => "\tInt_subCheck"
- | Word32_addCheck => "\tWord32_addCheck"
+ | Int_subCheck =>
+ if const0 ()
+ then "\tInt_subCheckCX"
+ else if const1 ()
+ then "\tInt_subCheckXC"
+ else "\tInt_subCheck"
+ | Word32_addCheck =>
+ if const0 ()
+ then "\tWord32_addCheckCX"
+ else if const1 ()
+ then "\tWord32_addCheckXC"
+ else "\tWord32_addCheck"
| Word32_mulCheck => "\tWord32_mulCheck"
| _ => Error.bug "strange overflow prim"
end
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
MLton-devel mailing list
MLton-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlton-devel