Commit aab778d3 by H.J. Lu Committed by H.J. Lu

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
parent 58c2ad42
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> 2018-05-22 Luis Machado <luis.machado@linaro.org>
* config/aarch64/aarch64.md (*ashift<mode>_extv_bfiz): New pattern. * config/aarch64/aarch64.md (*ashift<mode>_extv_bfiz): New pattern.
......
...@@ -517,6 +517,9 @@ cgraph_node::create (tree decl) ...@@ -517,6 +517,9 @@ cgraph_node::create (tree decl)
g->have_offload = true; g->have_offload = true;
} }
if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
node->ifunc_resolver = true;
node->register_symbol (); node->register_symbol ();
if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL) if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
...@@ -575,6 +578,8 @@ cgraph_node::create_alias (tree alias, tree target) ...@@ -575,6 +578,8 @@ cgraph_node::create_alias (tree alias, tree target)
alias_node->alias = true; alias_node->alias = true;
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL) if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
alias_node->transparent_alias = alias_node->weakref = true; alias_node->transparent_alias = alias_node->weakref = true;
if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (alias)))
alias_node->ifunc_resolver = true;
return alias_node; return alias_node;
} }
...@@ -2299,7 +2304,7 @@ cgraph_node::get_availability (symtab_node *ref) ...@@ -2299,7 +2304,7 @@ cgraph_node::get_availability (symtab_node *ref)
avail = AVAIL_AVAILABLE; avail = AVAIL_AVAILABLE;
else if (transparent_alias) else if (transparent_alias)
ultimate_alias_target (&avail, ref); ultimate_alias_target (&avail, ref);
else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)) else if (ifunc_resolver
|| lookup_attribute ("noipa", DECL_ATTRIBUTES (decl))) || lookup_attribute ("noipa", DECL_ATTRIBUTES (decl)))
avail = AVAIL_INTERPOSABLE; avail = AVAIL_INTERPOSABLE;
else if (!externally_visible) else if (!externally_visible)
......
...@@ -530,6 +530,9 @@ public: ...@@ -530,6 +530,9 @@ public:
/* Set when symbol can be streamed into bytecode for offloading. */ /* Set when symbol can be streamed into bytecode for offloading. */
unsigned offloadable : 1; unsigned offloadable : 1;
/* Set when symbol is an IFUNC resolver. */
unsigned ifunc_resolver : 1;
/* Ordering of all symtab entries. */ /* Ordering of all symtab entries. */
int order; int order;
...@@ -2886,6 +2889,7 @@ cgraph_node::only_called_directly_or_aliased_p (void) ...@@ -2886,6 +2889,7 @@ cgraph_node::only_called_directly_or_aliased_p (void)
{ {
gcc_assert (!global.inlined_to); gcc_assert (!global.inlined_to);
return (!force_output && !address_taken return (!force_output && !address_taken
&& !ifunc_resolver
&& !used_from_other_partition && !used_from_other_partition
&& !DECL_VIRTUAL_P (decl) && !DECL_VIRTUAL_P (decl)
&& !DECL_STATIC_CONSTRUCTOR (decl) && !DECL_STATIC_CONSTRUCTOR (decl)
......
...@@ -1307,7 +1307,7 @@ maybe_diag_incompatible_alias (tree alias, tree target) ...@@ -1307,7 +1307,7 @@ maybe_diag_incompatible_alias (tree alias, tree target)
tree altype = TREE_TYPE (alias); tree altype = TREE_TYPE (alias);
tree targtype = TREE_TYPE (target); tree targtype = TREE_TYPE (target);
bool ifunc = lookup_attribute ("ifunc", DECL_ATTRIBUTES (alias)); bool ifunc = cgraph_node::get (alias)->ifunc_resolver;
tree funcptr = altype; tree funcptr = altype;
if (ifunc) if (ifunc)
......
...@@ -1257,6 +1257,8 @@ input_node (struct lto_file_decl_data *file_data, ...@@ -1257,6 +1257,8 @@ input_node (struct lto_file_decl_data *file_data,
of ipa passes is done. Alays forcingly create a fresh node. */ of ipa passes is done. Alays forcingly create a fresh node. */
node = symtab->create_empty (); node = symtab->create_empty ();
node->decl = fn_decl; node->decl = fn_decl;
if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (fn_decl)))
node->ifunc_resolver = 1;
node->register_symbol (); node->register_symbol ();
} }
......
...@@ -998,6 +998,13 @@ symtab_node::verify_base (void) ...@@ -998,6 +998,13 @@ symtab_node::verify_base (void)
error ("function symbol is not function"); error ("function symbol is not function");
error_found = true; 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)) else if (is_a <varpool_node *> (this))
{ {
...@@ -2253,13 +2260,13 @@ symtab_node::binds_to_current_def_p (symtab_node *ref) ...@@ -2253,13 +2260,13 @@ symtab_node::binds_to_current_def_p (symtab_node *ref)
if (transparent_alias) if (transparent_alias)
return definition return definition
&& get_alias_target()->binds_to_current_def_p (ref); && 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; return false;
if (decl_binds_to_current_def_p (decl)) if (decl_binds_to_current_def_p (decl))
return true; return true;
/* Inline clones always binds locally. */ /* Inline clones always binds locally. */
cgraph_node *cnode = dyn_cast <cgraph_node *> (this);
if (cnode && cnode->global.inlined_to) if (cnode && cnode->global.inlined_to)
return true; return true;
......
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> 2018-05-22 Luis Machado <luis.machado@linaro.org>
* gcc.target/aarch64/lsl_asr_sbfiz.c: New test. * gcc.target/aarch64/lsl_asr_sbfiz.c: New test.
......
/* { 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;
}
...@@ -5833,7 +5833,8 @@ do_assemble_alias (tree decl, tree target) ...@@ -5833,7 +5833,8 @@ do_assemble_alias (tree decl, tree target)
globalize_decl (decl); globalize_decl (decl);
maybe_assemble_visibility (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 defined (ASM_OUTPUT_TYPE_DIRECTIVE)
if (targetm.has_ifunc_p ()) if (targetm.has_ifunc_p ())
...@@ -5916,7 +5917,7 @@ assemble_alias (tree decl, tree target) ...@@ -5916,7 +5917,7 @@ assemble_alias (tree decl, tree target)
# else # else
if (!DECL_WEAK (decl)) if (!DECL_WEAK (decl))
{ {
if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl))) if (cgraph_node::get (decl)->ifunc_resolver)
error_at (DECL_SOURCE_LOCATION (decl), error_at (DECL_SOURCE_LOCATION (decl),
"ifunc is not supported in this configuration"); "ifunc is not supported in this configuration");
else else
...@@ -7048,7 +7049,8 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate, ...@@ -7048,7 +7049,8 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
weakref alias. */ weakref alias. */
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp)) if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
|| (TREE_CODE (exp) == FUNCTION_DECL || (TREE_CODE (exp) == FUNCTION_DECL
&& lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp)))) && cgraph_node::get (exp)
&& cgraph_node::get (exp)->ifunc_resolver))
return false; return false;
/* Static variables are always local. */ /* Static variables are always local. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment