Don't mark IFUNC resolver as only called directly
authorH.J. Lu <hongjiu.lu@intel.com>
Tue, 22 May 2018 19:10:34 +0000 (19:10 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Tue, 22 May 2018 19:10:34 +0000 (12:10 -0700)
Since IFUNC resolver is called indirectly, don't mark IFUNC resolver as
only called directly.  This patch adds ifunc_resolver to cgraph_node,
sets ifunc_resolver for ifunc attribute and checks ifunc_resolver
instead of looking up ifunc attribute.

gcc/

PR target/85345
* cgraph.h (cgraph_node::create): Set ifunc_resolver for ifunc
attribute.
(cgraph_node::create_alias): Likewise.
(cgraph_node::get_availability): Check ifunc_resolver instead
of looking up ifunc attribute.
* cgraphunit.c (maybe_diag_incompatible_alias): Likewise.
* varasm.c (do_assemble_alias): Likewise.
(assemble_alias): Likewise.
(default_binds_local_p_3): Likewise.
* cgraph.h (cgraph_node): Add ifunc_resolver.
(cgraph_node::only_called_directly_or_aliased_p): Return false
for IFUNC resolver.
* lto-cgraph.c (input_node): Set ifunc_resolver for ifunc
attribute.
* symtab.c (symtab_node::verify_base): Verify that ifunc_resolver
is equivalent to lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)).
(symtab_node::binds_to_current_def_p): Check ifunc_resolver
instead of looking up ifunc attribute.

gcc/testsuite/

PR target/85345
* gcc.target/i386/pr85345.c: New test.

From-SVN: r260547

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/lto-cgraph.c
gcc/symtab.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr85345.c [new file with mode: 0644]
gcc/varasm.c

index d2e0b06741e22e1811724c9dba8843e96eb9d939..e665b03e1e1c3920fec4609b24aee4f08aff4188 100644 (file)
@@ -1,3 +1,25 @@
+2018-05-22  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR target/85345
+       * cgraph.h (cgraph_node::create): Set ifunc_resolver for ifunc
+       attribute.
+       (cgraph_node::create_alias): Likewise.
+       (cgraph_node::get_availability): Check ifunc_resolver instead
+       of looking up ifunc attribute.
+       * cgraphunit.c (maybe_diag_incompatible_alias): Likewise.
+       * varasm.c (do_assemble_alias): Likewise.
+       (assemble_alias): Likewise.
+       (default_binds_local_p_3): Likewise.
+       * cgraph.h (cgraph_node): Add ifunc_resolver.
+       (cgraph_node::only_called_directly_or_aliased_p): Return false
+       for IFUNC resolver.
+       * lto-cgraph.c (input_node): Set ifunc_resolver for ifunc
+       attribute.
+       * symtab.c (symtab_node::verify_base): Verify that ifunc_resolver
+       is equivalent to lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)).
+       (symtab_node::binds_to_current_def_p): Check ifunc_resolver
+       instead of looking up ifunc attribute.
+
 2018-05-22  Luis Machado  <luis.machado@linaro.org>
 
        * config/aarch64/aarch64.md (*ashift<mode>_extv_bfiz): New pattern.
index 9a7d54d7ceedbdeaa6f7898ecb534806b3389fd7..9f3a2929f6bd6e90cd7dac8a88b05779e4495c11 100644 (file)
@@ -517,6 +517,9 @@ cgraph_node::create (tree decl)
        g->have_offload = true;
     }
 
+  if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
+    node->ifunc_resolver = true;
+
   node->register_symbol ();
 
   if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
@@ -575,6 +578,8 @@ cgraph_node::create_alias (tree alias, tree target)
   alias_node->alias = true;
   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
     alias_node->transparent_alias = alias_node->weakref = true;
+  if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (alias)))
+    alias_node->ifunc_resolver = true;
   return alias_node;
 }
 
@@ -2299,7 +2304,7 @@ cgraph_node::get_availability (symtab_node *ref)
     avail = AVAIL_AVAILABLE;
   else if (transparent_alias)
     ultimate_alias_target (&avail, ref);
-  else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl))
+  else if (ifunc_resolver
           || lookup_attribute ("noipa", DECL_ATTRIBUTES (decl)))
     avail = AVAIL_INTERPOSABLE;
   else if (!externally_visible)
index ee7ebb41c24b53c153100ad1afe121e34dccdfb4..afb2745a841d598a507ef199c7bc4fba52637473 100644 (file)
@@ -530,6 +530,9 @@ public:
   /* Set when symbol can be streamed into bytecode for offloading.  */
   unsigned offloadable : 1;
 
+  /* Set when symbol is an IFUNC resolver.  */
+  unsigned ifunc_resolver : 1;
+
 
   /* Ordering of all symtab entries.  */
   int order;
@@ -2886,6 +2889,7 @@ cgraph_node::only_called_directly_or_aliased_p (void)
 {
   gcc_assert (!global.inlined_to);
   return (!force_output && !address_taken
+         && !ifunc_resolver
          && !used_from_other_partition
          && !DECL_VIRTUAL_P (decl)
          && !DECL_STATIC_CONSTRUCTOR (decl)
index e418ec041497a896d75f5e8ad8b6cbe41f989a41..212ee7b83403d69b308d3e1ec6e98d16f2f8fb80 100644 (file)
@@ -1307,7 +1307,7 @@ maybe_diag_incompatible_alias (tree alias, tree target)
   tree altype = TREE_TYPE (alias);
   tree targtype = TREE_TYPE (target);
 
-  bool ifunc = lookup_attribute ("ifunc", DECL_ATTRIBUTES (alias));
+  bool ifunc = cgraph_node::get (alias)->ifunc_resolver;
   tree funcptr = altype;
 
   if (ifunc)
index dcd5391012c6dc9efd818cd33d4317e8730cadd8..40baf858ca5c274755769cf8b2433b551a392b2a 100644 (file)
@@ -1257,6 +1257,8 @@ input_node (struct lto_file_decl_data *file_data,
         of ipa passes is done.  Alays forcingly create a fresh node.  */
       node = symtab->create_empty ();
       node->decl = fn_decl;
+      if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (fn_decl)))
+       node->ifunc_resolver = 1;
       node->register_symbol ();
     }
 
index c1533083573d9ac9afc6eb340dd8158abdec7706..954920b6dff4f51facf02bbab75fd26649f488b1 100644 (file)
@@ -998,6 +998,13 @@ symtab_node::verify_base (void)
           error ("function symbol is not function");
           error_found = true;
        }
+      else if ((lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl))
+               != NULL)
+              != dyn_cast <cgraph_node *> (this)->ifunc_resolver)
+       {
+          error ("inconsistent `ifunc' attribute");
+          error_found = true;
+       }
     }
   else if (is_a <varpool_node *> (this))
     {
@@ -2253,13 +2260,13 @@ symtab_node::binds_to_current_def_p (symtab_node *ref)
   if (transparent_alias)
     return definition
           && get_alias_target()->binds_to_current_def_p (ref);
-  if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
+  cgraph_node *cnode = dyn_cast <cgraph_node *> (this);
+  if (cnode && cnode->ifunc_resolver)
     return false;
   if (decl_binds_to_current_def_p (decl))
     return true;
 
   /* Inline clones always binds locally.  */
-  cgraph_node *cnode = dyn_cast <cgraph_node *> (this);
   if (cnode && cnode->global.inlined_to)
     return true;
 
index 5ab91fd0b88db4844614de7bd99c2d13c514dc49..2e5bb3f0fb13bce6eb762d955bc0c1a2252375a8 100644 (file)
@@ -1,3 +1,8 @@
+2018-05-22  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR target/85345
+       * gcc.target/i386/pr85345.c: New test.
+
 2018-05-22  Luis Machado  <luis.machado@linaro.org>
 
        * gcc.target/aarch64/lsl_asr_sbfiz.c: New test.
diff --git a/gcc/testsuite/gcc.target/i386/pr85345.c b/gcc/testsuite/gcc.target/i386/pr85345.c
new file mode 100644 (file)
index 0000000..ceb94e4
--- /dev/null
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection" } */
+/* { dg-final { scan-assembler-times {\mendbr} 4 } } */
+
+int resolver_fn = 0;
+int resolved_fn = 0;
+
+static inline void
+do_it_right_at_runtime_A (void)
+{
+  resolved_fn++;
+}
+
+static inline void
+do_it_right_at_runtime_B (void)
+{
+  resolved_fn++;
+}
+
+static inline void do_it_right_at_runtime (void);
+
+void do_it_right_at_runtime (void)
+  __attribute__ ((ifunc ("resolve_do_it_right_at_runtime")));
+
+extern int r;
+static void (*resolve_do_it_right_at_runtime (void)) (void)
+{
+  resolver_fn++;
+
+  typeof(do_it_right_at_runtime) *func;
+  if (r & 1)
+    func = do_it_right_at_runtime_A;
+  else
+    func = do_it_right_at_runtime_B;
+
+  return (void *) func;
+}
+
+int
+main ()
+{
+  do_it_right_at_runtime ();
+  return 0;
+}
index 8cf6e1e27582e2bce7500a05a77f240994e6999a..3bd9cbb69f0e760023b57e837c160b86b052cc26 100644 (file)
@@ -5833,7 +5833,8 @@ do_assemble_alias (tree decl, tree target)
       globalize_decl (decl);
       maybe_assemble_visibility (decl);
     }
-  if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && cgraph_node::get (decl)->ifunc_resolver)
     {
 #if defined (ASM_OUTPUT_TYPE_DIRECTIVE)
       if (targetm.has_ifunc_p ())
@@ -5916,7 +5917,7 @@ assemble_alias (tree decl, tree target)
 # else
       if (!DECL_WEAK (decl))
        {
-         if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
+         if (cgraph_node::get (decl)->ifunc_resolver)
            error_at (DECL_SOURCE_LOCATION (decl),
                      "ifunc is not supported in this configuration");
          else
@@ -7048,7 +7049,8 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
      weakref alias.  */
   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
       || (TREE_CODE (exp) == FUNCTION_DECL
-         && lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp))))
+         && cgraph_node::get (exp)
+         && cgraph_node::get (exp)->ifunc_resolver))
     return false;
 
   /* Static variables are always local.  */