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]>
---
 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
+    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 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.  */
+  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

Reply via email to