1 /* "Supergraph" classes that combine CFGs and callgraph into one digraph.
2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "hash-table.h"
30 #include "basic-block.h"
32 #include "gimple-fold.h"
34 #include "gimple-expr.h"
38 #include "gimple-iterator.h"
39 #include "gimple-pretty-print.h"
40 #include "tree-pretty-print.h"
46 #include "analyzer/analyzer.h"
47 #include "ordered-hash-map.h"
52 #include "analyzer/supergraph.h"
53 #include "analyzer/analyzer-logging.h"
59 /* Get the function of the ultimate alias target being called at EDGE,
63 get_ultimate_function_for_cgraph_edge (cgraph_edge
*edge
)
65 cgraph_node
*ultimate_node
= edge
->callee
->ultimate_alias_target ();
68 return ultimate_node
->get_fun ();
71 /* Get the cgraph_edge, but only if there's an underlying function body. */
74 supergraph_call_edge (function
*fun
, gimple
*stmt
)
76 gcall
*call
= dyn_cast
<gcall
*> (stmt
);
79 cgraph_edge
*edge
= cgraph_node::get (fun
->decl
)->get_edge (stmt
);
83 return NULL
; /* e.g. for a function pointer. */
84 if (!get_ultimate_function_for_cgraph_edge (edge
))
89 /* supergraph's ctor. Walk the callgraph, building supernodes for each
90 CFG basic block, splitting the basic blocks at callsites. Join
91 together the supernodes with interprocedural and intraprocedural
92 superedges as appropriate. */
94 supergraph::supergraph (logger
*logger
)
96 auto_timevar
tv (TV_ANALYZER_SUPERGRAPH
);
100 /* First pass: make supernodes. */
102 /* Sort the cgraph_nodes? */
104 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
106 function
*fun
= node
->get_fun ();
108 /* Ensure that EDGE_DFS_BACK is correct for every CFG edge in
109 the supergraph (by doing it per-function). */
110 auto_cfun
sentinel (fun
);
111 mark_dfs_back_edges ();
113 const int start_idx
= m_nodes
.length ();
116 FOR_ALL_BB_FN (bb
, fun
)
118 /* The initial supernode for the BB gets the phi nodes (if any). */
119 supernode
*node_for_stmts
= add_node (fun
, bb
, NULL
, phi_nodes (bb
));
120 m_bb_to_initial_node
.put (bb
, node_for_stmts
);
121 for (gphi_iterator gpi
= gsi_start_phis (bb
); !gsi_end_p (gpi
);
124 gimple
*stmt
= gsi_stmt (gpi
);
125 m_stmt_to_node_t
.put (stmt
, node_for_stmts
);
128 /* Append statements from BB to the current supernode, splitting
129 them into a new supernode at each call site; such call statements
130 appear in both supernodes (representing call and return). */
131 gimple_stmt_iterator gsi
;
132 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
134 gimple
*stmt
= gsi_stmt (gsi
);
135 node_for_stmts
->m_stmts
.safe_push (stmt
);
136 m_stmt_to_node_t
.put (stmt
, node_for_stmts
);
137 if (cgraph_edge
*edge
= supergraph_call_edge (fun
, stmt
))
139 m_cgraph_edge_to_caller_prev_node
.put(edge
, node_for_stmts
);
140 node_for_stmts
= add_node (fun
, bb
, as_a
<gcall
*> (stmt
), NULL
);
141 m_cgraph_edge_to_caller_next_node
.put (edge
, node_for_stmts
);
145 m_bb_to_final_node
.put (bb
, node_for_stmts
);
148 const unsigned num_snodes
= m_nodes
.length () - start_idx
;
149 m_function_to_num_snodes
.put (fun
, num_snodes
);
153 const int end_idx
= m_nodes
.length () - 1;
154 logger
->log ("SN: %i...%i: function %qD",
155 start_idx
, end_idx
, fun
->decl
);
160 /* Second pass: make superedges. */
162 /* Make superedges for CFG edges. */
163 for (bb_to_node_t::iterator iter
= m_bb_to_final_node
.begin ();
164 iter
!= m_bb_to_final_node
.end ();
167 basic_block bb
= (*iter
).first
;
168 supernode
*src_supernode
= (*iter
).second
;
173 FOR_EACH_VEC_ELT (*bb
->succs
, idx
, cfg_edge
)
175 basic_block dest_cfg_block
= cfg_edge
->dest
;
176 supernode
*dest_supernode
177 = *m_bb_to_initial_node
.get (dest_cfg_block
);
178 cfg_superedge
*cfg_sedge
179 = add_cfg_edge (src_supernode
, dest_supernode
, cfg_edge
, idx
);
180 m_cfg_edge_to_cfg_superedge
.put (cfg_edge
, cfg_sedge
);
184 /* Make interprocedural superedges for calls. */
186 for (cgraph_edge_to_node_t::iterator iter
187 = m_cgraph_edge_to_caller_prev_node
.begin ();
188 iter
!= m_cgraph_edge_to_caller_prev_node
.end ();
191 cgraph_edge
*edge
= (*iter
).first
;
192 supernode
*caller_prev_supernode
= (*iter
).second
;
193 function
* callee_fn
= get_ultimate_function_for_cgraph_edge (edge
);
194 if (!callee_fn
|| !callee_fn
->cfg
)
196 basic_block callee_cfg_block
= ENTRY_BLOCK_PTR_FOR_FN (callee_fn
);
197 supernode
*callee_supernode
198 = *m_bb_to_initial_node
.get (callee_cfg_block
);
199 call_superedge
*sedge
200 = add_call_superedge (caller_prev_supernode
,
203 m_cgraph_edge_to_call_superedge
.put (edge
, sedge
);
207 /* Make interprocedural superedges for returns. */
209 for (cgraph_edge_to_node_t::iterator iter
210 = m_cgraph_edge_to_caller_next_node
.begin ();
211 iter
!= m_cgraph_edge_to_caller_next_node
.end ();
214 cgraph_edge
*edge
= (*iter
).first
;
215 supernode
*caller_next_supernode
= (*iter
).second
;
216 function
* callee_fn
= get_ultimate_function_for_cgraph_edge (edge
);
217 if (!callee_fn
|| !callee_fn
->cfg
)
219 basic_block callee_cfg_block
= EXIT_BLOCK_PTR_FOR_FN (callee_fn
);
220 supernode
*callee_supernode
221 = *m_bb_to_initial_node
.get (callee_cfg_block
);
222 return_superedge
*sedge
223 = add_return_superedge (callee_supernode
,
224 caller_next_supernode
,
226 m_cgraph_edge_to_return_superedge
.put (edge
, sedge
);
230 /* Make intraprocedural superedges linking the two halves of a call. */
232 for (cgraph_edge_to_node_t::iterator iter
233 = m_cgraph_edge_to_caller_prev_node
.begin ();
234 iter
!= m_cgraph_edge_to_caller_prev_node
.end ();
237 cgraph_edge
*edge
= (*iter
).first
;
238 supernode
*caller_prev_supernode
= (*iter
).second
;
239 supernode
*caller_next_supernode
240 = *m_cgraph_edge_to_caller_next_node
.get (edge
);
242 = new callgraph_superedge (caller_prev_supernode
,
243 caller_next_supernode
,
244 SUPEREDGE_INTRAPROCEDURAL_CALL
,
247 m_cgraph_edge_to_intraproc_superedge
.put (edge
, sedge
);
254 /* Dump this graph in .dot format to PP, using DUMP_ARGS.
255 Cluster the supernodes by function, then by BB from original CFG. */
258 supergraph::dump_dot_to_pp (pretty_printer
*pp
,
259 const dump_args_t
&dump_args
) const
261 graphviz_out
gv (pp
);
263 pp_string (pp
, "digraph \"");
264 pp_write_text_to_stream (pp
);
265 pp_string (pp
, "supergraph");
266 pp_write_text_as_dot_label_to_stream (pp
, /*for_record=*/false);
267 pp_string (pp
, "\" {\n");
270 gv
.println ("overlap=false;");
271 gv
.println ("compound=true;");
273 /* TODO: maybe (optionally) sub-subdivide by TU, for LTO; see also:
274 https://gcc-python-plugin.readthedocs.io/en/latest/_images/sample-supergraph.png
277 /* Break out the supernodes into clusters by function. */
280 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
282 function
*fun
= node
->get_fun ();
283 const char *funcname
= function_name (fun
);
284 gv
.println ("subgraph \"cluster_%s\" {",
293 /* Break out the nodes into clusters by BB from original CFG. */
296 FOR_ALL_BB_FN (bb
, fun
)
298 if (dump_args
.m_flags
& SUPERGRAPH_DOT_SHOW_BBS
)
300 gv
.println ("subgraph \"cluster_%s_bb_%i\" {",
301 funcname
, bb
->index
);
306 " label=\"bb: %i\";\n"),
310 // TODO: maybe keep an index per-function/per-bb to speed this up???
313 FOR_EACH_VEC_ELT (m_nodes
, i
, n
)
314 if (n
->m_fun
== fun
&& n
->m_bb
== bb
)
315 n
->dump_dot (&gv
, dump_args
);
317 if (dump_args
.m_flags
& SUPERGRAPH_DOT_SHOW_BBS
)
319 /* Terminate per-bb "subgraph" */
326 /* Add an invisible edge from ENTRY to EXIT, to improve the graph layout. */
327 pp_string (pp
, "\t");
328 get_node_for_function_entry (fun
)->dump_dot_id (pp
);
329 pp_string (pp
, ":s -> ");
330 get_node_for_function_exit (fun
)->dump_dot_id (pp
);
331 pp_string (pp
, ":n [style=\"invis\",constraint=true];\n");
333 /* Terminate per-function "subgraph" */
342 FOR_EACH_VEC_ELT (m_edges
, i
, e
)
343 e
->dump_dot (&gv
, dump_args
);
345 /* Terminate "digraph" */
350 /* Dump this graph in .dot format to FP, using DUMP_ARGS. */
353 supergraph::dump_dot_to_file (FILE *fp
, const dump_args_t
&dump_args
) const
355 pretty_printer
*pp
= global_dc
->printer
->clone ();
356 pp_show_color (pp
) = 0;
357 /* %qE in logs for SSA_NAMEs should show the ssa names, rather than
358 trying to prettify things by showing the underlying var. */
359 pp_format_decoder (pp
) = default_tree_printer
;
361 pp
->buffer
->stream
= fp
;
362 dump_dot_to_pp (pp
, dump_args
);
367 /* Dump this graph in .dot format to PATH, using DUMP_ARGS. */
370 supergraph::dump_dot (const char *path
, const dump_args_t
&dump_args
) const
372 FILE *fp
= fopen (path
, "w");
373 dump_dot_to_file (fp
, dump_args
);
377 /* Create a supernode for BB within FUN and add it to this supergraph.
379 If RETURNING_CALL is non-NULL, the supernode represents the resumption
380 of the basic block after returning from that call.
382 If PHI_NODES is non-NULL, this is the initial supernode for the basic
383 block, and is responsible for any handling of the phi nodes. */
386 supergraph::add_node (function
*fun
, basic_block bb
, gcall
*returning_call
,
387 gimple_seq phi_nodes
)
389 supernode
*n
= new supernode (fun
, bb
, returning_call
, phi_nodes
,
391 m_nodes
.safe_push (n
);
395 /* Create a new cfg_superedge from SRC to DEST for the underlying CFG edge E,
396 adding it to this supergraph.
398 If the edge is for a switch statement, create a switch_cfg_superedge
399 subclass using IDX (the index of E within the out-edges from SRC's
400 underlying basic block). */
403 supergraph::add_cfg_edge (supernode
*src
, supernode
*dest
, ::edge e
, int idx
)
405 /* Special-case switch edges. */
406 gimple
*stmt
= src
->get_last_stmt ();
407 cfg_superedge
*new_edge
;
408 if (stmt
&& stmt
->code
== GIMPLE_SWITCH
)
409 new_edge
= new switch_cfg_superedge (src
, dest
, e
, idx
);
411 new_edge
= new cfg_superedge (src
, dest
, e
);
416 /* Create and add a call_superedge representing an interprocedural call
417 from SRC to DEST, using CEDGE. */
420 supergraph::add_call_superedge (supernode
*src
, supernode
*dest
,
423 call_superedge
*new_edge
= new call_superedge (src
, dest
, cedge
);
428 /* Create and add a return_superedge representing returning from an
429 interprocedural call, returning from SRC to DEST, using CEDGE. */
432 supergraph::add_return_superedge (supernode
*src
, supernode
*dest
,
435 return_superedge
*new_edge
= new return_superedge (src
, dest
, cedge
);
440 /* Implementation of dnode::dump_dot vfunc for supernodes.
442 Write a cluster for the node, and within it a .dot node showing
443 the phi nodes and stmts. Call into any node annotator from ARGS to
444 potentially add other records to the cluster. */
447 supernode::dump_dot (graphviz_out
*gv
, const dump_args_t
&args
) const
449 gv
->println ("subgraph cluster_node_%i {",
453 gv
->println("style=\"solid\";");
454 gv
->println("color=\"black\";");
455 gv
->println("fillcolor=\"lightgrey\";");
456 gv
->println("label=\"sn: %i (bb: %i)\";", m_index
, m_bb
->index
);
458 pretty_printer
*pp
= gv
->get_pp ();
460 if (args
.m_node_annotator
)
461 args
.m_node_annotator
->add_node_annotations (gv
, *this, false);
466 " [shape=none,margin=0,style=filled,fillcolor=%s,label=<",
468 pp_string (pp
, "<TABLE BORDER=\"0\">");
469 pp_write_text_to_stream (pp
);
471 bool had_row
= false;
473 /* Give any annotator the chance to add its own per-node TR elements. */
474 if (args
.m_node_annotator
)
475 if (args
.m_node_annotator
->add_node_annotations (gv
, *this, true))
478 if (m_returning_call
)
481 pp_string (pp
, "returning call: ");
486 pp_gimple_stmt_1 (pp
, m_returning_call
, 0, (dump_flags_t
)0);
487 pp_write_text_as_html_like_dot_to_stream (pp
);
489 /* Give any annotator the chance to add per-stmt TD elements to
491 if (args
.m_node_annotator
)
492 args
.m_node_annotator
->add_stmt_annotations (gv
, m_returning_call
,
496 /* Give any annotator the chance to add per-stmt TR elements. */
497 if (args
.m_node_annotator
)
498 args
.m_node_annotator
->add_stmt_annotations (gv
, m_returning_call
,
507 pp_string (pp
, "<TR><TD>ENTRY</TD></TR>");
514 pp_string (pp
, "<TR><TD>EXIT</TD></TR>");
520 for (gphi_iterator gpi
= const_cast<supernode
*> (this)->start_phis ();
521 !gsi_end_p (gpi
); gsi_next (&gpi
))
523 const gimple
*stmt
= gsi_stmt (gpi
);
526 pp_gimple_stmt_1 (pp
, stmt
, 0, (dump_flags_t
)0);
527 pp_write_text_as_html_like_dot_to_stream (pp
);
529 /* Give any annotator the chance to add per-phi TD elements to
531 if (args
.m_node_annotator
)
532 args
.m_node_annotator
->add_stmt_annotations (gv
, stmt
, true);
535 /* Give any annotator the chance to add per-phi TR elements. */
536 if (args
.m_node_annotator
)
537 args
.m_node_annotator
->add_stmt_annotations (gv
, stmt
, false);
546 FOR_EACH_VEC_ELT (m_stmts
, i
, stmt
)
550 pp_gimple_stmt_1 (pp
, stmt
, 0, (dump_flags_t
)0);
551 pp_write_text_as_html_like_dot_to_stream (pp
);
553 /* Give any annotator the chance to add per-stmt TD elements to
555 if (args
.m_node_annotator
)
556 args
.m_node_annotator
->add_stmt_annotations (gv
, stmt
, true);
559 /* Give any annotator the chance to add per-stmt TR elements. */
560 if (args
.m_node_annotator
)
561 args
.m_node_annotator
->add_stmt_annotations (gv
, stmt
, false);
567 /* Give any annotator the chance to add additional per-node TR elements
568 to the end of the TABLE. */
569 if (args
.m_node_annotator
)
570 if (args
.m_node_annotator
->add_after_node_annotations (gv
, *this))
573 /* Graphviz requires a TABLE element to have at least one TR
574 (and each TR to have at least one TD). */
577 pp_string (pp
, "<TR><TD>(empty)</TD></TR>");
581 pp_string (pp
, "</TABLE>>];\n\n");
584 /* Terminate "subgraph" */
589 /* Write an ID for this node to PP, for use in .dot output. */
592 supernode::dump_dot_id (pretty_printer
*pp
) const
594 pp_printf (pp
, "node_%i", m_index
);
597 /* Get a location_t for the start of this supernode. */
600 supernode::get_start_location () const
603 && get_pure_location (m_returning_call
->location
) != UNKNOWN_LOCATION
)
604 return m_returning_call
->location
;
608 FOR_EACH_VEC_ELT (m_stmts
, i
, stmt
)
609 if (get_pure_location (stmt
->location
) != UNKNOWN_LOCATION
)
610 return stmt
->location
;
614 // TWEAK: show the decl instead; this leads to more readable output:
615 return DECL_SOURCE_LOCATION (m_fun
->decl
);
617 return m_fun
->function_start_locus
;
620 return m_fun
->function_end_locus
;
622 return UNKNOWN_LOCATION
;
625 /* Get a location_t for the end of this supernode. */
628 supernode::get_end_location () const
632 FOR_EACH_VEC_ELT_REVERSE (m_stmts
, i
, stmt
)
633 if (get_pure_location (stmt
->location
) != UNKNOWN_LOCATION
)
634 return stmt
->location
;
637 && get_pure_location (m_returning_call
->location
) != UNKNOWN_LOCATION
)
638 return m_returning_call
->location
;
641 return m_fun
->function_start_locus
;
643 return m_fun
->function_end_locus
;
645 return UNKNOWN_LOCATION
;
648 /* Given STMT within this supernode, return its index within m_stmts. */
651 supernode::get_stmt_index (const gimple
*stmt
) const
655 FOR_EACH_VEC_ELT (m_stmts
, i
, iter_stmt
)
656 if (iter_stmt
== stmt
)
661 /* Dump this superedge to PP. */
664 superedge::dump (pretty_printer
*pp
) const
666 pp_printf (pp
, "edge: SN: %i -> SN: %i", m_src
->m_index
, m_dest
->m_index
);
667 char *desc
= get_description (false);
668 if (strlen (desc
) > 0)
671 pp_string (pp
, desc
);
676 /* Dump this superedge to stderr. */
679 superedge::dump () const
682 pp_format_decoder (&pp
) = default_tree_printer
;
683 pp_show_color (&pp
) = pp_show_color (global_dc
->printer
);
684 pp
.buffer
->stream
= stderr
;
690 /* Implementation of dedge::dump_dot for superedges.
691 Write a .dot edge to GV representing this superedge. */
694 superedge::dump_dot (graphviz_out
*gv
, const dump_args_t
&) const
696 const char *style
= "\"solid,bold\"";
697 const char *color
= "black";
699 const char *constraint
= "true";
705 case SUPEREDGE_CFG_EDGE
:
710 case SUPEREDGE_RETURN
:
713 case SUPEREDGE_INTRAPROCEDURAL_CALL
:
714 style
= "\"dotted\"";
718 /* Adapted from graph.c:draw_cfg_node_succ_edges. */
719 if (::edge cfg_edge
= get_any_cfg_edge ())
721 if (cfg_edge
->flags
& EDGE_FAKE
)
727 else if (cfg_edge
->flags
& EDGE_DFS_BACK
)
729 style
= "\"dotted,bold\"";
733 else if (cfg_edge
->flags
& EDGE_FALLTHRU
)
739 if (cfg_edge
->flags
& EDGE_ABNORMAL
)
745 pretty_printer
*pp
= gv
->get_pp ();
747 m_src
->dump_dot_id (pp
);
748 pp_string (pp
, " -> ");
749 m_dest
->dump_dot_id (pp
);
751 (" [style=%s, color=%s, weight=%d, constraint=%s,"
752 " ltail=\"cluster_node_%i\", lhead=\"cluster_node_%i\""
754 style
, color
, weight
, constraint
,
755 m_src
->m_index
, m_dest
->m_index
);
757 dump_label_to_pp (pp
, false);
759 pp_printf (pp
, "\"];\n");
762 /* If this is an intraprocedural superedge, return the associated
763 CFG edge. Otherwise, return NULL. */
766 superedge::get_any_cfg_edge () const
768 if (const cfg_superedge
*sub
= dyn_cast_cfg_superedge ())
769 return sub
->get_cfg_edge ();
773 /* If this is an interprocedural superedge, return the associated
774 cgraph_edge *. Otherwise, return NULL. */
777 superedge::get_any_callgraph_edge () const
779 if (const callgraph_superedge
*sub
= dyn_cast_callgraph_superedge ())
784 /* Build a description of this superedge (e.g. "true" for the true
785 edge of a conditional, or "case 42:" for a switch case).
787 The caller is responsible for freeing the result.
789 If USER_FACING is false, the result also contains any underlying
790 CFG edge flags. e.g. " (flags FALLTHRU | DFS_BACK)". */
793 superedge::get_description (bool user_facing
) const
796 dump_label_to_pp (&pp
, user_facing
);
797 return xstrdup (pp_formatted_text (&pp
));
800 /* Implementation of superedge::dump_label_to_pp for non-switch CFG
803 For true/false edges, print "true" or "false" to PP.
805 If USER_FACING is false, also print flags on the underlying CFG edge to
809 cfg_superedge::dump_label_to_pp (pretty_printer
*pp
,
810 bool user_facing
) const
813 pp_printf (pp
, "true");
814 else if (false_value_p ())
815 pp_printf (pp
, "false");
820 /* Express edge flags as a string with " | " separator.
821 e.g. " (flags FALLTHRU | DFS_BACK)". */
824 pp_string (pp
, " (flags ");
825 bool seen_flag
= false;
826 #define DEF_EDGE_FLAG(NAME,IDX) \
828 if (get_flags () & EDGE_##NAME) \
831 pp_string (pp, " | "); \
832 pp_printf (pp, "%s", (#NAME)); \
836 #include "cfg-flags.def"
841 /* Otherwise, no label. */
844 /* Get the phi argument for PHI for this CFG edge. */
847 cfg_superedge::get_phi_arg (const gphi
*phi
) const
849 size_t index
= m_cfg_edge
->dest_idx
;
850 return gimple_phi_arg_def (phi
, index
);
853 /* Implementation of superedge::dump_label_to_pp for CFG superedges for
856 Print "case VAL:", "case LOWER ... UPPER:", or "default:" to PP. */
859 switch_cfg_superedge::dump_label_to_pp (pretty_printer
*pp
,
860 bool user_facing ATTRIBUTE_UNUSED
) const
862 tree case_label
= get_case_label ();
863 gcc_assert (TREE_CODE (case_label
) == CASE_LABEL_EXPR
);
864 tree lower_bound
= CASE_LOW (case_label
);
865 tree upper_bound
= CASE_HIGH (case_label
);
868 pp_printf (pp
, "case ");
869 dump_generic_node (pp
, lower_bound
, 0, (dump_flags_t
)0, false);
872 pp_printf (pp
, " ... ");
873 dump_generic_node (pp
, upper_bound
, 0, (dump_flags_t
)0, false);
878 pp_printf (pp
, "default:");
881 /* Get the case label for this "switch" superedge. */
884 switch_cfg_superedge::get_case_label () const
886 return gimple_switch_label (get_switch_stmt (), m_idx
);
889 /* Implementation of superedge::dump_label_to_pp for interprocedural
893 callgraph_superedge::dump_label_to_pp (pretty_printer
*pp
,
894 bool user_facing ATTRIBUTE_UNUSED
) const
899 case SUPEREDGE_CFG_EDGE
:
903 pp_printf (pp
, "call");
906 case SUPEREDGE_RETURN
:
907 pp_printf (pp
, "return");
910 case SUPEREDGE_INTRAPROCEDURAL_CALL
:
911 pp_printf (pp
, "intraproc link");
916 /* Get the function that was called at this interprocedural call/return
920 callgraph_superedge::get_callee_function () const
922 return get_ultimate_function_for_cgraph_edge (m_cedge
);
925 /* Get the calling function at this interprocedural call/return edge. */
928 callgraph_superedge::get_caller_function () const
930 return m_cedge
->caller
->get_fun ();
933 /* Get the fndecl that was called at this interprocedural call/return
937 callgraph_superedge::get_callee_decl () const
939 return get_callee_function ()->decl
;
942 /* Get the calling fndecl at this interprocedural call/return edge. */
945 callgraph_superedge::get_caller_decl () const
947 return get_caller_function ()->decl
;
950 /* Given PARM_TO_FIND, a PARM_DECL, identify its index (writing it
951 to *OUT if OUT is non-NULL), and return the corresponding argument
955 callgraph_superedge::get_arg_for_parm (tree parm_to_find
,
956 callsite_expr
*out
) const
958 gcc_assert (TREE_CODE (parm_to_find
) == PARM_DECL
);
960 tree callee
= get_callee_decl ();
961 const gcall
*call_stmt
= get_call_stmt ();
964 for (tree iter_parm
= DECL_ARGUMENTS (callee
); iter_parm
;
965 iter_parm
= DECL_CHAIN (iter_parm
), ++i
)
967 if (i
>= gimple_call_num_args (call_stmt
))
969 if (iter_parm
== parm_to_find
)
972 *out
= callsite_expr::from_zero_based_param (i
);
973 return gimple_call_arg (call_stmt
, i
);
981 /* Look for a use of ARG_TO_FIND as an argument at this callsite.
982 If found, return the default SSA def of the corresponding parm within
983 the callee, and if OUT is non-NULL, write the index to *OUT.
984 Only the first match is handled. */
987 callgraph_superedge::get_parm_for_arg (tree arg_to_find
,
988 callsite_expr
*out
) const
990 tree callee
= get_callee_decl ();
991 const gcall
*call_stmt
= get_call_stmt ();
994 for (tree iter_parm
= DECL_ARGUMENTS (callee
); iter_parm
;
995 iter_parm
= DECL_CHAIN (iter_parm
), ++i
)
997 if (i
>= gimple_call_num_args (call_stmt
))
999 tree param
= gimple_call_arg (call_stmt
, i
);
1000 if (arg_to_find
== param
)
1003 *out
= callsite_expr::from_zero_based_param (i
);
1004 return ssa_default_def (get_callee_function (), iter_parm
);
1012 /* Map caller_expr back to an expr within the callee, or return NULL_TREE.
1013 If non-NULL is returned, populate OUT. */
1016 callgraph_superedge::map_expr_from_caller_to_callee (tree caller_expr
,
1017 callsite_expr
*out
) const
1019 /* Is it an argument (actual param)? If so, convert to
1020 parameter (formal param). */
1021 tree parm
= get_parm_for_arg (caller_expr
, out
);
1024 /* Otherwise try return value. */
1025 if (caller_expr
== gimple_call_lhs (get_call_stmt ()))
1028 *out
= callsite_expr::from_return_value ();
1029 return DECL_RESULT (get_callee_decl ());
1035 /* Map callee_expr back to an expr within the caller, or return NULL_TREE.
1036 If non-NULL is returned, populate OUT. */
1039 callgraph_superedge::map_expr_from_callee_to_caller (tree callee_expr
,
1040 callsite_expr
*out
) const
1042 if (callee_expr
== NULL_TREE
)
1045 /* If it's a parameter (formal param), get the argument (actual param). */
1046 if (TREE_CODE (callee_expr
) == PARM_DECL
)
1047 return get_arg_for_parm (callee_expr
, out
);
1049 /* Similar for the default SSA name of the PARM_DECL. */
1050 if (TREE_CODE (callee_expr
) == SSA_NAME
1051 && SSA_NAME_IS_DEFAULT_DEF (callee_expr
)
1052 && TREE_CODE (SSA_NAME_VAR (callee_expr
)) == PARM_DECL
)
1053 return get_arg_for_parm (SSA_NAME_VAR (callee_expr
), out
);
1055 /* Otherwise try return value. */
1056 if (callee_expr
== DECL_RESULT (get_callee_decl ()))
1059 *out
= callsite_expr::from_return_value ();
1060 return gimple_call_lhs (get_call_stmt ());
1068 #endif /* #if ENABLE_ANALYZER */