@@ -129,6 +129,16 @@ chkp_build_instrumented_fndecl (tree fndecl)
make own copy. */
DECL_ATTRIBUTES (new_decl) = copy_list (DECL_ATTRIBUTES (fndecl));
+ /* Change builtin function code. */
+ if (DECL_BUILT_IN (new_decl))
+ {
+ gcc_assert (DECL_BUILT_IN_CLASS (new_decl) == BUILT_IN_NORMAL);
+ gcc_assert (DECL_FUNCTION_CODE (new_decl) < BEGIN_CHKP_BUILTINS);
+ DECL_FUNCTION_CODE (new_decl)
+ = (enum built_in_function)(DECL_FUNCTION_CODE (new_decl)
+ + BEGIN_CHKP_BUILTINS + 1);
+ }
+
return new_decl;
}
@@ -354,6 +364,33 @@ chkp_add_bounds_params_to_function (tree fndecl)
chkp_copy_function_type_adding_bounds (TREE_TYPE (fndecl));
}
+/* Return an instrumentation clone for builtin function
+ FNDECL. Create one if needed. */
+
+tree
+chkp_maybe_clone_builtin_fndecl (tree fndecl)
+{
+ tree clone;
+ enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+
+ gcc_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ && fcode < BEGIN_CHKP_BUILTINS);
+
+ fcode = (enum built_in_function) (fcode + BEGIN_CHKP_BUILTINS + 1);
+ clone = builtin_decl_explicit (fcode);
+ if (clone)
+ return clone;
+
+ clone = chkp_build_instrumented_fndecl (fndecl);
+ chkp_add_bounds_params_to_function (clone);
+
+ gcc_assert (DECL_FUNCTION_CODE (clone) == fcode);
+
+ set_builtin_decl (fcode, clone, false);
+
+ return clone;
+}
+
/* Return clone created for instrumentation of NODE or NULL. */
cgraph_node *
@@ -364,6 +401,54 @@ chkp_maybe_create_clone (tree fndecl)
gcc_assert (!node->instrumentation_clone);
+ if (DECL_BUILT_IN (fndecl)
+ && (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL
+ || DECL_FUNCTION_CODE (fndecl) >= BEGIN_CHKP_BUILTINS))
+ return NULL;
+
+ clone = node->instrumented_version;
+
+ /* Some instrumented builtin function calls may be optimized and
+ cgraph nodes may be removed as unreachable. Later optimizations
+ may generate new calls to removed functions and in this case
+ we have to recreate cgraph node. FUNCTION_DECL for instrumented
+ builtin still exists and should be reused in such case. */
+ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ && fndecl == builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl))
+ && !clone)
+ {
+ enum built_in_function fncode = DECL_FUNCTION_CODE (fndecl);
+ tree new_decl;
+
+ fncode = (enum built_in_function) (fncode + BEGIN_CHKP_BUILTINS + 1);
+ new_decl = builtin_decl_explicit (fncode);
+
+ /* We've actually already created an instrumented clone once.
+ Restore it. */
+ if (new_decl)
+ {
+ clone = cgraph_node::get (new_decl);
+
+ if (!clone)
+ {
+ gcc_assert (!gimple_has_body_p (fndecl));
+ clone = cgraph_node::get_create (new_decl);
+ clone->externally_visible = node->externally_visible;
+ clone->local = node->local;
+ clone->address_taken = node->address_taken;
+ clone->thunk = node->thunk;
+ clone->alias = node->alias;
+ clone->weakref = node->weakref;
+ clone->cpp_implicit_alias = node->cpp_implicit_alias;
+ clone->orig_decl = fndecl;
+ clone->instrumentation_clone = true;
+ }
+
+ clone->instrumented_version = node;
+ node->instrumented_version = clone;
+ }
+ }
+
if (!clone)
{
tree new_decl = chkp_build_instrumented_fndecl (fndecl);
@@ -408,6 +493,15 @@ chkp_maybe_create_clone (tree fndecl)
actually copies args list from the original decl. */
chkp_add_bounds_params_to_function (new_decl);
+ /* Remember builtin fndecl. */
+ if (DECL_BUILT_IN_CLASS (clone->decl) == BUILT_IN_NORMAL
+ && fndecl == builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl)))
+ {
+ gcc_assert (!builtin_decl_explicit (DECL_FUNCTION_CODE (clone->decl)));
+ set_builtin_decl (DECL_FUNCTION_CODE (clone->decl),
+ clone->decl, false);
+ }
+
/* Clones have the same comdat group as originals. */
if (node->same_comdat_group
|| DECL_ONE_ONLY (node->decl))
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#define GCC_IPA_CHKP_H
extern tree chkp_copy_function_type_adding_bounds (tree orig_type);
+extern tree chkp_maybe_clone_builtin_fndecl (tree fndecl);
extern cgraph_node *chkp_maybe_create_clone (tree fndecl);
#endif /* GCC_IPA_CHKP_H */
@@ -168,6 +168,14 @@ enum built_in_class {
enum built_in_function {
#include "builtins.def"
+ BEGIN_CHKP_BUILTINS,
+
+#undef DEF_BUILTIN
+#define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) ENUM##_CHKP,
+#include "builtins.def"
+
+ END_CHKP_BUILTINS,
+
/* Complex division routines in libgcc. These are done via builtins
because emit_library_call_value can't handle complex values. */
BUILT_IN_COMPLEX_MUL_MIN,
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "streamer-hooks.h"
#include "lto-streamer.h"
#include "builtins.h"
+#include "ipa-chkp.h"
/* Read a STRING_CST from the string table in DATA_IN using input
block IB. */
@@ -1113,6 +1114,14 @@ streamer_get_builtin_tree (struct lto_input_block *ib, struct data_in *data_in)
if (fcode >= END_BUILTINS)
fatal_error ("machine independent builtin code out of range");
result = builtin_decl_explicit (fcode);
+ if (!result
+ && fcode > BEGIN_CHKP_BUILTINS
+ && fcode < END_CHKP_BUILTINS)
+ {
+ fcode = (enum built_in_function) (fcode - BEGIN_CHKP_BUILTINS - 1);
+ result = builtin_decl_explicit (fcode);
+ result = chkp_maybe_clone_builtin_fndecl (result);
+ }
gcc_assert (result);
}
else if (fclass == BUILT_IN_MD)