Hi,
this is the second version of this patch (v1:
https://gcc.gnu.org/pipermail/gcc-patches/2025-December/702502.html).
I fixed the formatting issues and added the missing comment in
cgraph.cc for callback_called_p.  I haven't retested it, since
these changes should have no effect on the correctness of this patch.

Best regards,
Josef

gcc/ChangeLog:

        PR ipa/122798
        * cgraph.cc (cgraph_edge::redirect_callee): Set address taken
        for new callee.
        (cgraph_node::callback_called_p): New function.
        * cgraph.h (struct cgraph_node): Likewise.
        * cgraphclones.cc (cgraph_node::create_virtual_clone): Set local
        flag to false when cloning a function with a callback call.

Signed-off-by: Josef Melcr <[email protected]>
---
 gcc/cgraph.cc       | 12 ++++++++++++
 gcc/cgraph.h        |  3 +++
 gcc/cgraphclones.cc |  4 ++++
 3 files changed, 19 insertions(+)

diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 3c21e174943..e643b6a61df 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -1698,6 +1698,7 @@ cgraph_edge::redirect_callee (cgraph_node *n)
       new_ref->lto_stmt_uid = lto_stmt_uid;
       if (!old_callee->referred_to_p ())
        old_callee->address_taken = 0;
+      n->mark_address_taken ();
     }
 
   if (!inline_failed)
@@ -3575,6 +3576,17 @@ cgraph_node::only_called_directly_p (void)
                                       NULL, true);
 }
 
+/* Return TRUE if the node has at least one callback edge pointing to it.  */
+
+bool
+cgraph_node::callback_called_p () const
+{
+  cgraph_edge *e;
+  for (e = callers; e; e = e->next_caller)
+    if (e->callback)
+      return true;
+  return false;
+}
 
 /* Collect all callers of NODE.  Worker for collect_callers_of_node.  */
 
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 313610fbe2c..b534a470b77 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1278,6 +1278,9 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : 
public symtab_node
      it is not used in any other non-standard way.  */
   bool only_called_directly_p (void);
 
+  /* Return TRUE if the node has at least one callback edge pointing to it.  */
+  bool callback_called_p (void) const;
+
   /* Turn profile to global0.  Walk into inlined functions.  */
   void make_profile_local ();
 
diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc
index 49f0e58fa1e..3cfbfec4c1a 100644
--- a/gcc/cgraphclones.cc
+++ b/gcc/cgraphclones.cc
@@ -687,6 +687,7 @@ cgraph_node::create_virtual_clone (const vec<cgraph_edge *> 
&redirect_callers,
                           clone_function_name (old_decl, suffix, num_suffix));
   SET_DECL_RTL (new_decl, NULL);
 
+  bool has_callback_call = callback_called_p ();
   new_node = create_clone (new_decl, count, false,
                           redirect_callers, false, NULL, param_adjustments,
                           suffix);
@@ -697,6 +698,9 @@ cgraph_node::create_virtual_clone (const vec<cgraph_edge *> 
&redirect_callers,
      ??? We cannot use COMDAT linkage because there is no
      ABI support for this.  */
   set_new_clone_decl_and_node_flags (new_node);
+  if (has_callback_call)
+    /* Callback clone can never be local, since it has its address taken.  */
+    new_node->local = false;
   new_node->ipcp_clone = ipcp_clone;
   if (tree_map)
     clone_info::get_create (new_node)->tree_map = tree_map;
-- 
2.52.0

Reply via email to