https://gcc.gnu.org/g:455e2bc5aafc11305e571f5b129fdc2d7c1d31f9

commit r17-5626-g455e2bc5aafc11305e571f5b129fdc2d7c1d31f9
Author: Josef Melcr <[email protected]>
Date:   Tue Sep 15 11:59:02 2026 +0200

    cgraph: Add functions for internal callback edge creation
    
    This patch adds the basic logic to make the creation of callback edges
    bound to internal calls ("internal callback edges") possible.  Because
    internal calls are not usually represented in the call graph, internal
    callback edges don't have any callback-carrying edges (as opposed to
    their regular counterparts).  Internal callback edges are currently only
    meant to be used for outlined IFN_ASSUME bodies, though I tried to keep
    the logic generic enough for future expansion.
    
    Note that make_callback_internal has no uses in this patch.  The
    creation of the edges sets a lot of the logic in this patch series in
    motion, so I am saving that for a later patch.
    
    gcc/ChangeLog:
    
            * callback-info.cc (callback_info::create_internal_summary): Add
            implementation.
            * callback-info.h: Add create_internal_summary method.  Creates
            and initializes a callback summary for an internal callback edge.
            a callback edge bound to an internal call.
            * cgraph.cc (cgraph_edge::make_callback_internal): Add
            implementation.
            * cgraph.h: Add make_callback_internal method.  Creates a
            callback edge bound to an internal call.
    
    Signed-off-by: Josef Melcr <[email protected]>

Diff:
---
 gcc/callback-info.cc | 24 ++++++++++++++++++++++++
 gcc/callback-info.h  |  4 ++++
 gcc/cgraph.cc        | 30 ++++++++++++++++++++++++++++++
 gcc/cgraph.h         |  9 +++++++++
 4 files changed, 67 insertions(+)

diff --git a/gcc/callback-info.cc b/gcc/callback-info.cc
index a75a7d695e5c..f72339bf83ef 100644
--- a/gcc/callback-info.cc
+++ b/gcc/callback-info.cc
@@ -118,6 +118,30 @@ callback_info::init (cgraph_edge *e, unsigned fn_idx, tree 
attr)
   redirected = false;
 }
 
+/* Initialize the summary for a callback call CBE of internal function IFN.  */
+callback_info *
+callback_info::create_internal_summary (cgraph_edge *cbe, internal_fn ifn)
+{
+  callback_info_sum_t::check_create_info_sum ();
+  callback_info *ci = callback_info_sum->get_create (cbe);
+  switch (ifn)
+    {
+    case IFN_ASSUME:
+      {
+       ci->fn_idx = 0;
+       unsigned n = gimple_call_num_args (cbe->call_stmt);
+       for (unsigned i = 0; i < n - 1; i++)
+         ci->arg_mapping.safe_push (i + 1);
+       invert_arg_mapping (cbe, ci);
+       break;
+      }
+    default:
+      gcc_unreachable ();
+    }
+  ci->redirected = false;
+  return ci;
+}
+
 /* Populates the callback_info_sum if it's NULL.  */
 void
 callback_info_sum_t::check_create_info_sum (void)
diff --git a/gcc/callback-info.h b/gcc/callback-info.h
index bb656a90c889..2a75647ab434 100644
--- a/gcc/callback-info.h
+++ b/gcc/callback-info.h
@@ -60,6 +60,10 @@ public:
 
   /* Initializes the summary.  */
   void init (cgraph_edge *e, unsigned fn_idx, tree attr);
+
+  /* Create the summary for a callback call CBE of internal function IFN. */
+  static callback_info *create_internal_summary (cgraph_edge *cbe,
+                                                internal_fn ifn);
 };
 
 class callback_info_sum_t : public call_summary<callback_info *>
diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index ba596966aea3..f86b14762df6 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -1387,6 +1387,36 @@ cgraph_edge::make_callback (cgraph_node *n2, unsigned 
fn_idx, tree attr)
   return e2;
 }
 
+/* Create a callback edge, representing an indirect call to target
+    passed to an internal function by argument.  As internal calls are not
+    represented in the callgraph, the created edge won't have any associated
+    dispatching edge.  The created callback edge will be attached to the
+    internal call statement STMT.  Returns created callback edge.  */
+
+cgraph_edge *
+cgraph_edge::make_callback_internal (cgraph_node *caller, cgraph_node *target,
+                                    gcall *call_stmt)
+{
+  cgraph_edge *ret;
+
+  ret
+    = caller->create_edge (target, call_stmt, profile_count::uninitialized ());
+  if (dump_file)
+    {
+      fprintf (dump_file,
+              "Created callback edge %s -> %s belonging to internal call ",
+              ret->caller->dump_name (), ret->callee->dump_name ());
+      print_gimple_stmt (dump_file, call_stmt, 0);
+    }
+  ret->inline_failed = CIF_CALLBACK_EDGE;
+  ret->callback = true;
+  if (TREE_NOTHROW (target->decl))
+    ret->can_throw_external = false;
+  target->mark_address_taken ();
+  callback_info::create_internal_summary (ret, IFN_ASSUME);
+  return ret;
+}
+
 /* Returns the callback_carrying edge of a callback edge on which
    it is called on or NULL when no such edge can be found.
 
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 1b55df76e95a..cad7fb3c1279 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1935,6 +1935,15 @@ public:
      edge.  */
   cgraph_edge *make_callback (cgraph_node *n2, unsigned fn_idx, tree attr);
 
+  /* Create a callback edge, representing an indirect call to target
+     passed to an internal function by argument.  As internal calls are not
+     represented in the callgraph, the created edge won't have any associated
+     dispatching edge.  The created callback edge will be attached to the
+     internal call statement STMT.  Returns created callback edge.  */
+  static cgraph_edge *make_callback_internal (cgraph_node *caller,
+                                             cgraph_node *target,
+                                             gcall *call_stmt);
+
   /* Returns the callback-carrying edge of a callback edge or NULL, if such 
edge
      cannot be found.  An edge is considered callback-carrying, if it has it's
      has_callback flag set and shares it's call statement with the edge

Reply via email to