diff options
author | David Malcolm <dmalcolm@gcc.gnu.org> | 2015-01-08 01:09:14 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2015-01-08 01:09:14 +0000 |
commit | 605f96ba2d17d8c9f265ee7c5781ed03cc6d8135 (patch) | |
tree | 08ef9268ffbbc311501b65468f2d5f46df0aca04 /gcc | |
parent | c211cd236cb0b4cda31657cd96668aace2e8e4ac (diff) | |
download | gcc-605f96ba2d17d8c9f265ee7c5781ed03cc6d8135.zip gcc-605f96ba2d17d8c9f265ee7c5781ed03cc6d8135.tar.gz gcc-605f96ba2d17d8c9f265ee7c5781ed03cc6d8135.tar.bz2 |
Add new jit testcase accidentally omitted from r219320
From-SVN: r219334
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/jit.dg/test-arith-overflow.c | 223 |
1 files changed, 223 insertions, 0 deletions
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); +} |