[gcc(refs/users/aoliva/heads/testme)] [PR83782] ifunc: back-propagate ifunc_resolver to aliases
Alexandre Oliva
aoliva@gcc.gnu.org
Sat Dec 13 08:46:41 GMT 2025
https://gcc.gnu.org/g:169b85342ebb8d21a1c814d3e35fc14cf085d8c3
commit 169b85342ebb8d21a1c814d3e35fc14cf085d8c3
Author: Alexandre Oliva <oliva@adacore.com>
Date: Sat Dec 13 04:11:49 2025 -0300
[PR83782] ifunc: back-propagate ifunc_resolver to aliases
gcc.target/i386/mvc10.c fails with -fPIE on ia32 because we omit the
@PLT mark when calling an alias to an indirect function. Such aliases
aren't marked as ifunc_resolvers in the cgraph, so the test that would
have forced the PLT call fails.
I've arranged for ifunc_resolver to be back-propagated to aliases, and
relaxed the test that required the ifunc attribute to be attached to
directly the decl, rather than taken from an aliased decl, when the
ifunc_resolver bit is set.
for gcc/ChangeLog
PR target/83782
* cgraph.h (symtab_node::set_ifunc_resolver): New, overloaded.
Back-propagate flag to aliases.
* cgraph.cc (cgraph_node::create): Use set_ifunc_resolver.
(cgraph_node::create_alias): Likewise.
* lto-cgraph.cc (input_node): Likewise.
* multiple_target.cc (create_dispatcher_calls): Propagate to
aliases when redirecting them.
* symtab.cc (symtab_node::verify_base): Accept ifunc_resolver
set in an alias to another ifunc_resolver nodes.
(symtab_node::resolve_alias): Propagate ifunc_resolver from
resolved target to alias.
* varasm.cc (do_assemble_alias): Checking for the attribute.
Diff:
---
gcc/cgraph.cc | 4 ++--
gcc/cgraph.h | 13 +++++++++++++
gcc/lto-cgraph.cc | 2 +-
gcc/multiple_target.cc | 2 ++
gcc/symtab.cc | 15 ++++++++++++++-
gcc/varasm.cc | 5 ++++-
6 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 1a7d49922e09..cb314b5add80 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -672,7 +672,7 @@ cgraph_node::create (tree decl)
}
if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
- node->ifunc_resolver = true;
+ node->set_ifunc_resolver ();
node->register_symbol ();
maybe_record_nested_function (node);
@@ -730,7 +730,7 @@ cgraph_node::create_alias (tree alias, tree target)
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;
+ alias_node->set_ifunc_resolver ();
return alias_node;
}
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 6d589f59442f..1083b0dadf0b 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -504,6 +504,19 @@ public:
return decl->decl_with_vis.symtab_node;
}
+ /* Worked for the nonstatic set_ifunc_resolver, to vback-propagate
+ ifunc_resolver in the alias chain. */
+ static bool set_ifunc_resolver (symtab_node *n, void * = NULL)
+ {
+ n->ifunc_resolver = true;
+ return false;
+ }
+
+ /* Set the ifunc_resolver bit in this node and in any aliases thereof. */
+ void set_ifunc_resolver () {
+ call_for_symbol_and_aliases (set_ifunc_resolver, NULL, true);
+ }
+
/* Try to find a symtab node for declaration DECL and if it does not
exist or if it corresponds to an inline clone, create a new one. */
static inline symtab_node * get_create (tree node);
diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc
index 4c60bf0dd74a..d4ab4f7b21cf 100644
--- a/gcc/lto-cgraph.cc
+++ b/gcc/lto-cgraph.cc
@@ -1327,7 +1327,7 @@ input_node (struct lto_file_decl_data *file_data,
node = symtab->create_empty ();
node->decl = fn_decl;
if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (fn_decl)))
- node->ifunc_resolver = 1;
+ node->set_ifunc_resolver ();
node->register_symbol ();
}
diff --git a/gcc/multiple_target.cc b/gcc/multiple_target.cc
index 02353d9dca62..b46c8da0a17d 100644
--- a/gcc/multiple_target.cc
+++ b/gcc/multiple_target.cc
@@ -202,6 +202,8 @@ create_dispatcher_calls (struct cgraph_node *node)
source->remove_from_same_comdat_group ();
source->add_to_same_comdat_group (inode);
}
+ if (!source->ifunc_resolver)
+ source->set_ifunc_resolver ();
}
else
gcc_unreachable ();
diff --git a/gcc/symtab.cc b/gcc/symtab.cc
index a8b6091848bb..3550835105ba 100644
--- a/gcc/symtab.cc
+++ b/gcc/symtab.cc
@@ -1124,9 +1124,19 @@ symtab_node::verify_base (void)
error ("function symbol is not function");
error_found = true;
}
+ /* If the ifunc attribute is present, the node must be marked as
+ ifunc_resolver, but it may also be marked on a node that
+ doesn't have the attribute, if it's an alias to another
+ marked node. The resolver node itself is an alias to the
+ function that performs the resolution proper, and that
+ function is not marked, but here we test other kinds of
+ aliases, that alias the indirect function. */
else if ((lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl))
!= NULL)
- != dyn_cast <cgraph_node *> (this)->ifunc_resolver)
+ ? !ifunc_resolver
+ : ifunc_resolver
+ ? !get_alias_target ()->ifunc_resolver
+ : (alias && analyzed && get_alias_target ()->ifunc_resolver))
{
error ("inconsistent %<ifunc%> attribute");
error_found = true;
@@ -1988,6 +1998,9 @@ symtab_node::resolve_alias (symtab_node *target, bool transparent)
if (target->implicit_section)
call_for_symbol_and_aliases (set_implicit_section, NULL, true);
+ if (target->ifunc_resolver && !ifunc_resolver)
+ set_ifunc_resolver ();
+
/* Alias targets become redundant after alias is resolved into an reference.
We do not want to keep it around or we would have to mind updating them
when renaming symbols. */
diff --git a/gcc/varasm.cc b/gcc/varasm.cc
index 0d78f5b384fb..8b0a5d345467 100644
--- a/gcc/varasm.cc
+++ b/gcc/varasm.cc
@@ -6556,7 +6556,10 @@ do_assemble_alias (tree decl, tree target)
maybe_assemble_visibility (decl);
}
if (TREE_CODE (decl) == FUNCTION_DECL
- && cgraph_node::get (decl)->ifunc_resolver)
+ && cgraph_node::get (decl)->ifunc_resolver
+ /* Aliases to the ifunc decl will also have the ifunc_resolver
+ bit set, so check that this is the ifunc declaration. */
+ && lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
{
#if defined (ASM_OUTPUT_TYPE_DIRECTIVE)
if (targetm.has_ifunc_p ())
More information about the Gcc-cvs
mailing list