Hi,
On Mon, Sep 21 2026, Josef Melcr wrote:
> 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.
Just one nit...
>
> Signed-off-by: Josef Melcr <[email protected]>
> ---
> 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 95357b9c8ff..95897f376f1 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 87455ab1f76..254f336ec3f 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 ba596966aea..fc1d7838d5d 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 n2
...by n2 you mean 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. */
Returns the 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 0f05b5024e9..938b832d95c 100644
> --- a/gcc/cgraph.h
> +++ b/gcc/cgraph.h
> @@ -1932,6 +1932,15 @@ public:
> edge. */
> cgraph_edge *make_callback (cgraph_node *n2, unsigned fn_idx, tree attr);
>
> + /* Create a callback edge, representing an indirect call to n2
> + 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.
> */
Likewise.
Otherwise OK.
Thanks,
Martin
> + 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
> --
> 2.55.0