mirror of git://gcc.gnu.org/git/gcc.git
tree-chkp-opt.c (chkp_get_nobnd_fndecl): New.
gcc/ * tree-chkp-opt.c (chkp_get_nobnd_fndecl): New. (chkp_get_nochk_fndecl): New. (chkp_optimize_string_function_calls): New. (chkp_opt_execute): Call chkp_optimize_string_function_calls. * tree-cfg.h (insert_cond_bb): New. * tree-cfg.c (insert_cond_bb): New. gcc/testsuite/ * gcc.target/i386/chkp-stropt-1.c: New. * gcc.target/i386/chkp-stropt-2.c: New. * gcc.target/i386/chkp-stropt-3.c: New. * gcc.target/i386/chkp-stropt-4.c: New. * gcc.target/i386/chkp-stropt-5.c: New. * gcc.target/i386/chkp-stropt-6.c: New. * gcc.target/i386/chkp-stropt-7.c: New. * gcc.target/i386/chkp-stropt-8.c: New. * gcc.target/i386/chkp-stropt-9.c: New. * gcc.target/i386/chkp-stropt-10.c: New. * gcc.target/i386/chkp-stropt-11.c: New. * gcc.target/i386/chkp-stropt-12.c: New. * gcc.target/i386/chkp-stropt-13.c: New. * gcc.target/i386/chkp-stropt-14.c: New. * gcc.target/i386/chkp-stropt-15.c: New. * gcc.target/i386/chkp-stropt-16.c: New. From-SVN: r217656
This commit is contained in:
parent
edcf72f3c9
commit
e472781227
|
|
@ -1,3 +1,12 @@
|
|||
2014-11-17 Ilya Enkovich <ilya.enkovich@intel.com>
|
||||
|
||||
* tree-chkp-opt.c (chkp_get_nobnd_fndecl): New.
|
||||
(chkp_get_nochk_fndecl): New.
|
||||
(chkp_optimize_string_function_calls): New.
|
||||
(chkp_opt_execute): Call chkp_optimize_string_function_calls.
|
||||
* tree-cfg.h (insert_cond_bb): New.
|
||||
* tree-cfg.c (insert_cond_bb): New.
|
||||
|
||||
2014-11-17 Ilya Enkovich <ilya.enkovich@intel.com>
|
||||
|
||||
* tree-core.h (built_in_class): Add builtin codes to be used
|
||||
|
|
|
|||
|
|
@ -1,3 +1,22 @@
|
|||
2014-11-17 Ilya Enkovich <ilya.enkovich@intel.com>
|
||||
|
||||
* gcc.target/i386/chkp-stropt-1.c: New.
|
||||
* gcc.target/i386/chkp-stropt-2.c: New.
|
||||
* gcc.target/i386/chkp-stropt-3.c: New.
|
||||
* gcc.target/i386/chkp-stropt-4.c: New.
|
||||
* gcc.target/i386/chkp-stropt-5.c: New.
|
||||
* gcc.target/i386/chkp-stropt-6.c: New.
|
||||
* gcc.target/i386/chkp-stropt-7.c: New.
|
||||
* gcc.target/i386/chkp-stropt-8.c: New.
|
||||
* gcc.target/i386/chkp-stropt-9.c: New.
|
||||
* gcc.target/i386/chkp-stropt-10.c: New.
|
||||
* gcc.target/i386/chkp-stropt-11.c: New.
|
||||
* gcc.target/i386/chkp-stropt-12.c: New.
|
||||
* gcc.target/i386/chkp-stropt-13.c: New.
|
||||
* gcc.target/i386/chkp-stropt-14.c: New.
|
||||
* gcc.target/i386/chkp-stropt-15.c: New.
|
||||
* gcc.target/i386/chkp-stropt-16.c: New.
|
||||
|
||||
2014-11-17 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* g++.dg/ipa/pr63894.C (new): Replace unsigned long with
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump "memcpy_nochk" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int *buf2, size_t len)
|
||||
{
|
||||
memcpy (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump-not "memset_nobnd" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (void *buf1, int c, size_t len)
|
||||
{
|
||||
memset (buf1, c, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump-not "memmove_nobnd" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (void *buf1, void *buf2, size_t len)
|
||||
{
|
||||
memmove (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions -D_GNU_SOURCE" } */
|
||||
/* { dg-final { scan-tree-dump-not "mempcpy_nobnd" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (void *buf1, void *buf2, size_t len)
|
||||
{
|
||||
mempcpy (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions -fchkp-use-fast-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump "memcpy_nobnd_nochk" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int *buf2, size_t len)
|
||||
{
|
||||
memcpy (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions -fchkp-use-fast-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump "memset_nobnd_nochk" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int c, size_t len)
|
||||
{
|
||||
memset (buf1, c, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions -fchkp-use-fast-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump "memmove_nobnd_nochk" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int *buf2, size_t len)
|
||||
{
|
||||
memmove (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions -fchkp-use-fast-string-functions -D_GNU_SOURCE" } */
|
||||
/* { dg-final { scan-tree-dump "mempcpy_nobnd_nochk" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int *buf2, size_t len)
|
||||
{
|
||||
mempcpy (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump "memset_nochk" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int c, size_t len)
|
||||
{
|
||||
memset (buf1, c, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump "memmove_nochk" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int *buf2, size_t len)
|
||||
{
|
||||
memmove (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-nochk-string-functions -D_GNU_SOURCE" } */
|
||||
/* { dg-final { scan-tree-dump "mempcpy_nochk" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int *buf2, size_t len)
|
||||
{
|
||||
mempcpy (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump "memcpy_nobnd" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int *buf2, size_t len)
|
||||
{
|
||||
memcpy (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump "memset_nobnd" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int c, size_t len)
|
||||
{
|
||||
memset (buf1, c, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump "memmove_nobnd" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int *buf2, size_t len)
|
||||
{
|
||||
memmove (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions -D_GNU_SOURCE" } */
|
||||
/* { dg-final { scan-tree-dump "mempcpy_nobnd" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (int *buf1, int *buf2, size_t len)
|
||||
{
|
||||
mempcpy (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target mpx } */
|
||||
/* { dg-options "-fcheck-pointer-bounds -mmpx -O2 -fdump-tree-chkpopt -fchkp-use-fast-string-functions" } */
|
||||
/* { dg-final { scan-tree-dump-not "memcpy_nobnd" "chkpopt" } } */
|
||||
/* { dg-final { cleanup-tree-dump "chkpopt" } } */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void test (void *buf1, void *buf2, size_t len)
|
||||
{
|
||||
memcpy (buf1, buf2, len);
|
||||
}
|
||||
|
|
@ -8178,6 +8178,46 @@ make_pass_split_crit_edges (gcc::context *ctxt)
|
|||
}
|
||||
|
||||
|
||||
/* Insert COND expression which is GIMPLE_COND after STMT
|
||||
in basic block BB with appropriate basic block split
|
||||
and creation of a new conditionally executed basic block.
|
||||
Return created basic block. */
|
||||
basic_block
|
||||
insert_cond_bb (basic_block bb, gimple stmt, gimple cond)
|
||||
{
|
||||
edge fall = split_block (bb, stmt);
|
||||
gimple_stmt_iterator iter = gsi_last_bb (bb);
|
||||
basic_block new_bb;
|
||||
|
||||
/* Insert cond statement. */
|
||||
gcc_assert (gimple_code (cond) == GIMPLE_COND);
|
||||
if (gsi_end_p (iter))
|
||||
gsi_insert_before (&iter, cond, GSI_CONTINUE_LINKING);
|
||||
else
|
||||
gsi_insert_after (&iter, cond, GSI_CONTINUE_LINKING);
|
||||
|
||||
/* Create conditionally executed block. */
|
||||
new_bb = create_empty_bb (bb);
|
||||
make_edge (bb, new_bb, EDGE_TRUE_VALUE);
|
||||
make_single_succ_edge (new_bb, fall->dest, EDGE_FALLTHRU);
|
||||
|
||||
/* Fix edge for split bb. */
|
||||
fall->flags = EDGE_FALSE_VALUE;
|
||||
|
||||
/* Update dominance info. */
|
||||
if (dom_info_available_p (CDI_DOMINATORS))
|
||||
{
|
||||
set_immediate_dominator (CDI_DOMINATORS, new_bb, bb);
|
||||
set_immediate_dominator (CDI_DOMINATORS, fall->dest, bb);
|
||||
}
|
||||
|
||||
/* Update loop info. */
|
||||
if (current_loops)
|
||||
add_bb_to_loop (new_bb, bb->loop_father);
|
||||
|
||||
return new_bb;
|
||||
}
|
||||
|
||||
/* Build a ternary operation and gimplify it. Emit code before GSI.
|
||||
Return the gimple_val holding the result. */
|
||||
|
||||
|
|
|
|||
|
|
@ -100,5 +100,6 @@ extern tree gimplify_build1 (gimple_stmt_iterator *, enum tree_code,
|
|||
extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
|
||||
extern unsigned int execute_fixup_cfg (void);
|
||||
extern unsigned int split_critical_edges (void);
|
||||
extern basic_block insert_cond_bb (basic_block, gimple, gimple);
|
||||
|
||||
#endif /* _TREE_CFG_H */
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "gimplify-me.h"
|
||||
#include "expr.h"
|
||||
#include "tree-chkp.h"
|
||||
#include "ipa-chkp.h"
|
||||
#include "diagnostic.h"
|
||||
|
||||
enum check_type
|
||||
|
|
@ -845,6 +846,265 @@ chkp_remove_constant_checks (void)
|
|||
}
|
||||
}
|
||||
|
||||
/* Return fast version of string function FNCODE. */
|
||||
static tree
|
||||
chkp_get_nobnd_fndecl (enum built_in_function fncode)
|
||||
{
|
||||
/* Check if we are allowed to use fast string functions. */
|
||||
if (!flag_chkp_use_fast_string_functions)
|
||||
return NULL_TREE;
|
||||
|
||||
tree fndecl = NULL_TREE;
|
||||
|
||||
switch (fncode)
|
||||
{
|
||||
case BUILT_IN_MEMCPY_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND);
|
||||
break;
|
||||
|
||||
case BUILT_IN_MEMPCPY_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOBND);
|
||||
break;
|
||||
|
||||
case BUILT_IN_MEMMOVE_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOBND);
|
||||
break;
|
||||
|
||||
case BUILT_IN_MEMSET_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOBND);
|
||||
break;
|
||||
|
||||
case BUILT_IN_CHKP_MEMCPY_NOCHK_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK);
|
||||
break;
|
||||
|
||||
case BUILT_IN_CHKP_MEMPCPY_NOCHK_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK);
|
||||
break;
|
||||
|
||||
case BUILT_IN_CHKP_MEMMOVE_NOCHK_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOBND_NOCHK);
|
||||
break;
|
||||
|
||||
case BUILT_IN_CHKP_MEMSET_NOCHK_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOBND_NOCHK);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fndecl)
|
||||
fndecl = chkp_maybe_clone_builtin_fndecl (fndecl);
|
||||
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
|
||||
/* Return no-check version of string function FNCODE. */
|
||||
static tree
|
||||
chkp_get_nochk_fndecl (enum built_in_function fncode)
|
||||
{
|
||||
/* Check if we are allowed to use fast string functions. */
|
||||
if (!flag_chkp_use_nochk_string_functions)
|
||||
return NULL_TREE;
|
||||
|
||||
tree fndecl = NULL_TREE;
|
||||
|
||||
switch (fncode)
|
||||
{
|
||||
case BUILT_IN_MEMCPY_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOCHK);
|
||||
break;
|
||||
|
||||
case BUILT_IN_MEMPCPY_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOCHK);
|
||||
break;
|
||||
|
||||
case BUILT_IN_MEMMOVE_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOCHK);
|
||||
break;
|
||||
|
||||
case BUILT_IN_MEMSET_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOCHK);
|
||||
break;
|
||||
|
||||
case BUILT_IN_CHKP_MEMCPY_NOBND_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK);
|
||||
break;
|
||||
|
||||
case BUILT_IN_CHKP_MEMPCPY_NOBND_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK);
|
||||
break;
|
||||
|
||||
case BUILT_IN_CHKP_MEMMOVE_NOBND_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMMOVE_NOBND_NOCHK);
|
||||
break;
|
||||
|
||||
case BUILT_IN_CHKP_MEMSET_NOBND_CHKP:
|
||||
fndecl = builtin_decl_implicit (BUILT_IN_CHKP_MEMSET_NOBND_NOCHK);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fndecl)
|
||||
fndecl = chkp_maybe_clone_builtin_fndecl (fndecl);
|
||||
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
/* Find memcpy, mempcpy, memmove and memset calls, perform
|
||||
checks before call and then call no_chk version of
|
||||
functions. We do it on O2 to enable inlining of these
|
||||
functions during expand.
|
||||
|
||||
Also try to find memcpy, mempcpy, memmove and memset calls
|
||||
which are known to not write pointers to memory and use
|
||||
faster function versions for them. */
|
||||
static void
|
||||
chkp_optimize_string_function_calls (void)
|
||||
{
|
||||
basic_block bb;
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
fprintf (dump_file, "Searching for replaceable string function calls...\n");
|
||||
|
||||
FOR_EACH_BB_FN (bb, cfun)
|
||||
{
|
||||
gimple_stmt_iterator i;
|
||||
|
||||
for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
|
||||
{
|
||||
gimple stmt = gsi_stmt (i);
|
||||
tree fndecl;
|
||||
|
||||
if (gimple_code (stmt) != GIMPLE_CALL
|
||||
|| !gimple_call_with_bounds_p (stmt))
|
||||
continue;
|
||||
|
||||
fndecl = gimple_call_fndecl (stmt);
|
||||
|
||||
if (!fndecl || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
|
||||
continue;
|
||||
|
||||
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMCPY_CHKP
|
||||
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMPCPY_CHKP
|
||||
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMMOVE_CHKP
|
||||
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHKP)
|
||||
{
|
||||
tree dst = gimple_call_arg (stmt, 0);
|
||||
tree dst_bnd = gimple_call_arg (stmt, 1);
|
||||
bool is_memset = DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHKP;
|
||||
tree size = gimple_call_arg (stmt, is_memset ? 3 : 4);
|
||||
tree fndecl_nochk;
|
||||
gimple_stmt_iterator j;
|
||||
basic_block check_bb;
|
||||
address_t size_val;
|
||||
int sign;
|
||||
bool known;
|
||||
|
||||
/* We may replace call with corresponding __chkp_*_nobnd
|
||||
call in case destination pointer base type is not
|
||||
void or pointer. */
|
||||
if (POINTER_TYPE_P (TREE_TYPE (dst))
|
||||
&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (dst)))
|
||||
&& !chkp_type_has_pointer (TREE_TYPE (TREE_TYPE (dst))))
|
||||
{
|
||||
tree fndecl_nobnd
|
||||
= chkp_get_nobnd_fndecl (DECL_FUNCTION_CODE (fndecl));
|
||||
|
||||
if (fndecl_nobnd)
|
||||
fndecl = fndecl_nobnd;
|
||||
}
|
||||
|
||||
fndecl_nochk = chkp_get_nochk_fndecl (DECL_FUNCTION_CODE (fndecl));
|
||||
|
||||
if (fndecl_nochk)
|
||||
fndecl = fndecl_nochk;
|
||||
|
||||
if (fndecl != gimple_call_fndecl (stmt))
|
||||
{
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "Replacing call: ");
|
||||
print_gimple_stmt (dump_file, stmt, 0,
|
||||
TDF_VOPS|TDF_MEMSYMS);
|
||||
}
|
||||
|
||||
gimple_call_set_fndecl (stmt, fndecl);
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "With a new call: ");
|
||||
print_gimple_stmt (dump_file, stmt, 0,
|
||||
TDF_VOPS|TDF_MEMSYMS);
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is no nochk version of function then
|
||||
do nothing. Otherwise insert checks before
|
||||
the call. */
|
||||
if (!fndecl_nochk)
|
||||
continue;
|
||||
|
||||
/* If size passed to call is known and > 0
|
||||
then we may insert checks unconditionally. */
|
||||
size_val.pol.create (0);
|
||||
chkp_collect_value (size, size_val);
|
||||
known = chkp_is_constant_addr (size_val, &sign);
|
||||
size_val.pol.release ();
|
||||
|
||||
/* If we are not sure size is not zero then we have
|
||||
to perform runtime check for size and perform
|
||||
checks only when size is not zero. */
|
||||
if (!known)
|
||||
{
|
||||
gimple check = gimple_build_cond (NE_EXPR,
|
||||
size,
|
||||
size_zero_node,
|
||||
NULL_TREE,
|
||||
NULL_TREE);
|
||||
|
||||
/* Split block before string function call. */
|
||||
gsi_prev (&i);
|
||||
check_bb = insert_cond_bb (bb, gsi_stmt (i), check);
|
||||
|
||||
/* Set position for checks. */
|
||||
j = gsi_last_bb (check_bb);
|
||||
|
||||
/* The block was splitted and therefore we
|
||||
need to set iterator to its end. */
|
||||
i = gsi_last_bb (bb);
|
||||
}
|
||||
/* If size is known to be zero then no checks
|
||||
should be performed. */
|
||||
else if (!sign)
|
||||
continue;
|
||||
else
|
||||
j = i;
|
||||
|
||||
size = size_binop (MINUS_EXPR, size, size_one_node);
|
||||
if (!is_memset)
|
||||
{
|
||||
tree src = gimple_call_arg (stmt, 2);
|
||||
tree src_bnd = gimple_call_arg (stmt, 3);
|
||||
|
||||
chkp_check_mem_access (src, fold_build_pointer_plus (src, size),
|
||||
src_bnd, j, gimple_location (stmt),
|
||||
integer_zero_node);
|
||||
}
|
||||
|
||||
chkp_check_mem_access (dst, fold_build_pointer_plus (dst, size),
|
||||
dst_bnd, j, gimple_location (stmt),
|
||||
integer_one_node);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Intrumentation pass inserts most of bounds creation code
|
||||
in the header of the function. We want to move bounds
|
||||
creation closer to bounds usage to reduce bounds lifetime.
|
||||
|
|
@ -1026,6 +1286,10 @@ chkp_opt_execute (void)
|
|||
{
|
||||
chkp_opt_init();
|
||||
|
||||
/* This optimization may introduce new checks
|
||||
and thus we put it before checks search. */
|
||||
chkp_optimize_string_function_calls ();
|
||||
|
||||
chkp_gather_checks_info ();
|
||||
|
||||
chkp_remove_excess_intersections ();
|
||||
|
|
|
|||
Loading…
Reference in New Issue