public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, committed] Add test of handling arithmetic-overflow from JIT
@ 2015-01-01  0:00 David Malcolm
  0 siblings, 0 replies; only message in thread
From: David Malcolm @ 2015-01-01  0:00 UTC (permalink / raw)
  To: jit, gcc-patches; +Cc: David Malcolm

New testcase to verify that libgccjit client code can handle arithmeti
overflow.

This testcase brings jit.sum from:
  # of expected passes        5158
to:
  # of expected passes        6121

Committed to trunk as r219320.

FWIW my motivation for this testcase was due to implementing
"INT_*_OVF" operations within an experimental backend for PyPy I'm
hacking on:
  https://bitbucket.org/pypy/pypy/branch/libgccjit-backend
where I hope to use libgccjit within PyPy's JIT for turning traced
loops into machine code; the commit in question there was:
 https://bitbucket.org/pypy/pypy/commits/dfab06318973a8b8a5393708519269280dab395e

gcc/testsuite/ChangeLog:
	* jit.dg/test-arith-overflow.c: New test case.
	* jit.dg/all-non-failing-tests.h: Add test-arith-overflow.c.
	* jit.dg/test-combination.c (create_code): Likewise.
	(verify_code): Likewise.
	* jit.dg/test-threads.c (testcases): Likewise.
---
 gcc/testsuite/jit.dg/all-non-failing-tests.h |   7 +
 gcc/testsuite/jit.dg/test-arith-overflow.c   | 223 +++++++++++++++++++++++++++
 gcc/testsuite/jit.dg/test-combination.c      |   2 +
 gcc/testsuite/jit.dg/test-threads.c          |   3 +
 4 files changed, 235 insertions(+)
 create mode 100644 gcc/testsuite/jit.dg/test-arith-overflow.c

diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 10d7199..beb3d13 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -22,6 +22,13 @@
 #undef create_code
 #undef verify_code
 
+/* test-arith-overflow.c */
+#define create_code create_code_arith_overflow
+#define verify_code verify_code_arith_overflow
+#include "test-arith-overflow.c"
+#undef create_code
+#undef verify_code
+
 /* test-array-as-pointer.c */
 #define create_code create_code_array_as_pointer
 #define verify_code verify_code_array_as_pointer
diff --git a/gcc/testsuite/jit.dg/test-arith-overflow.c b/gcc/testsuite/jit.dg/test-arith-overflow.c
new file mode 100644
index 0000000..8d130b2
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-arith-overflow.c
@@ -0,0 +1,223 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+static void
+create_overflow_fn (gcc_jit_context *ctxt,
+		    gcc_jit_type *type,
+		    const char *funcname,
+		    const char *builtin_name)
+{
+  /* Create the equivalent of this C:
+
+       int
+       test_overflow_T_OP (T x, T y, int *ovf)
+       {
+	 T result;
+	 result = x OP y;
+	 *ovf = ...; // did overflow happen?
+	 return result;
+       }
+
+  */
+  gcc_jit_type *t_bool =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+  gcc_jit_type *t_bool_star =
+    gcc_jit_type_get_pointer (t_bool);
+
+  gcc_jit_param *x =
+    gcc_jit_context_new_param (
+      ctxt,
+      NULL,
+      type, "x");
+  gcc_jit_param *y =
+    gcc_jit_context_new_param (
+      ctxt,
+      NULL,
+      type, "y");
+  gcc_jit_param *ovf =
+    gcc_jit_context_new_param (
+      ctxt,
+      NULL,
+      t_bool_star, "ovf");
+  gcc_jit_param *params[3] = {x, y, ovf};
+
+  gcc_jit_function *func =
+    gcc_jit_context_new_function (ctxt,
+				  NULL,
+				  GCC_JIT_FUNCTION_EXPORTED,
+				  type,
+				  funcname,
+				  3, params, 0);
+
+  gcc_jit_lvalue *result =
+    gcc_jit_function_new_local (func, NULL, type, "result");
+
+  gcc_jit_block *b_initial =
+    gcc_jit_function_new_block (func, "initial");
+
+  /* The builtins are listed in builtins.def as being variadic, but
+     the have these signatures:
+       bool __builtin_add_overflow (type1 a, type2 b, type3 *res);
+       bool __builtin_sub_overflow (type1 a, type2 b, type3 *res);
+       bool __builtin_mul_overflow (type1 a, type2 b, type3 *res);  */
+
+  gcc_jit_function *builtin_fn =
+    gcc_jit_context_get_builtin_function (ctxt, builtin_name);
+
+  /* Construct a call of the form:
+       (returns bool) __builtin_add_overflow (x, y, &result).  */
+  gcc_jit_rvalue *args[3] = {gcc_jit_param_as_rvalue (x),
+			     gcc_jit_param_as_rvalue (y),
+			     gcc_jit_lvalue_get_address (result, NULL)};
+  gcc_jit_rvalue *call =
+    gcc_jit_context_new_call (ctxt,
+			      NULL,
+			      builtin_fn,
+			      3, args);
+
+  /* "*ovf = BUILTIN_CALL ();" */
+  gcc_jit_block_add_assignment (
+    b_initial, NULL,
+    gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (ovf),
+				NULL),
+    call);
+
+  /* "return result;" */
+  gcc_jit_block_end_with_return (
+    b_initial, NULL,
+    gcc_jit_lvalue_as_rvalue (result));
+}
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* int */
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  create_overflow_fn (ctxt, int_type,
+		      "test_overflow_int_add",
+		      "__builtin_add_overflow");
+  create_overflow_fn (ctxt, int_type,
+		      "test_overflow_int_sub",
+		      "__builtin_sub_overflow");
+  create_overflow_fn (ctxt, int_type,
+		      "test_overflow_int_mul",
+		      "__builtin_mul_overflow");
+
+  /* uint */
+  gcc_jit_type *uint_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_INT);
+  create_overflow_fn (ctxt, uint_type,
+		      "test_overflow_uint_add",
+		      "__builtin_add_overflow");
+  create_overflow_fn (ctxt, uint_type,
+		      "test_overflow_uint_sub",
+		      "__builtin_sub_overflow");
+  create_overflow_fn (ctxt, uint_type,
+		      "test_overflow_uint_mul",
+		      "__builtin_mul_overflow");
+}
+
+void
+verify_int_overflow_fn (gcc_jit_result *jit_result,
+			const char *funcname,
+			int x, int y,
+			int expected_result,
+			int expected_ovf)
+{
+  CHECK_NON_NULL (jit_result);
+  typedef int (*overflow_fn_type) (int, int, int *);
+  overflow_fn_type fn =
+    (overflow_fn_type)gcc_jit_result_get_code (jit_result, funcname);
+  CHECK_NON_NULL (fn);
+
+  /* Call the function:  */
+  int actual_ovf = 0;
+  int actual_result = fn (x, y, &actual_ovf);
+  note ("%s (%d, %d) returned: %d with ovf: %d",
+	funcname, x, y, actual_result, actual_ovf);
+  CHECK_VALUE (actual_result, expected_result);
+  CHECK_VALUE (actual_ovf, expected_ovf);
+}
+
+void
+verify_uint_overflow_fn (gcc_jit_result *jit_result,
+			 const char *funcname,
+			 unsigned int x, unsigned int y,
+			 unsigned int expected_result,
+			 int expected_ovf)
+{
+  CHECK_NON_NULL (jit_result);
+  typedef unsigned int (*overflow_fn_type) (unsigned int, unsigned int, int *);
+  overflow_fn_type fn =
+    (overflow_fn_type)gcc_jit_result_get_code (jit_result, funcname);
+  CHECK_NON_NULL (fn);
+
+  /* Call the function:  */
+  int actual_ovf = 0;
+  unsigned int actual_result = fn (x, y, &actual_ovf);
+  note ("%s (%d, %d) returned: %d with ovf: %d",
+	funcname, x, y, actual_result, actual_ovf);
+  CHECK_VALUE (actual_result, expected_result);
+  CHECK_VALUE (actual_ovf, expected_ovf);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  verify_int_overflow_fn (result, "test_overflow_int_add",
+			  5, 15,
+			  20, 0);
+  verify_int_overflow_fn (result, "test_overflow_int_add",
+			  INT_MAX, 1,
+			  INT_MIN, 1);
+  verify_int_overflow_fn (result, "test_overflow_int_sub",
+			  5, 15,
+			  -10, 0);
+  verify_int_overflow_fn (result, "test_overflow_int_sub",
+			  INT_MIN, 1,
+			  INT_MAX, 1);
+  verify_int_overflow_fn (result, "test_overflow_int_mul",
+			  5, 15,
+			  75, 0);
+  verify_int_overflow_fn (result, "test_overflow_int_mul",
+			  INT_MAX, 1,
+			  INT_MAX, 0);
+  verify_int_overflow_fn (result, "test_overflow_int_mul",
+			  INT_MAX, 2,
+			  -2, 1);
+
+  verify_uint_overflow_fn (result, "test_overflow_uint_add",
+			   5, 15,
+			   20, 0);
+  verify_uint_overflow_fn (result, "test_overflow_uint_add",
+			   INT_MAX, 1,
+			   (((unsigned int)INT_MAX) + 1), 0);
+  verify_uint_overflow_fn (result, "test_overflow_uint_add",
+			   UINT_MAX, 1,
+			   0, 1);
+  verify_uint_overflow_fn (result, "test_overflow_uint_sub",
+			   5, 15,
+			   (UINT_MAX - 9), 1);
+  verify_uint_overflow_fn (result, "test_overflow_uint_sub",
+			   INT_MIN, 1,
+			   ((unsigned int)INT_MIN - 1), 0);
+  verify_uint_overflow_fn (result, "test_overflow_uint_mul",
+			   5, 15,
+			   75, 0);
+  verify_uint_overflow_fn (result, "test_overflow_uint_mul",
+			   INT_MAX, 1,
+			   INT_MAX, 0);
+  verify_uint_overflow_fn (result, "test_overflow_uint_mul",
+			   INT_MAX, 2,
+			   (unsigned int)INT_MAX * 2, 0);
+  verify_uint_overflow_fn (result, "test_overflow_uint_mul",
+			   UINT_MAX, 2,
+			   -2/*(unsigned int)INT_MAX * 2*/, 1);
+}
diff --git a/gcc/testsuite/jit.dg/test-combination.c b/gcc/testsuite/jit.dg/test-combination.c
index 06ba902..e99f4d0 100644
--- a/gcc/testsuite/jit.dg/test-combination.c
+++ b/gcc/testsuite/jit.dg/test-combination.c
@@ -17,6 +17,7 @@ create_code (gcc_jit_context *ctxt, void * user_data)
 {
   create_code_accessing_struct (ctxt, user_data);
   create_code_accessing_union (ctxt, user_data);
+  create_code_arith_overflow (ctxt, user_data);
   create_code_array_as_pointer (ctxt, user_data);
   create_code_arrays (ctxt, user_data);
   create_code_calling_external_function (ctxt, user_data);
@@ -44,6 +45,7 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
 {
   verify_code_accessing_struct (ctxt, result);
   verify_code_accessing_union (ctxt, result);
+  verify_code_arith_overflow (ctxt, result);
   verify_code_array_as_pointer (ctxt, result);
   verify_code_arrays (ctxt, result);
   verify_code_calling_external_function (ctxt, result);
diff --git a/gcc/testsuite/jit.dg/test-threads.c b/gcc/testsuite/jit.dg/test-threads.c
index 7c248cc..cd5ef6a 100644
--- a/gcc/testsuite/jit.dg/test-threads.c
+++ b/gcc/testsuite/jit.dg/test-threads.c
@@ -107,6 +107,9 @@ const struct testcase testcases[] = {
   {"accessing_union",
    create_code_accessing_union,
    verify_code_accessing_union},
+  {"arith_overflow",
+   create_code_arith_overflow,
+   verify_code_arith_overflow},
   {"array_as_pointer",
    create_code_array_as_pointer,
    verify_code_array_as_pointer},
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-01-07 20:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-01  0:00 [PATCH, committed] Add test of handling arithmetic-overflow from JIT David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).