aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2018-05-22 19:10:34 +0000
committerH.J. Lu <hjl@gcc.gnu.org>2018-05-22 12:10:34 -0700
commitaab778d3825052d262e3fc6d87af67e7cc196273 (patch)
treef88364764fd0a5dbf2703b09f278a52dcaaddaef /gcc
parent58c2ad42a89438281327c74afb3f7483ffe22514 (diff)
downloadgcc-aab778d3825052d262e3fc6d87af67e7cc196273.zip
gcc-aab778d3825052d262e3fc6d87af67e7cc196273.tar.gz
gcc-aab778d3825052d262e3fc6d87af67e7cc196273.tar.bz2
Don't mark IFUNC resolver as only called directly
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog22
-rw-r--r--gcc/cgraph.c7
-rw-r--r--gcc/cgraph.h4
-rw-r--r--gcc/cgraphunit.c2
-rw-r--r--gcc/lto-cgraph.c2
-rw-r--r--gcc/symtab.c11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85345.c44
-rw-r--r--gcc/varasm.c8
9 files changed, 98 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d2e0b06..e665b03 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 9a7d54d..9f3a292 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -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)
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index ee7ebb4..afb2745 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -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)
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index e418ec0..212ee7b 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -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)
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index dcd5391..40baf85 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -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 ();
}
diff --git a/gcc/symtab.c b/gcc/symtab.c
index c153308..954920b 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5ab91fd..2e5bb3f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..ceb94e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85345.c
@@ -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;
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 8cf6e1e..3bd9cbb 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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. */