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 cgraph_edge, but only if there's an underlying function body. */
62 supergraph_call_edge (function
*fun
, gimple
*stmt
)
64 gcall
*call
= dyn_cast
<gcall
*> (stmt
);
67 cgraph_edge
*edge
= cgraph_node::get (fun
->decl
)->get_edge (stmt
);
71 return NULL
; /* e.g. for a function pointer. */
72 if (!edge
->callee
->get_fun ())
77 /* supergraph's ctor. Walk the callgraph, building supernodes for each
78 CFG basic block, splitting the basic blocks at callsites. Join
79 together the supernodes with interprocedural and intraprocedural
80 superedges as appropriate. */
82 supergraph::supergraph (logger
*logger
)
84 auto_timevar
tv (TV_ANALYZER_SUPERGRAPH
);
88 /* First pass: make supernodes. */
90 /* Sort the cgraph_nodes? */
92 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
94 function
*fun
= node
->get_fun ();
96 /* Ensure that EDGE_DFS_BACK is correct for every CFG edge in
97 the supergraph (by doing it per-function). */
98 auto_cfun
sentinel (fun
);
99 mark_dfs_back_edges ();
101 const int start_idx
= m_nodes
.length ();
104 FOR_ALL_BB_FN (bb
, fun
)
106 /* The initial supernode for the BB gets the phi nodes (if any). */
107 supernode
*node_for_stmts
= add_node (fun
, bb
, NULL
, phi_nodes (bb
));
108 m_bb_to_initial_node
.put (bb
, node_for_stmts
);
109 for (gphi_iterator gpi
= gsi_start_phis (bb
); !gsi_end_p (gpi
);
112 gimple
*stmt
= gsi_stmt (gpi
);
113 m_stmt_to_node_t
.put (stmt
, node_for_stmts
);
116 /* Append statements from BB to the current supernode, splitting
117 them into a new supernode at each call site; such call statements
118 appear in both supernodes (representing call and return). */
119 gimple_stmt_iterator gsi
;
120 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
122 gimple
*stmt
= gsi_stmt (gsi
);
123 node_for_stmts
->m_stmts
.safe_push (stmt
);
124 m_stmt_to_node_t
.put (stmt
, node_for_stmts
);
125 if (cgraph_edge
*edge
= supergraph_call_edge (fun
, stmt
))
127 m_cgraph_edge_to_caller_prev_node
.put(edge
, node_for_stmts
);
128 node_for_stmts
= add_node (fun
, bb
, as_a
<gcall
*> (stmt
), NULL
);
129 m_cgraph_edge_to_caller_next_node
.put (edge
, node_for_stmts
);
133 m_bb_to_final_node
.put (bb
, node_for_stmts
);
136 const unsigned num_snodes
= m_nodes
.length () - start_idx
;
137 m_function_to_num_snodes
.put (fun
, num_snodes
);
141 const int end_idx
= m_nodes
.length () - 1;
142 logger
->log ("SN: %i...%i: function %qD",
143 start_idx
, end_idx
, fun
->decl
);
148 /* Second pass: make superedges. */
150 /* Make superedges for CFG edges. */
151 for (bb_to_node_t::iterator iter
= m_bb_to_final_node
.begin ();
152 iter
!= m_bb_to_final_node
.end ();
155 basic_block bb
= (*iter
).first
;
156 supernode
*src_supernode
= (*iter
).second
;
161 FOR_EACH_VEC_ELT (*bb
->succs
, idx
, cfg_edge
)
163 basic_block dest_cfg_block
= cfg_edge
->dest
;
164 supernode
*dest_supernode
165 = *m_bb_to_initial_node
.get (dest_cfg_block
);
166 cfg_superedge
*cfg_sedge
167 = add_cfg_edge (src_supernode
, dest_supernode
, cfg_edge
, idx
);
168 m_cfg_edge_to_cfg_superedge
.put (cfg_edge
, cfg_sedge
);
172 /* Make interprocedural superedges for calls. */
174 for (cgraph_edge_to_node_t::iterator iter
175 = m_cgraph_edge_to_caller_prev_node
.begin ();
176 iter
!= m_cgraph_edge_to_caller_prev_node
.end ();
179 cgraph_edge
*edge
= (*iter
).first
;
180 supernode
*caller_prev_supernode
= (*iter
).second
;
181 basic_block callee_cfg_block
182 = ENTRY_BLOCK_PTR_FOR_FN (edge
->callee
->get_fun ());
183 supernode
*callee_supernode
184 = *m_bb_to_initial_node
.get (callee_cfg_block
);
185 call_superedge
*sedge
186 = add_call_superedge (caller_prev_supernode
,
189 m_cgraph_edge_to_call_superedge
.put (edge
, sedge
);
193 /* Make interprocedural superedges for returns. */
195 for (cgraph_edge_to_node_t::iterator iter
196 = m_cgraph_edge_to_caller_next_node
.begin ();
197 iter
!= m_cgraph_edge_to_caller_next_node
.end ();
200 cgraph_edge
*edge
= (*iter
).first
;
201 supernode
*caller_next_supernode
= (*iter
).second
;
202 basic_block callee_cfg_block
203 = EXIT_BLOCK_PTR_FOR_FN (edge
->callee
->get_fun ());
204 supernode
*callee_supernode
205 = *m_bb_to_initial_node
.get (callee_cfg_block
);
206 return_superedge
*sedge
207 = add_return_superedge (callee_supernode
,
208 caller_next_supernode
,
210 m_cgraph_edge_to_return_superedge
.put (edge
, sedge
);
214 /* Make intraprocedural superedges linking the two halves of a call. */
216 for (cgraph_edge_to_node_t::iterator iter
217 = m_cgraph_edge_to_caller_prev_node
.begin ();
218 iter
!= m_cgraph_edge_to_caller_prev_node
.end ();
221 cgraph_edge
*edge
= (*iter
).first
;
222 supernode
*caller_prev_supernode
= (*iter
).second
;
223 supernode
*caller_next_supernode
224 = *m_cgraph_edge_to_caller_next_node
.get (edge
);
226 = new callgraph_superedge (caller_prev_supernode
,
227 caller_next_supernode
,
228 SUPEREDGE_INTRAPROCEDURAL_CALL
,
231 m_cgraph_edge_to_intraproc_superedge
.put (edge
, sedge
);
238 /* Dump this graph in .dot format to PP, using DUMP_ARGS.
239 Cluster the supernodes by function, then by BB from original CFG. */
242 supergraph::dump_dot_to_pp (pretty_printer
*pp
,
243 const dump_args_t
&dump_args
) const
245 graphviz_out
gv (pp
);
247 pp_string (pp
, "digraph \"");
248 pp_write_text_to_stream (pp
);
249 pp_string (pp
, "supergraph");
250 pp_write_text_as_dot_label_to_stream (pp
, /*for_record=*/false);
251 pp_string (pp
, "\" {\n");
254 gv
.println ("overlap=false;");
255 gv
.println ("compound=true;");
257 /* TODO: maybe (optionally) sub-subdivide by TU, for LTO; see also:
258 https://gcc-python-plugin.readthedocs.io/en/latest/_images/sample-supergraph.png
261 /* Break out the supernodes into clusters by function. */
264 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
266 function
*fun
= node
->get_fun ();
267 const char *funcname
= function_name (fun
);
268 gv
.println ("subgraph \"cluster_%s\" {",
277 /* Break out the nodes into clusters by BB from original CFG. */
280 FOR_ALL_BB_FN (bb
, fun
)
282 if (dump_args
.m_flags
& SUPERGRAPH_DOT_SHOW_BBS
)
284 gv
.println ("subgraph \"cluster_%s_bb_%i\" {",
285 funcname
, bb
->index
);
290 " label=\"bb: %i\";\n"),
294 // TODO: maybe keep an index per-function/per-bb to speed this up???
297 FOR_EACH_VEC_ELT (m_nodes
, i
, n
)
298 if (n
->m_fun
== fun
&& n
->m_bb
== bb
)
299 n
->dump_dot (&gv
, dump_args
);
301 if (dump_args
.m_flags
& SUPERGRAPH_DOT_SHOW_BBS
)
303 /* Terminate per-bb "subgraph" */
310 /* Add an invisible edge from ENTRY to EXIT, to improve the graph layout. */
311 pp_string (pp
, "\t");
312 get_node_for_function_entry (fun
)->dump_dot_id (pp
);
313 pp_string (pp
, ":s -> ");
314 get_node_for_function_exit (fun
)->dump_dot_id (pp
);
315 pp_string (pp
, ":n [style=\"invis\",constraint=true];\n");
317 /* Terminate per-function "subgraph" */
326 FOR_EACH_VEC_ELT (m_edges
, i
, e
)
327 e
->dump_dot (&gv
, dump_args
);
329 /* Terminate "digraph" */
334 /* Dump this graph in .dot format to FP, using DUMP_ARGS. */
337 supergraph::dump_dot_to_file (FILE *fp
, const dump_args_t
&dump_args
) const
339 pretty_printer
*pp
= global_dc
->printer
->clone ();
340 pp_show_color (pp
) = 0;
341 /* %qE in logs for SSA_NAMEs should show the ssa names, rather than
342 trying to prettify things by showing the underlying var. */
343 pp_format_decoder (pp
) = default_tree_printer
;
345 pp
->buffer
->stream
= fp
;
346 dump_dot_to_pp (pp
, dump_args
);
351 /* Dump this graph in .dot format to PATH, using DUMP_ARGS. */
354 supergraph::dump_dot (const char *path
, const dump_args_t
&dump_args
) const
356 FILE *fp
= fopen (path
, "w");
357 dump_dot_to_file (fp
, dump_args
);
361 /* Create a supernode for BB within FUN and add it to this supergraph.
363 If RETURNING_CALL is non-NULL, the supernode represents the resumption
364 of the basic block after returning from that call.
366 If PHI_NODES is non-NULL, this is the initial supernode for the basic
367 block, and is responsible for any handling of the phi nodes. */
370 supergraph::add_node (function
*fun
, basic_block bb
, gcall
*returning_call
,
371 gimple_seq phi_nodes
)
373 supernode
*n
= new supernode (fun
, bb
, returning_call
, phi_nodes
,
375 m_nodes
.safe_push (n
);
379 /* Create a new cfg_superedge from SRC to DEST for the underlying CFG edge E,
380 adding it to this supergraph.
382 If the edge is for a switch statement, create a switch_cfg_superedge
383 subclass using IDX (the index of E within the out-edges from SRC's
384 underlying basic block). */
387 supergraph::add_cfg_edge (supernode
*src
, supernode
*dest
, ::edge e
, int idx
)
389 /* Special-case switch edges. */
390 gimple
*stmt
= src
->get_last_stmt ();
391 cfg_superedge
*new_edge
;
392 if (stmt
&& stmt
->code
== GIMPLE_SWITCH
)
393 new_edge
= new switch_cfg_superedge (src
, dest
, e
, idx
);
395 new_edge
= new cfg_superedge (src
, dest
, e
);
400 /* Create and add a call_superedge representing an interprocedural call
401 from SRC to DEST, using CEDGE. */
404 supergraph::add_call_superedge (supernode
*src
, supernode
*dest
,
407 call_superedge
*new_edge
= new call_superedge (src
, dest
, cedge
);
412 /* Create and add a return_superedge representing returning from an
413 interprocedural call, returning from SRC to DEST, using CEDGE. */
416 supergraph::add_return_superedge (supernode
*src
, supernode
*dest
,
419 return_superedge
*new_edge
= new return_superedge (src
, dest
, cedge
);
424 /* Implementation of dnode::dump_dot vfunc for supernodes.
426 Write a cluster for the node, and within it a .dot node showing
427 the phi nodes and stmts. Call into any node annotator from ARGS to
428 potentially add other records to the cluster. */
431 supernode::dump_dot (graphviz_out
*gv
, const dump_args_t
&args
) const
433 gv
->println ("subgraph cluster_node_%i {",
437 gv
->println("style=\"solid\";");
438 gv
->println("color=\"black\";");
439 gv
->println("fillcolor=\"lightgrey\";");
440 gv
->println("label=\"sn: %i\";", m_index
);
442 pretty_printer
*pp
= gv
->get_pp ();
444 if (args
.m_node_annotator
)
445 args
.m_node_annotator
->add_node_annotations (gv
, *this);
450 " [shape=none,margin=0,style=filled,fillcolor=%s,label=<",
452 pp_string (pp
, "<TABLE BORDER=\"0\">");
453 pp_write_text_to_stream (pp
);
455 bool had_row
= false;
457 if (m_returning_call
)
460 pp_string (pp
, "returning call: ");
464 pp_gimple_stmt_1 (pp
, m_returning_call
, 0, (dump_flags_t
)0);
465 pp_write_text_as_html_like_dot_to_stream (pp
);
468 if (args
.m_node_annotator
)
469 args
.m_node_annotator
->add_stmt_annotations (gv
, m_returning_call
);
477 pp_string (pp
, "<TR><TD>ENTRY</TD></TR>");
484 pp_string (pp
, "<TR><TD>EXIT</TD></TR>");
490 for (gphi_iterator gpi
= const_cast<supernode
*> (this)->start_phis ();
491 !gsi_end_p (gpi
); gsi_next (&gpi
))
493 const gimple
*stmt
= gsi_stmt (gpi
);
495 pp_gimple_stmt_1 (pp
, stmt
, 0, (dump_flags_t
)0);
496 pp_write_text_as_html_like_dot_to_stream (pp
);
499 if (args
.m_node_annotator
)
500 args
.m_node_annotator
->add_stmt_annotations (gv
, stmt
);
509 FOR_EACH_VEC_ELT (m_stmts
, i
, stmt
)
512 pp_gimple_stmt_1 (pp
, stmt
, 0, (dump_flags_t
)0);
513 pp_write_text_as_html_like_dot_to_stream (pp
);
516 if (args
.m_node_annotator
)
517 args
.m_node_annotator
->add_stmt_annotations (gv
, stmt
);
523 /* Graphviz requires a TABLE element to have at least one TR
524 (and each TR to have at least one TD). */
527 pp_string (pp
, "<TR><TD>(empty)</TD></TR>");
531 pp_string (pp
, "</TABLE>>];\n\n");
534 /* Terminate "subgraph" */
539 /* Write an ID for this node to PP, for use in .dot output. */
542 supernode::dump_dot_id (pretty_printer
*pp
) const
544 pp_printf (pp
, "node_%i", m_index
);
547 /* Get a location_t for the start of this supernode. */
550 supernode::get_start_location () const
553 && get_pure_location (m_returning_call
->location
) != UNKNOWN_LOCATION
)
554 return m_returning_call
->location
;
558 FOR_EACH_VEC_ELT (m_stmts
, i
, stmt
)
559 if (get_pure_location (stmt
->location
) != UNKNOWN_LOCATION
)
560 return stmt
->location
;
564 // TWEAK: show the decl instead; this leads to more readable output:
565 return DECL_SOURCE_LOCATION (m_fun
->decl
);
567 return m_fun
->function_start_locus
;
570 return m_fun
->function_end_locus
;
572 return UNKNOWN_LOCATION
;
575 /* Get a location_t for the end of this supernode. */
578 supernode::get_end_location () const
582 FOR_EACH_VEC_ELT_REVERSE (m_stmts
, i
, stmt
)
583 if (get_pure_location (stmt
->location
) != UNKNOWN_LOCATION
)
584 return stmt
->location
;
587 && get_pure_location (m_returning_call
->location
) != UNKNOWN_LOCATION
)
588 return m_returning_call
->location
;
591 return m_fun
->function_start_locus
;
593 return m_fun
->function_end_locus
;
595 return UNKNOWN_LOCATION
;
598 /* Given STMT within this supernode, return its index within m_stmts. */
601 supernode::get_stmt_index (const gimple
*stmt
) const
605 FOR_EACH_VEC_ELT (m_stmts
, i
, iter_stmt
)
606 if (iter_stmt
== stmt
)
611 /* Implementation of dedge::dump_dot for superedges.
612 Write a .dot edge to GV representing this superedge. */
615 superedge::dump_dot (graphviz_out
*gv
, const dump_args_t
&) const
617 const char *style
= "\"solid,bold\"";
618 const char *color
= "black";
620 const char *constraint
= "true";
626 case SUPEREDGE_CFG_EDGE
:
631 case SUPEREDGE_RETURN
:
634 case SUPEREDGE_INTRAPROCEDURAL_CALL
:
635 style
= "\"dotted\"";
639 /* Adapted from graph.c:draw_cfg_node_succ_edges. */
640 if (::edge cfg_edge
= get_any_cfg_edge ())
642 if (cfg_edge
->flags
& EDGE_FAKE
)
648 else if (cfg_edge
->flags
& EDGE_DFS_BACK
)
650 style
= "\"dotted,bold\"";
654 else if (cfg_edge
->flags
& EDGE_FALLTHRU
)
660 if (cfg_edge
->flags
& EDGE_ABNORMAL
)
666 pretty_printer
*pp
= gv
->get_pp ();
668 m_src
->dump_dot_id (pp
);
669 pp_string (pp
, " -> ");
670 m_dest
->dump_dot_id (pp
);
672 (" [style=%s, color=%s, weight=%d, constraint=%s,"
673 " ltail=\"cluster_node_%i\", lhead=\"cluster_node_%i\""
675 style
, color
, weight
, constraint
,
676 m_src
->m_index
, m_dest
->m_index
);
678 dump_label_to_pp (pp
, false);
680 pp_printf (pp
, "\"];\n");
683 /* If this is an intraprocedural superedge, return the associated
684 CFG edge. Otherwise, return NULL. */
687 superedge::get_any_cfg_edge () const
689 if (const cfg_superedge
*sub
= dyn_cast_cfg_superedge ())
690 return sub
->get_cfg_edge ();
694 /* If this is an interprocedural superedge, return the associated
695 cgraph_edge *. Otherwise, return NULL. */
698 superedge::get_any_callgraph_edge () const
700 if (const callgraph_superedge
*sub
= dyn_cast_callgraph_superedge ())
705 /* Build a description of this superedge (e.g. "true" for the true
706 edge of a conditional, or "case 42:" for a switch case).
708 The caller is responsible for freeing the result.
710 If USER_FACING is false, the result also contains any underlying
711 CFG edge flags. e.g. " (flags FALLTHRU | DFS_BACK)". */
714 superedge::get_description (bool user_facing
) const
717 dump_label_to_pp (&pp
, user_facing
);
718 return xstrdup (pp_formatted_text (&pp
));
721 /* Implementation of superedge::dump_label_to_pp for non-switch CFG
724 For true/false edges, print "true" or "false" to PP.
726 If USER_FACING is false, also print flags on the underlying CFG edge to
730 cfg_superedge::dump_label_to_pp (pretty_printer
*pp
,
731 bool user_facing
) const
734 pp_printf (pp
, "true");
735 else if (false_value_p ())
736 pp_printf (pp
, "false");
741 /* Express edge flags as a string with " | " separator.
742 e.g. " (flags FALLTHRU | DFS_BACK)". */
745 pp_string (pp
, " (flags ");
746 bool seen_flag
= false;
747 #define DEF_EDGE_FLAG(NAME,IDX) \
749 if (get_flags () & EDGE_##NAME) \
752 pp_string (pp, " | "); \
753 pp_printf (pp, "%s", (#NAME)); \
757 #include "cfg-flags.def"
762 /* Otherwise, no label. */
765 /* Get the phi argument for PHI for this CFG edge. */
768 cfg_superedge::get_phi_arg (const gphi
*phi
) const
770 size_t index
= m_cfg_edge
->dest_idx
;
771 return gimple_phi_arg_def (phi
, index
);
774 /* Implementation of superedge::dump_label_to_pp for CFG superedges for
777 Print "case VAL:", "case LOWER ... UPPER:", or "default:" to PP. */
780 switch_cfg_superedge::dump_label_to_pp (pretty_printer
*pp
,
781 bool user_facing ATTRIBUTE_UNUSED
) const
783 tree case_label
= get_case_label ();
784 gcc_assert (TREE_CODE (case_label
) == CASE_LABEL_EXPR
);
785 tree lower_bound
= CASE_LOW (case_label
);
786 tree upper_bound
= CASE_HIGH (case_label
);
789 pp_printf (pp
, "case ");
790 dump_generic_node (pp
, lower_bound
, 0, (dump_flags_t
)0, false);
793 pp_printf (pp
, " ... ");
794 dump_generic_node (pp
, upper_bound
, 0, (dump_flags_t
)0, false);
799 pp_printf (pp
, "default:");
802 /* Get the case label for this "switch" superedge. */
805 switch_cfg_superedge::get_case_label () const
807 return gimple_switch_label (get_switch_stmt (), m_idx
);
810 /* Implementation of superedge::dump_label_to_pp for interprocedural
814 callgraph_superedge::dump_label_to_pp (pretty_printer
*pp
,
815 bool user_facing ATTRIBUTE_UNUSED
) const
820 case SUPEREDGE_CFG_EDGE
:
824 pp_printf (pp
, "call");
827 case SUPEREDGE_RETURN
:
828 pp_printf (pp
, "return");
831 case SUPEREDGE_INTRAPROCEDURAL_CALL
:
832 pp_printf (pp
, "intraproc link");
837 /* Get the function that was called at this interprocedural call/return
841 callgraph_superedge::get_callee_function () const
843 return m_cedge
->callee
->get_fun ();
846 /* Get the calling function at this interprocedural call/return edge. */
849 callgraph_superedge::get_caller_function () const
851 return m_cedge
->caller
->get_fun ();
854 /* Get the fndecl that was called at this interprocedural call/return
858 callgraph_superedge::get_callee_decl () const
860 return get_callee_function ()->decl
;
863 /* Get the calling fndecl at this interprocedural call/return edge. */
866 callgraph_superedge::get_caller_decl () const
868 return get_caller_function ()->decl
;
871 /* Given PARM_TO_FIND, a PARM_DECL, identify its index (writing it
872 to *OUT if OUT is non-NULL), and return the corresponding argument
876 callgraph_superedge::get_arg_for_parm (tree parm_to_find
,
877 callsite_expr
*out
) const
879 gcc_assert (TREE_CODE (parm_to_find
) == PARM_DECL
);
881 tree callee
= get_callee_decl ();
884 for (tree iter_parm
= DECL_ARGUMENTS (callee
); iter_parm
;
885 iter_parm
= DECL_CHAIN (iter_parm
), ++i
)
887 if (iter_parm
== parm_to_find
)
890 *out
= callsite_expr::from_zero_based_param (i
);
891 return gimple_call_arg (get_call_stmt (), i
);
899 /* Look for a use of ARG_TO_FIND as an argument at this callsite.
900 If found, return the default SSA def of the corresponding parm within
901 the callee, and if OUT is non-NULL, write the index to *OUT.
902 Only the first match is handled. */
905 callgraph_superedge::get_parm_for_arg (tree arg_to_find
,
906 callsite_expr
*out
) const
908 tree callee
= get_callee_decl ();
911 for (tree iter_parm
= DECL_ARGUMENTS (callee
); iter_parm
;
912 iter_parm
= DECL_CHAIN (iter_parm
), ++i
)
914 tree param
= gimple_call_arg (get_call_stmt (), i
);
915 if (arg_to_find
== param
)
918 *out
= callsite_expr::from_zero_based_param (i
);
919 return ssa_default_def (get_callee_function (), iter_parm
);
927 /* Map caller_expr back to an expr within the callee, or return NULL_TREE.
928 If non-NULL is returned, populate OUT. */
931 callgraph_superedge::map_expr_from_caller_to_callee (tree caller_expr
,
932 callsite_expr
*out
) const
934 /* Is it an argument (actual param)? If so, convert to
935 parameter (formal param). */
936 tree parm
= get_parm_for_arg (caller_expr
, out
);
939 /* Otherwise try return value. */
940 if (caller_expr
== gimple_call_lhs (get_call_stmt ()))
943 *out
= callsite_expr::from_return_value ();
944 return DECL_RESULT (get_callee_decl ());
950 /* Map callee_expr back to an expr within the caller, or return NULL_TREE.
951 If non-NULL is returned, populate OUT. */
954 callgraph_superedge::map_expr_from_callee_to_caller (tree callee_expr
,
955 callsite_expr
*out
) const
957 if (callee_expr
== NULL_TREE
)
960 /* If it's a parameter (formal param), get the argument (actual param). */
961 if (TREE_CODE (callee_expr
) == PARM_DECL
)
962 return get_arg_for_parm (callee_expr
, out
);
964 /* Similar for the default SSA name of the PARM_DECL. */
965 if (TREE_CODE (callee_expr
) == SSA_NAME
966 && SSA_NAME_IS_DEFAULT_DEF (callee_expr
)
967 && TREE_CODE (SSA_NAME_VAR (callee_expr
)) == PARM_DECL
)
968 return get_arg_for_parm (SSA_NAME_VAR (callee_expr
), out
);
970 /* Otherwise try return value. */
971 if (callee_expr
== DECL_RESULT (get_callee_decl ()))
974 *out
= callsite_expr::from_return_value ();
975 return gimple_call_lhs (get_call_stmt ());
983 #endif /* #if ENABLE_ANALYZER */