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
