[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