https://gcc.gnu.org/g:44091b3480985244d5d981886f3c5624e8ca1571
commit 44091b3480985244d5d981886f3c5624e8ca1571 Author: Alexandre Oliva <ol...@adacore.com> Date: Thu Dec 14 03:21:28 2023 -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 b5d096d530c0..9f6493c9b156 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -520,7 +520,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); @@ -578,7 +578,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 a8c3224802c1..261d4745d142 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -471,6 +471,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 1d4311a8832b..e8af5ea14a98 100644 --- a/gcc/lto-cgraph.cc +++ b/gcc/lto-cgraph.cc @@ -1299,7 +1299,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 1fdd279da04a..1deaa3d3c3ec 100644 --- a/gcc/multiple_target.cc +++ b/gcc/multiple_target.cc @@ -156,6 +156,8 @@ create_dispatcher_calls (struct cgraph_node *node) source->create_reference (inode, IPA_REF_ALIAS); if (inode->get_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 3b018ab3ea21..08607497970f 100644 --- a/gcc/symtab.cc +++ b/gcc/symtab.cc @@ -1109,9 +1109,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; @@ -1971,6 +1981,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 c25400554216..6cd922e45881 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -6345,7 +6345,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 ())