From 8e9b2773979616d97a18977bb2fb8cab75fd1e60 Mon Sep 17 00:00:00 2001 From: Ilya Enkovich Date: Mon, 1 Jun 2015 11:24:07 +0000 Subject: [PATCH] re PR target/65527 (ICE: in expand_builtin_with_bounds, at builtins.c:7120 with -fcheck-pointer-bounds -mmpx) gcc/ PR target/65527 * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Add redirection for instrumented calls. * lto-wrapper.c (merge_and_complain): Merge -fcheck-pointer-bounds. (append_compiler_options): Append -fcheck-pointer-bounds. * tree-chkp.h (chkp_copy_call_skip_bounds): New. (chkp_redirect_edge): New. * tree-chkp.c (chkp_copy_call_skip_bounds): New. (chkp_redirect_edge): New. gcc/testsuite/ PR target/65527 * gcc.target/i386/mpx/chkp-fix-calls-1.c: New. * gcc.target/i386/mpx/chkp-fix-calls-2.c: New. * gcc.target/i386/mpx/chkp-fix-calls-3.c: New. * gcc.target/i386/mpx/chkp-fix-calls-4.c: New. From-SVN: r223929 --- gcc/ChangeLog | 12 ++++ gcc/cgraph.c | 25 +++++-- gcc/lto-wrapper.c | 2 + gcc/testsuite/ChangeLog | 8 +++ .../gcc.target/i386/mpx/chkp-fix-calls-1.c | 16 +++++ .../gcc.target/i386/mpx/chkp-fix-calls-2.c | 16 +++++ .../gcc.target/i386/mpx/chkp-fix-calls-3.c | 33 ++++++++++ .../gcc.target/i386/mpx/chkp-fix-calls-4.c | 17 +++++ gcc/tree-chkp.c | 65 +++++++++++++++++++ gcc/tree-chkp.h | 2 + 10 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-1.c create mode 100644 gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-2.c create mode 100644 gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-3.c create mode 100644 gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-4.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4b007b4a0e0..d61b465bdb2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2015-06-01 Ilya Enkovich + + PR target/65527 + * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): Add + redirection for instrumented calls. + * lto-wrapper.c (merge_and_complain): Merge -fcheck-pointer-bounds. + (append_compiler_options): Append -fcheck-pointer-bounds. + * tree-chkp.h (chkp_copy_call_skip_bounds): New. + (chkp_redirect_edge): New. + * tree-chkp.c (chkp_copy_call_skip_bounds): New. + (chkp_redirect_edge): New. + 2015-06-01 Richard Biener PR tree-optimization/66280 diff --git a/gcc/cgraph.c b/gcc/cgraph.c index dc7d3a74e1f..6a674db4078 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1281,6 +1281,7 @@ cgraph_edge::redirect_call_stmt_to_callee (void) tree lhs = gimple_call_lhs (e->call_stmt); gcall *new_stmt; gimple_stmt_iterator gsi; + bool skip_bounds = false; #ifdef ENABLE_CHECKING cgraph_node *node; #endif @@ -1389,8 +1390,16 @@ cgraph_edge::redirect_call_stmt_to_callee (void) } } + /* We might propagate instrumented function pointer into + not instrumented function and vice versa. In such a + case we need to either fix function declaration or + remove bounds from call statement. */ + if (flag_check_pointer_bounds && e->callee) + skip_bounds = chkp_redirect_edge (e); + if (e->indirect_unknown_callee - || decl == e->callee->decl) + || (decl == e->callee->decl + && !skip_bounds)) return e->call_stmt; #ifdef ENABLE_CHECKING @@ -1415,13 +1424,19 @@ cgraph_edge::redirect_call_stmt_to_callee (void) } } - if (e->callee->clone.combined_args_to_skip) + if (e->callee->clone.combined_args_to_skip + || skip_bounds) { int lp_nr; - new_stmt - = gimple_call_copy_skip_args (e->call_stmt, - e->callee->clone.combined_args_to_skip); + new_stmt = e->call_stmt; + if (e->callee->clone.combined_args_to_skip) + new_stmt + = gimple_call_copy_skip_args (new_stmt, + e->callee->clone.combined_args_to_skip); + if (skip_bounds) + new_stmt = chkp_copy_call_skip_bounds (new_stmt); + gimple_call_set_fndecl (new_stmt, e->callee->decl); gimple_call_set_fntype (new_stmt, gimple_call_fntype (e->call_stmt)); diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index 11bf9ad0639..d59bd8c6635 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -273,6 +273,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options, case OPT_fwrapv: case OPT_fopenmp: case OPT_fopenacc: + case OPT_fcheck_pointer_bounds: /* For selected options we can merge conservatively. */ for (j = 0; j < *decoded_options_count; ++j) if ((*decoded_options)[j].opt_index == foption->opt_index) @@ -503,6 +504,7 @@ append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts, case OPT_Ofast: case OPT_Og: case OPT_Os: + case OPT_fcheck_pointer_bounds: break; default: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 239cf4908c7..fab0df2e41a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2015-06-01 Ilya Enkovich + + PR target/65527 + * gcc.target/i386/mpx/chkp-fix-calls-1.c: New. + * gcc.target/i386/mpx/chkp-fix-calls-2.c: New. + * gcc.target/i386/mpx/chkp-fix-calls-3.c: New. + * gcc.target/i386/mpx/chkp-fix-calls-4.c: New. + 2015-06-01 Alan Lawrence * gcc.target/aarch64/advsimd-intrinsics/advsimd-intrinsics.exp: Pass diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-1.c b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-1.c new file mode 100644 index 00000000000..cb4d22984b6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fcheck-pointer-bounds -mmpx" } */ + +#include "math.h" + +double +test1 (double x, double y, double (*fn)(double, double)) +{ + return fn (x, y); +} + +double +test2 (double x, double y) +{ + return test1 (x, y, copysign); +} diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-2.c b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-2.c new file mode 100644 index 00000000000..951e7dece19 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fcheck-pointer-bounds -mmpx -fno-inline" } */ + +#include "math.h" + +double +test1 (double x, double y, double (*fn)(double, double)) +{ + return fn (x, y); +} + +double +test2 (double x, double y) +{ + return test1 (x, y, copysign); +} diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-3.c b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-3.c new file mode 100644 index 00000000000..439f631a3b9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-3.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fexceptions -fcheck-pointer-bounds -mmpx" } */ + +extern int f2 (const char*, int, ...); +extern long int f3 (int *); +extern void err (void) __attribute__((__error__("error"))); + +extern __inline __attribute__ ((__always_inline__)) int +f1 (int i, ...) +{ + if (__builtin_constant_p (i)) + { + if (i) + err (); + return f2 ("", i); + } + + return f2 ("", i); +} + +int +test () +{ + int i; + + if (f1 (0)) + if (f3 (&i)) + i = 0; + + return i; +} + + diff --git a/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-4.c b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-4.c new file mode 100644 index 00000000000..1b7d7032ecb --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/mpx/chkp-fix-calls-4.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -fcheck-pointer-bounds -mmpx" } */ + +typedef void (func) (int *); + +static inline void +bar (func f) +{ + int i; + f (&i); +} + +void +foo () +{ + bar (0); +} diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c index 88c1f459c18..015df1139c7 100644 --- a/gcc/tree-chkp.c +++ b/gcc/tree-chkp.c @@ -529,6 +529,71 @@ chkp_insert_retbnd_call (tree bndval, tree retval, return bndval; } +/* Build a GIMPLE_CALL identical to CALL but skipping bounds + arguments. */ + +gcall * +chkp_copy_call_skip_bounds (gcall *call) +{ + bitmap bounds; + unsigned i; + + bitmap_obstack_initialize (NULL); + bounds = BITMAP_ALLOC (NULL); + + for (i = 0; i < gimple_call_num_args (call); i++) + if (POINTER_BOUNDS_P (gimple_call_arg (call, i))) + bitmap_set_bit (bounds, i); + + if (!bitmap_empty_p (bounds)) + call = gimple_call_copy_skip_args (call, bounds); + gimple_call_set_with_bounds (call, false); + + BITMAP_FREE (bounds); + bitmap_obstack_release (NULL); + + return call; +} + +/* Redirect edge E to the correct node according to call_stmt. + Return 1 if bounds removal from call_stmt should be done + instead of redirection. */ + +bool +chkp_redirect_edge (cgraph_edge *e) +{ + bool instrumented = false; + tree decl = e->callee->decl; + + if (e->callee->instrumentation_clone + || chkp_function_instrumented_p (decl)) + instrumented = true; + + if (instrumented + && !gimple_call_with_bounds_p (e->call_stmt)) + e->redirect_callee (cgraph_node::get_create (e->callee->orig_decl)); + else if (!instrumented + && gimple_call_with_bounds_p (e->call_stmt) + && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDCL) + && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDCU) + && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDSTX)) + { + if (e->callee->instrumented_version) + e->redirect_callee (e->callee->instrumented_version); + else + { + tree args = TYPE_ARG_TYPES (TREE_TYPE (decl)); + /* Avoid bounds removal if all args will be removed. */ + if (!args || TREE_VALUE (args) != void_type_node) + return true; + else + gimple_call_set_with_bounds (e->call_stmt, false); + } + } + + return false; +} + /* Mark statement S to not be instrumented. */ static void chkp_mark_stmt (gimple s) diff --git a/gcc/tree-chkp.h b/gcc/tree-chkp.h index 1bafe994da2..b5ab56252ed 100644 --- a/gcc/tree-chkp.h +++ b/gcc/tree-chkp.h @@ -56,5 +56,7 @@ extern bool chkp_gimple_call_builtin_p (gimple call, extern void chkp_expand_bounds_reset_for_mem (tree mem, tree ptr); extern tree chkp_insert_retbnd_call (tree bndval, tree retval, gimple_stmt_iterator *gsi); +extern gcall *chkp_copy_call_skip_bounds (gcall *call); +extern bool chkp_redirect_edge (cgraph_edge *e); #endif /* GCC_TREE_CHKP_H */ -- 2.30.2