diff mbox

[Pointer,Bounds,Checker,Builtins,instrumentation,1/5] Builtin codes and decls

Message ID 20141117133137.GA5422@msticlxl57.ims.intel.com
State New
Headers show

Commit Message

Ilya Enkovich Nov. 17, 2014, 1:31 p.m. UTC
On 15 Nov 00:03, Jeff Law wrote:
> On 11/14/14 01:22, Ilya Enkovich wrote:
> >
> >I don't think I'm hiding some problem here.  Builtin function calls
> >may be removed during various optimizations.  Therefore we may remove
> >all calls to some instrumented builtins and corresponding cgraph_node
> >is removed as unreachable (but fndecl still exists).  Later calls to
> >removed function may be created again.  IIRC in my test case it
> >happened in strlen pass which may replace builtin calls with another
> >ones.  In this case cgraph_node is recreated but fndecl recreation
> >should be avoided, existing one should be used instead.
> OK. Please add those details to the comment.  With that comment
> updated, OK for the trunk.
> 
> jeff
> 

Thanks! Below is a final version.

Ilya
--
diff mbox

Patch

diff --git a/gcc/ipa-chkp.c b/gcc/ipa-chkp.c
index 19a9894..3e343d4 100644
--- a/gcc/ipa-chkp.c
+++ b/gcc/ipa-chkp.c
@@ -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))
diff --git a/gcc/ipa-chkp.h b/gcc/ipa-chkp.h
index d4ad113..b2d03ad 100644
--- a/gcc/ipa-chkp.h
+++ b/gcc/ipa-chkp.h
@@ -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 */
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 58bdfff..fe3fbb4 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.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,
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index a11a46e..fba6048 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -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)