libstdc++: Simplify std::any to fix -Wdeprecated-declarations warning
[official-gcc.git] / gcc / analyzer / supergraph.cc
blob68d83bb914a70c4866777e7ddead74380685bc63
1 /* "Supergraph" classes that combine CFGs and callgraph into one digraph.
2 Copyright (C) 2019-2024 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)
10 any later version.
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/>. */
21 #include "config.h"
22 #define INCLUDE_MEMORY
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tree.h"
26 #include "tm.h"
27 #include "toplev.h"
28 #include "hash-table.h"
29 #include "vec.h"
30 #include "ggc.h"
31 #include "basic-block.h"
32 #include "function.h"
33 #include "gimple.h"
34 #include "gimple-iterator.h"
35 #include "gimple-fold.h"
36 #include "tree-eh.h"
37 #include "gimple-expr.h"
38 #include "is-a.h"
39 #include "timevar.h"
40 #include "gimple-pretty-print.h"
41 #include "tree-pretty-print.h"
42 #include "graphviz.h"
43 #include "cgraph.h"
44 #include "tree-dfa.h"
45 #include "bitmap.h"
46 #include "cfganal.h"
47 #include "function.h"
48 #include "analyzer/analyzer.h"
49 #include "ordered-hash-map.h"
50 #include "options.h"
51 #include "cgraph.h"
52 #include "cfg.h"
53 #include "digraph.h"
54 #include "tree-cfg.h"
55 #include "analyzer/supergraph.h"
56 #include "analyzer/analyzer-logging.h"
58 #if ENABLE_ANALYZER
60 namespace ana {
62 /* Get the function of the ultimate alias target being called at EDGE,
63 if any. */
65 function *
66 get_ultimate_function_for_cgraph_edge (cgraph_edge *edge)
68 cgraph_node *ultimate_node = edge->callee->ultimate_alias_target ();
69 if (!ultimate_node)
70 return NULL;
71 return ultimate_node->get_fun ();
74 /* Get the cgraph_edge, but only if there's an underlying function body. */
76 cgraph_edge *
77 supergraph_call_edge (function *fun, const gimple *stmt)
79 const gcall *call = dyn_cast<const gcall *> (stmt);
80 if (!call)
81 return NULL;
82 cgraph_edge *edge
83 = cgraph_node::get (fun->decl)->get_edge (const_cast <gimple *> (stmt));
84 if (!edge)
85 return NULL;
86 if (!edge->callee)
87 return NULL; /* e.g. for a function pointer. */
88 if (!get_ultimate_function_for_cgraph_edge (edge))
89 return NULL;
90 return edge;
93 /* class saved_uids.
95 In order to ensure consistent results without relying on the ordering
96 of pointer values we assign a uid to each gimple stmt, globally unique
97 across all functions.
99 Normally, the stmt uids are a scratch space that each pass can freely
100 assign its own values to. However, in the case of LTO, the uids are
101 used to associate call stmts with callgraph edges between the WPA phase
102 (where the analyzer runs in LTO mode) and the LTRANS phase; if the
103 analyzer changes them in the WPA phase, it leads to errors when
104 streaming the code back in at LTRANS.
105 lto_prepare_function_for_streaming has code to renumber the stmt UIDs
106 when the code is streamed back out, but for some reason this isn't
107 called for clones.
109 Hence, as a workaround, this class has responsibility for tracking
110 the original uids and restoring them once the pass is complete
111 (in the supergraph dtor). */
113 /* Give STMT a globally unique uid, storing its original uid so it can
114 later be restored. */
116 void
117 saved_uids::make_uid_unique (gimple *stmt)
119 unsigned next_uid = m_old_stmt_uids.length ();
120 unsigned old_stmt_uid = stmt->uid;
121 stmt->uid = next_uid;
122 m_old_stmt_uids.safe_push
123 (std::pair<gimple *, unsigned> (stmt, old_stmt_uid));
126 /* Restore the saved uids of all stmts. */
128 void
129 saved_uids::restore_uids () const
131 unsigned i;
132 std::pair<gimple *, unsigned> *pair;
133 FOR_EACH_VEC_ELT (m_old_stmt_uids, i, pair)
134 pair->first->uid = pair->second;
137 /* supergraph's ctor. Walk the callgraph, building supernodes for each
138 CFG basic block, splitting the basic blocks at callsites. Join
139 together the supernodes with interprocedural and intraprocedural
140 superedges as appropriate.
141 Assign UIDs to the gimple stmts. */
143 supergraph::supergraph (logger *logger)
145 auto_timevar tv (TV_ANALYZER_SUPERGRAPH);
147 LOG_FUNC (logger);
149 /* First pass: make supernodes (and assign UIDs to the gimple stmts). */
151 /* Sort the cgraph_nodes? */
152 cgraph_node *node;
153 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
155 function *fun = node->get_fun ();
157 /* Ensure that EDGE_DFS_BACK is correct for every CFG edge in
158 the supergraph (by doing it per-function). */
159 auto_cfun sentinel (fun);
160 mark_dfs_back_edges ();
162 const int start_idx = m_nodes.length ();
164 basic_block bb;
165 FOR_ALL_BB_FN (bb, fun)
167 /* The initial supernode for the BB gets the phi nodes (if any). */
168 supernode *node_for_stmts = add_node (fun, bb, NULL, phi_nodes (bb));
169 m_bb_to_initial_node.put (bb, node_for_stmts);
170 for (gphi_iterator gpi = gsi_start_phis (bb); !gsi_end_p (gpi);
171 gsi_next (&gpi))
173 gimple *stmt = gsi_stmt (gpi);
174 m_stmt_to_node_t.put (stmt, node_for_stmts);
175 m_stmt_uids.make_uid_unique (stmt);
178 /* Append statements from BB to the current supernode, splitting
179 them into a new supernode at each call site; such call statements
180 appear in both supernodes (representing call and return). */
181 gimple_stmt_iterator gsi;
182 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
184 gimple *stmt = gsi_stmt (gsi);
185 /* Discard debug stmts here, so we don't have to check for
186 them anywhere within the analyzer. */
187 if (is_gimple_debug (stmt))
188 continue;
189 node_for_stmts->m_stmts.safe_push (stmt);
190 m_stmt_to_node_t.put (stmt, node_for_stmts);
191 m_stmt_uids.make_uid_unique (stmt);
192 if (cgraph_edge *edge = supergraph_call_edge (fun, stmt))
194 m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts);
195 node_for_stmts = add_node (fun, bb, as_a <gcall *> (stmt),
196 NULL);
197 m_cgraph_edge_to_caller_next_node.put (edge, node_for_stmts);
199 else
201 // maybe call is via a function pointer
202 if (gcall *call = dyn_cast<gcall *> (stmt))
204 cgraph_edge *edge
205 = cgraph_node::get (fun->decl)->get_edge (stmt);
206 if (!edge || !edge->callee)
208 supernode *old_node_for_stmts = node_for_stmts;
209 node_for_stmts = add_node (fun, bb, call, NULL);
211 superedge *sedge
212 = new callgraph_superedge (old_node_for_stmts,
213 node_for_stmts,
214 SUPEREDGE_INTRAPROCEDURAL_CALL,
215 NULL);
216 add_edge (sedge);
222 m_bb_to_final_node.put (bb, node_for_stmts);
225 const unsigned num_snodes = m_nodes.length () - start_idx;
226 m_function_to_num_snodes.put (fun, num_snodes);
228 if (logger)
230 const int end_idx = m_nodes.length () - 1;
231 logger->log ("SN: %i...%i: function %qD",
232 start_idx, end_idx, fun->decl);
237 /* Second pass: make superedges. */
239 /* Make superedges for CFG edges. */
240 for (bb_to_node_t::iterator iter = m_bb_to_final_node.begin ();
241 iter != m_bb_to_final_node.end ();
242 ++iter)
244 basic_block bb = (*iter).first;
245 supernode *src_supernode = (*iter).second;
247 ::edge cfg_edge;
248 int idx;
249 if (bb->succs)
250 FOR_EACH_VEC_ELT (*bb->succs, idx, cfg_edge)
252 basic_block dest_cfg_block = cfg_edge->dest;
253 supernode *dest_supernode
254 = *m_bb_to_initial_node.get (dest_cfg_block);
255 cfg_superedge *cfg_sedge
256 = add_cfg_edge (src_supernode, dest_supernode, cfg_edge);
257 m_cfg_edge_to_cfg_superedge.put (cfg_edge, cfg_sedge);
261 /* Make interprocedural superedges for calls. */
263 for (cgraph_edge_to_node_t::iterator iter
264 = m_cgraph_edge_to_caller_prev_node.begin ();
265 iter != m_cgraph_edge_to_caller_prev_node.end ();
266 ++iter)
268 cgraph_edge *edge = (*iter).first;
269 supernode *caller_prev_supernode = (*iter).second;
270 function* callee_fn = get_ultimate_function_for_cgraph_edge (edge);
271 if (!callee_fn || !callee_fn->cfg)
272 continue;
273 basic_block callee_cfg_block = ENTRY_BLOCK_PTR_FOR_FN (callee_fn);
274 supernode *callee_supernode
275 = *m_bb_to_initial_node.get (callee_cfg_block);
276 call_superedge *sedge
277 = add_call_superedge (caller_prev_supernode,
278 callee_supernode,
279 edge);
280 m_cgraph_edge_to_call_superedge.put (edge, sedge);
284 /* Make interprocedural superedges for returns. */
286 for (cgraph_edge_to_node_t::iterator iter
287 = m_cgraph_edge_to_caller_next_node.begin ();
288 iter != m_cgraph_edge_to_caller_next_node.end ();
289 ++iter)
291 cgraph_edge *edge = (*iter).first;
292 supernode *caller_next_supernode = (*iter).second;
293 function* callee_fn = get_ultimate_function_for_cgraph_edge (edge);
294 if (!callee_fn || !callee_fn->cfg)
295 continue;
296 basic_block callee_cfg_block = EXIT_BLOCK_PTR_FOR_FN (callee_fn);
297 supernode *callee_supernode
298 = *m_bb_to_initial_node.get (callee_cfg_block);
299 return_superedge *sedge
300 = add_return_superedge (callee_supernode,
301 caller_next_supernode,
302 edge);
303 m_cgraph_edge_to_return_superedge.put (edge, sedge);
307 /* Make intraprocedural superedges linking the two halves of a call. */
309 for (cgraph_edge_to_node_t::iterator iter
310 = m_cgraph_edge_to_caller_prev_node.begin ();
311 iter != m_cgraph_edge_to_caller_prev_node.end ();
312 ++iter)
314 cgraph_edge *edge = (*iter).first;
315 supernode *caller_prev_supernode = (*iter).second;
316 supernode *caller_next_supernode
317 = *m_cgraph_edge_to_caller_next_node.get (edge);
318 superedge *sedge
319 = new callgraph_superedge (caller_prev_supernode,
320 caller_next_supernode,
321 SUPEREDGE_INTRAPROCEDURAL_CALL,
322 edge);
323 add_edge (sedge);
324 m_cgraph_edge_to_intraproc_superedge.put (edge, sedge);
331 /* supergraph's dtor. Reset stmt uids. */
333 supergraph::~supergraph ()
335 m_stmt_uids.restore_uids ();
338 /* Dump this graph in .dot format to PP, using DUMP_ARGS.
339 Cluster the supernodes by function, then by BB from original CFG. */
341 void
342 supergraph::dump_dot_to_pp (pretty_printer *pp,
343 const dump_args_t &dump_args) const
345 graphviz_out gv (pp);
347 pp_string (pp, "digraph \"");
348 pp_write_text_to_stream (pp);
349 pp_string (pp, "supergraph");
350 pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/false);
351 pp_string (pp, "\" {\n");
352 gv.indent ();
354 gv.println ("overlap=false;");
355 gv.println ("compound=true;");
357 /* TODO: maybe (optionally) sub-subdivide by TU, for LTO; see also:
358 https://gcc-python-plugin.readthedocs.io/en/latest/_images/sample-supergraph.png
361 /* Break out the supernodes into clusters by function. */
363 cgraph_node *node;
364 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
366 function *fun = node->get_fun ();
367 gcc_assert (fun);
368 const char *funcname = function_name (fun);
369 gv.println ("subgraph \"cluster_%s\" {",
370 funcname);
371 gv.indent ();
372 pp_printf (pp,
373 ("style=\"dashed\";"
374 " color=\"black\";"
375 " label=\"%s\";\n"),
376 funcname);
378 /* Break out the nodes into clusters by BB from original CFG. */
380 basic_block bb;
381 FOR_ALL_BB_FN (bb, fun)
383 if (dump_args.m_flags & SUPERGRAPH_DOT_SHOW_BBS)
385 gv.println ("subgraph \"cluster_%s_bb_%i\" {",
386 funcname, bb->index);
387 gv.indent ();
388 pp_printf (pp,
389 ("style=\"dashed\";"
390 " color=\"black\";"
391 " label=\"bb: %i\";\n"),
392 bb->index);
395 // TODO: maybe keep an index per-function/per-bb to speed this up???
396 int i;
397 supernode *n;
398 FOR_EACH_VEC_ELT (m_nodes, i, n)
399 if (n->m_fun == fun && n->m_bb == bb)
400 n->dump_dot (&gv, dump_args);
402 if (dump_args.m_flags & SUPERGRAPH_DOT_SHOW_BBS)
404 /* Terminate per-bb "subgraph" */
405 gv.outdent ();
406 gv.println ("}");
411 /* Add an invisible edge from ENTRY to EXIT, to improve the graph layout. */
412 pp_string (pp, "\t");
413 get_node_for_function_entry (*fun)->dump_dot_id (pp);
414 pp_string (pp, ":s -> ");
415 get_node_for_function_exit (*fun)->dump_dot_id (pp);
416 pp_string (pp, ":n [style=\"invis\",constraint=true];\n");
418 /* Terminate per-function "subgraph" */
419 gv.outdent ();
420 gv.println ("}");
424 /* Superedges. */
425 int i;
426 superedge *e;
427 FOR_EACH_VEC_ELT (m_edges, i, e)
428 e->dump_dot (&gv, dump_args);
430 /* Terminate "digraph" */
431 gv.outdent ();
432 gv.println ("}");
435 /* Dump this graph in .dot format to FP, using DUMP_ARGS. */
437 void
438 supergraph::dump_dot_to_file (FILE *fp, const dump_args_t &dump_args) const
440 pretty_printer *pp = global_dc->printer->clone ();
441 pp_show_color (pp) = 0;
442 /* %qE in logs for SSA_NAMEs should show the ssa names, rather than
443 trying to prettify things by showing the underlying var. */
444 pp_format_decoder (pp) = default_tree_printer;
446 pp->set_output_stream (fp);
447 dump_dot_to_pp (pp, dump_args);
448 pp_flush (pp);
449 delete pp;
452 /* Dump this graph in .dot format to PATH, using DUMP_ARGS. */
454 void
455 supergraph::dump_dot (const char *path, const dump_args_t &dump_args) const
457 FILE *fp = fopen (path, "w");
458 dump_dot_to_file (fp, dump_args);
459 fclose (fp);
462 /* Return a new json::object of the form
463 {"nodes" : [objs for snodes],
464 "edges" : [objs for sedges]}. */
466 json::object *
467 supergraph::to_json () const
469 json::object *sgraph_obj = new json::object ();
471 /* Nodes. */
473 json::array *nodes_arr = new json::array ();
474 unsigned i;
475 supernode *n;
476 FOR_EACH_VEC_ELT (m_nodes, i, n)
477 nodes_arr->append (n->to_json ());
478 sgraph_obj->set ("nodes", nodes_arr);
481 /* Edges. */
483 json::array *edges_arr = new json::array ();
484 unsigned i;
485 superedge *n;
486 FOR_EACH_VEC_ELT (m_edges, i, n)
487 edges_arr->append (n->to_json ());
488 sgraph_obj->set ("edges", edges_arr);
491 return sgraph_obj;
494 /* Create a supernode for BB within FUN and add it to this supergraph.
496 If RETURNING_CALL is non-NULL, the supernode represents the resumption
497 of the basic block after returning from that call.
499 If PHI_NODES is non-NULL, this is the initial supernode for the basic
500 block, and is responsible for any handling of the phi nodes. */
502 supernode *
503 supergraph::add_node (function *fun, basic_block bb, gcall *returning_call,
504 gimple_seq phi_nodes)
506 supernode *n = new supernode (fun, bb, returning_call, phi_nodes,
507 m_nodes.length ());
508 m_nodes.safe_push (n);
509 return n;
512 /* Create a new cfg_superedge from SRC to DEST for the underlying CFG edge E,
513 adding it to this supergraph.
515 If the edge is for a switch statement, create a switch_cfg_superedge
516 subclass. */
518 cfg_superedge *
519 supergraph::add_cfg_edge (supernode *src, supernode *dest, ::edge e)
521 /* Special-case switch edges. */
522 gimple *stmt = src->get_last_stmt ();
523 cfg_superedge *new_edge;
524 if (stmt && stmt->code == GIMPLE_SWITCH)
525 new_edge = new switch_cfg_superedge (src, dest, e);
526 else
527 new_edge = new cfg_superedge (src, dest, e);
528 add_edge (new_edge);
529 return new_edge;
532 /* Create and add a call_superedge representing an interprocedural call
533 from SRC to DEST, using CEDGE. */
535 call_superedge *
536 supergraph::add_call_superedge (supernode *src, supernode *dest,
537 cgraph_edge *cedge)
539 call_superedge *new_edge = new call_superedge (src, dest, cedge);
540 add_edge (new_edge);
541 return new_edge;
544 /* Create and add a return_superedge representing returning from an
545 interprocedural call, returning from SRC to DEST, using CEDGE. */
547 return_superedge *
548 supergraph::add_return_superedge (supernode *src, supernode *dest,
549 cgraph_edge *cedge)
551 return_superedge *new_edge = new return_superedge (src, dest, cedge);
552 add_edge (new_edge);
553 return new_edge;
556 /* Implementation of dnode::dump_dot vfunc for supernodes.
558 Write a cluster for the node, and within it a .dot node showing
559 the phi nodes and stmts. Call into any node annotator from ARGS to
560 potentially add other records to the cluster. */
562 void
563 supernode::dump_dot (graphviz_out *gv, const dump_args_t &args) const
565 gv->println ("subgraph cluster_node_%i {",
566 m_index);
567 gv->indent ();
569 gv->println("style=\"solid\";");
570 gv->println("color=\"black\";");
571 gv->println("fillcolor=\"lightgrey\";");
572 gv->println("label=\"sn: %i (bb: %i)\";", m_index, m_bb->index);
574 pretty_printer *pp = gv->get_pp ();
576 if (args.m_node_annotator)
577 args.m_node_annotator->add_node_annotations (gv, *this, false);
579 gv->write_indent ();
580 dump_dot_id (pp);
581 pp_printf (pp,
582 " [shape=none,margin=0,style=filled,fillcolor=%s,label=<",
583 "lightgrey");
584 pp_string (pp, "<TABLE BORDER=\"0\">");
585 pp_write_text_to_stream (pp);
587 bool had_row = false;
589 /* Give any annotator the chance to add its own per-node TR elements. */
590 if (args.m_node_annotator)
591 if (args.m_node_annotator->add_node_annotations (gv, *this, true))
592 had_row = true;
594 if (m_returning_call)
596 gv->begin_trtd ();
597 pp_string (pp, "returning call: ");
598 gv->end_tdtr ();
600 gv->begin_tr ();
601 gv->begin_td ();
602 pp_gimple_stmt_1 (pp, m_returning_call, 0, (dump_flags_t)0);
603 pp_write_text_as_html_like_dot_to_stream (pp);
604 gv->end_td ();
605 /* Give any annotator the chance to add per-stmt TD elements to
606 this row. */
607 if (args.m_node_annotator)
608 args.m_node_annotator->add_stmt_annotations (gv, m_returning_call,
609 true);
610 gv->end_tr ();
612 /* Give any annotator the chance to add per-stmt TR elements. */
613 if (args.m_node_annotator)
614 args.m_node_annotator->add_stmt_annotations (gv, m_returning_call,
615 false);
616 pp_newline (pp);
618 had_row = true;
621 if (entry_p ())
623 pp_string (pp, "<TR><TD>ENTRY</TD></TR>");
624 pp_newline (pp);
625 had_row = true;
628 if (return_p ())
630 pp_string (pp, "<TR><TD>EXIT</TD></TR>");
631 pp_newline (pp);
632 had_row = true;
635 /* Phi nodes. */
636 for (gphi_iterator gpi = const_cast<supernode *> (this)->start_phis ();
637 !gsi_end_p (gpi); gsi_next (&gpi))
639 const gimple *stmt = gsi_stmt (gpi);
640 gv->begin_tr ();
641 gv->begin_td ();
642 pp_gimple_stmt_1 (pp, stmt, 0, (dump_flags_t)0);
643 pp_write_text_as_html_like_dot_to_stream (pp);
644 gv->end_td ();
645 /* Give any annotator the chance to add per-phi TD elements to
646 this row. */
647 if (args.m_node_annotator)
648 args.m_node_annotator->add_stmt_annotations (gv, stmt, true);
649 gv->end_tr ();
651 /* Give any annotator the chance to add per-phi TR elements. */
652 if (args.m_node_annotator)
653 args.m_node_annotator->add_stmt_annotations (gv, stmt, false);
655 pp_newline (pp);
656 had_row = true;
659 /* Statements. */
660 int i;
661 gimple *stmt;
662 FOR_EACH_VEC_ELT (m_stmts, i, stmt)
664 gv->begin_tr ();
665 gv->begin_td ();
666 pp_gimple_stmt_1 (pp, stmt, 0, (dump_flags_t)0);
667 pp_write_text_as_html_like_dot_to_stream (pp);
668 gv->end_td ();
669 /* Give any annotator the chance to add per-stmt TD elements to
670 this row. */
671 if (args.m_node_annotator)
672 args.m_node_annotator->add_stmt_annotations (gv, stmt, true);
673 gv->end_tr ();
675 /* Give any annotator the chance to add per-stmt TR elements. */
676 if (args.m_node_annotator)
677 args.m_node_annotator->add_stmt_annotations (gv, stmt, false);
679 pp_newline (pp);
680 had_row = true;
683 /* Give any annotator the chance to add additional per-node TR elements
684 to the end of the TABLE. */
685 if (args.m_node_annotator)
686 if (args.m_node_annotator->add_after_node_annotations (gv, *this))
687 had_row = true;
689 /* Graphviz requires a TABLE element to have at least one TR
690 (and each TR to have at least one TD). */
691 if (!had_row)
693 pp_string (pp, "<TR><TD>(empty)</TD></TR>");
694 pp_newline (pp);
697 pp_string (pp, "</TABLE>>];\n\n");
698 pp_flush (pp);
700 /* Terminate "subgraph" */
701 gv->outdent ();
702 gv->println ("}");
705 /* Write an ID for this node to PP, for use in .dot output. */
707 void
708 supernode::dump_dot_id (pretty_printer *pp) const
710 pp_printf (pp, "node_%i", m_index);
713 /* Return a new json::object of the form
714 {"idx": int,
715 "fun": optional str
716 "bb_idx": int,
717 "returning_call": optional str,
718 "phis": [str],
719 "stmts" : [str]}. */
721 json::object *
722 supernode::to_json () const
724 json::object *snode_obj = new json::object ();
726 snode_obj->set_integer ("idx", m_index);
727 snode_obj->set_integer ("bb_idx", m_bb->index);
728 if (function *fun = get_function ())
729 snode_obj->set_string ("fun", function_name (fun));
731 if (m_returning_call)
733 pretty_printer pp;
734 pp_format_decoder (&pp) = default_tree_printer;
735 pp_gimple_stmt_1 (&pp, m_returning_call, 0, (dump_flags_t)0);
736 snode_obj->set_string ("returning_call", pp_formatted_text (&pp));
739 /* Phi nodes. */
741 json::array *phi_arr = new json::array ();
742 for (gphi_iterator gpi = const_cast<supernode *> (this)->start_phis ();
743 !gsi_end_p (gpi); gsi_next (&gpi))
745 const gimple *stmt = gsi_stmt (gpi);
746 pretty_printer pp;
747 pp_format_decoder (&pp) = default_tree_printer;
748 pp_gimple_stmt_1 (&pp, stmt, 0, (dump_flags_t)0);
749 phi_arr->append_string (pp_formatted_text (&pp));
751 snode_obj->set ("phis", phi_arr);
754 /* Statements. */
756 json::array *stmt_arr = new json::array ();
757 int i;
758 gimple *stmt;
759 FOR_EACH_VEC_ELT (m_stmts, i, stmt)
761 pretty_printer pp;
762 pp_format_decoder (&pp) = default_tree_printer;
763 pp_gimple_stmt_1 (&pp, stmt, 0, (dump_flags_t)0);
764 stmt_arr->append_string (pp_formatted_text (&pp));
766 snode_obj->set ("stmts", stmt_arr);
769 return snode_obj;
772 /* Get a location_t for the start of this supernode. */
774 location_t
775 supernode::get_start_location () const
777 if (m_returning_call
778 && get_pure_location (m_returning_call->location) != UNKNOWN_LOCATION)
779 return m_returning_call->location;
781 int i;
782 gimple *stmt;
783 FOR_EACH_VEC_ELT (m_stmts, i, stmt)
784 if (get_pure_location (stmt->location) != UNKNOWN_LOCATION)
785 return stmt->location;
787 if (entry_p ())
789 // TWEAK: show the decl instead; this leads to more readable output:
790 return DECL_SOURCE_LOCATION (m_fun->decl);
792 return m_fun->function_start_locus;
794 if (return_p ())
795 return m_fun->function_end_locus;
797 /* We have no locations for stmts. If we have a single out-edge that's
798 a CFG edge, the goto_locus of that edge is a better location for this
799 than UNKNOWN_LOCATION. */
800 if (m_succs.length () == 1)
801 if (const cfg_superedge *cfg_sedge = m_succs[0]->dyn_cast_cfg_superedge ())
802 return cfg_sedge->get_goto_locus ();
804 return UNKNOWN_LOCATION;
807 /* Get a location_t for the end of this supernode. */
809 location_t
810 supernode::get_end_location () const
812 int i;
813 gimple *stmt;
814 FOR_EACH_VEC_ELT_REVERSE (m_stmts, i, stmt)
815 if (get_pure_location (stmt->location) != UNKNOWN_LOCATION)
816 return stmt->location;
818 if (m_returning_call
819 && get_pure_location (m_returning_call->location) != UNKNOWN_LOCATION)
820 return m_returning_call->location;
822 if (entry_p ())
823 return m_fun->function_start_locus;
824 if (return_p ())
825 return m_fun->function_end_locus;
827 /* If we have a single out-edge that's a CFG edge, use the goto_locus of
828 that edge. */
829 if (m_succs.length () == 1)
830 if (const cfg_superedge *cfg_sedge = m_succs[0]->dyn_cast_cfg_superedge ())
831 return cfg_sedge->get_goto_locus ();
833 return UNKNOWN_LOCATION;
836 /* Given STMT within this supernode, return its index within m_stmts. */
838 unsigned int
839 supernode::get_stmt_index (const gimple *stmt) const
841 unsigned i;
842 gimple *iter_stmt;
843 FOR_EACH_VEC_ELT (m_stmts, i, iter_stmt)
844 if (iter_stmt == stmt)
845 return i;
846 gcc_unreachable ();
849 /* Get any label_decl for this supernode, or NULL_TREE if there isn't one. */
851 tree
852 supernode::get_label () const
854 if (m_stmts.length () == 0)
855 return NULL_TREE;
856 const glabel *label_stmt = dyn_cast<const glabel *> (m_stmts[0]);
857 if (!label_stmt)
858 return NULL_TREE;
859 return gimple_label_label (label_stmt);
862 /* Get a string for PK. */
864 static const char *
865 edge_kind_to_string (enum edge_kind kind)
867 switch (kind)
869 default:
870 gcc_unreachable ();
871 case SUPEREDGE_CFG_EDGE:
872 return "SUPEREDGE_CFG_EDGE";
873 case SUPEREDGE_CALL:
874 return "SUPEREDGE_CALL";
875 case SUPEREDGE_RETURN:
876 return "SUPEREDGE_RETURN";
877 case SUPEREDGE_INTRAPROCEDURAL_CALL:
878 return "SUPEREDGE_INTRAPROCEDURAL_CALL";
882 /* Dump this superedge to PP. */
884 void
885 superedge::dump (pretty_printer *pp) const
887 pp_printf (pp, "edge: SN: %i -> SN: %i", m_src->m_index, m_dest->m_index);
888 label_text desc (get_description (false));
889 if (strlen (desc.get ()) > 0)
891 pp_space (pp);
892 pp_string (pp, desc.get ());
896 /* Dump this superedge to stderr. */
898 DEBUG_FUNCTION void
899 superedge::dump () const
901 pretty_printer pp;
902 pp_format_decoder (&pp) = default_tree_printer;
903 pp_show_color (&pp) = pp_show_color (global_dc->printer);
904 pp.set_output_stream (stderr);
905 dump (&pp);
906 pp_newline (&pp);
907 pp_flush (&pp);
910 /* Implementation of dedge::dump_dot for superedges.
911 Write a .dot edge to GV representing this superedge. */
913 void
914 superedge::dump_dot (graphviz_out *gv, const dump_args_t &) const
916 const char *style = "\"solid,bold\"";
917 const char *color = "black";
918 int weight = 10;
919 const char *constraint = "true";
921 switch (m_kind)
923 default:
924 gcc_unreachable ();
925 case SUPEREDGE_CFG_EDGE:
926 break;
927 case SUPEREDGE_CALL:
928 color = "red";
929 break;
930 case SUPEREDGE_RETURN:
931 color = "green";
932 break;
933 case SUPEREDGE_INTRAPROCEDURAL_CALL:
934 style = "\"dotted\"";
935 break;
938 /* Adapted from graph.cc:draw_cfg_node_succ_edges. */
939 if (::edge cfg_edge = get_any_cfg_edge ())
941 if (cfg_edge->flags & EDGE_FAKE)
943 style = "dotted";
944 color = "green";
945 weight = 0;
947 else if (cfg_edge->flags & EDGE_DFS_BACK)
949 style = "\"dotted,bold\"";
950 color = "blue";
951 weight = 10;
953 else if (cfg_edge->flags & EDGE_FALLTHRU)
955 color = "blue";
956 weight = 100;
959 if (cfg_edge->flags & EDGE_ABNORMAL)
960 color = "red";
963 gv->write_indent ();
965 pretty_printer *pp = gv->get_pp ();
967 m_src->dump_dot_id (pp);
968 pp_string (pp, " -> ");
969 m_dest->dump_dot_id (pp);
970 pp_printf (pp,
971 (" [style=%s, color=%s, weight=%d, constraint=%s,"
972 " ltail=\"cluster_node_%i\", lhead=\"cluster_node_%i\""
973 " headlabel=\""),
974 style, color, weight, constraint,
975 m_src->m_index, m_dest->m_index);
977 dump_label_to_pp (pp, false);
979 pp_printf (pp, "\"];\n");
982 /* Return a new json::object of the form
983 {"kind" : str,
984 "src_idx": int, the index of the source supernode,
985 "dst_idx": int, the index of the destination supernode,
986 "desc" : str. */
988 json::object *
989 superedge::to_json () const
991 json::object *sedge_obj = new json::object ();
992 sedge_obj->set_string ("kind", edge_kind_to_string (m_kind));
993 sedge_obj->set_integer ("src_idx", m_src->m_index);
994 sedge_obj->set_integer ("dst_idx", m_dest->m_index);
997 pretty_printer pp;
998 pp_format_decoder (&pp) = default_tree_printer;
999 dump_label_to_pp (&pp, false);
1000 sedge_obj->set_string ("desc", pp_formatted_text (&pp));
1003 return sedge_obj;
1006 /* If this is an intraprocedural superedge, return the associated
1007 CFG edge. Otherwise, return NULL. */
1009 ::edge
1010 superedge::get_any_cfg_edge () const
1012 if (const cfg_superedge *sub = dyn_cast_cfg_superedge ())
1013 return sub->get_cfg_edge ();
1014 return NULL;
1017 /* If this is an interprocedural superedge, return the associated
1018 cgraph_edge *. Otherwise, return NULL. */
1020 cgraph_edge *
1021 superedge::get_any_callgraph_edge () const
1023 if (const callgraph_superedge *sub = dyn_cast_callgraph_superedge ())
1024 return sub->m_cedge;
1025 return NULL;
1028 /* Build a description of this superedge (e.g. "true" for the true
1029 edge of a conditional, or "case 42:" for a switch case).
1031 If USER_FACING is false, the result also contains any underlying
1032 CFG edge flags. e.g. " (flags FALLTHRU | DFS_BACK)". */
1034 label_text
1035 superedge::get_description (bool user_facing) const
1037 pretty_printer pp;
1038 dump_label_to_pp (&pp, user_facing);
1039 return label_text::take (xstrdup (pp_formatted_text (&pp)));
1042 /* Implementation of superedge::dump_label_to_pp for non-switch CFG
1043 superedges.
1045 For true/false edges, print "true" or "false" to PP.
1047 If USER_FACING is false, also print flags on the underlying CFG edge to
1048 PP. */
1050 void
1051 cfg_superedge::dump_label_to_pp (pretty_printer *pp,
1052 bool user_facing) const
1054 if (true_value_p ())
1055 pp_printf (pp, "true");
1056 else if (false_value_p ())
1057 pp_printf (pp, "false");
1059 if (user_facing)
1060 return;
1062 /* Express edge flags as a string with " | " separator.
1063 e.g. " (flags FALLTHRU | DFS_BACK)". */
1064 if (get_flags ())
1066 pp_string (pp, " (flags ");
1067 bool seen_flag = false;
1068 #define DEF_EDGE_FLAG(NAME,IDX) \
1069 do { \
1070 if (get_flags () & EDGE_##NAME) \
1072 if (seen_flag) \
1073 pp_string (pp, " | "); \
1074 pp_printf (pp, "%s", (#NAME)); \
1075 seen_flag = true; \
1077 } while (0);
1078 #include "cfg-flags.def"
1079 #undef DEF_EDGE_FLAG
1080 pp_string (pp, ")");
1083 if (m_cfg_edge->goto_locus > BUILTINS_LOCATION)
1084 pp_string (pp, " (has goto_locus)");
1086 /* Otherwise, no label. */
1089 /* Get the index number for this edge for use in phi stmts
1090 in its destination. */
1092 size_t
1093 cfg_superedge::get_phi_arg_idx () const
1095 return m_cfg_edge->dest_idx;
1098 /* Get the phi argument for PHI for this CFG edge. */
1100 tree
1101 cfg_superedge::get_phi_arg (const gphi *phi) const
1103 size_t index = get_phi_arg_idx ();
1104 return gimple_phi_arg_def (phi, index);
1107 switch_cfg_superedge::switch_cfg_superedge (supernode *src,
1108 supernode *dst,
1109 ::edge e)
1110 : cfg_superedge (src, dst, e)
1112 /* Populate m_case_labels with all cases which go to DST. */
1113 const gswitch *gswitch = get_switch_stmt ();
1114 for (unsigned i = 0; i < gimple_switch_num_labels (gswitch); i++)
1116 tree case_ = gimple_switch_label (gswitch, i);
1117 basic_block bb = label_to_block (src->get_function (),
1118 CASE_LABEL (case_));
1119 if (bb == dst->m_bb)
1120 m_case_labels.safe_push (case_);
1124 /* Implementation of superedge::dump_label_to_pp for CFG superedges for
1125 "switch" statements.
1127 Print "case VAL:", "case LOWER ... UPPER:", or "default:" to PP. */
1129 void
1130 switch_cfg_superedge::dump_label_to_pp (pretty_printer *pp,
1131 bool user_facing ATTRIBUTE_UNUSED) const
1133 if (user_facing)
1135 for (unsigned i = 0; i < m_case_labels.length (); ++i)
1137 if (i > 0)
1138 pp_string (pp, ", ");
1139 tree case_label = m_case_labels[i];
1140 gcc_assert (TREE_CODE (case_label) == CASE_LABEL_EXPR);
1141 tree lower_bound = CASE_LOW (case_label);
1142 tree upper_bound = CASE_HIGH (case_label);
1143 if (lower_bound)
1145 pp_printf (pp, "case ");
1146 dump_generic_node (pp, lower_bound, 0, (dump_flags_t)0, false);
1147 if (upper_bound)
1149 pp_printf (pp, " ... ");
1150 dump_generic_node (pp, upper_bound, 0, (dump_flags_t)0,
1151 false);
1153 pp_printf (pp, ":");
1155 else
1156 pp_printf (pp, "default:");
1159 else
1161 pp_character (pp, '{');
1162 for (unsigned i = 0; i < m_case_labels.length (); ++i)
1164 if (i > 0)
1165 pp_string (pp, ", ");
1166 tree case_label = m_case_labels[i];
1167 gcc_assert (TREE_CODE (case_label) == CASE_LABEL_EXPR);
1168 tree lower_bound = CASE_LOW (case_label);
1169 tree upper_bound = CASE_HIGH (case_label);
1170 if (lower_bound)
1172 if (upper_bound)
1174 pp_character (pp, '[');
1175 dump_generic_node (pp, lower_bound, 0, (dump_flags_t)0,
1176 false);
1177 pp_string (pp, ", ");
1178 dump_generic_node (pp, upper_bound, 0, (dump_flags_t)0,
1179 false);
1180 pp_character (pp, ']');
1182 else
1183 dump_generic_node (pp, lower_bound, 0, (dump_flags_t)0, false);
1185 else
1186 pp_printf (pp, "default");
1188 pp_character (pp, '}');
1189 if (implicitly_created_default_p ())
1191 pp_string (pp, " IMPLICITLY CREATED");
1196 /* Return true iff this edge is purely for an implicitly-created "default". */
1198 bool
1199 switch_cfg_superedge::implicitly_created_default_p () const
1201 if (m_case_labels.length () != 1)
1202 return false;
1204 tree case_label = m_case_labels[0];
1205 gcc_assert (TREE_CODE (case_label) == CASE_LABEL_EXPR);
1206 if (CASE_LOW (case_label))
1207 return false;
1209 /* We have a single "default" case.
1210 Assume that it was implicitly created if it has UNKNOWN_LOCATION. */
1211 return EXPR_LOCATION (case_label) == UNKNOWN_LOCATION;
1214 /* Implementation of superedge::dump_label_to_pp for interprocedural
1215 superedges. */
1217 void
1218 callgraph_superedge::dump_label_to_pp (pretty_printer *pp,
1219 bool user_facing ATTRIBUTE_UNUSED) const
1221 switch (m_kind)
1223 default:
1224 case SUPEREDGE_CFG_EDGE:
1225 gcc_unreachable ();
1227 case SUPEREDGE_CALL:
1228 pp_printf (pp, "call");
1229 break;
1231 case SUPEREDGE_RETURN:
1232 pp_printf (pp, "return");
1233 break;
1235 case SUPEREDGE_INTRAPROCEDURAL_CALL:
1236 pp_printf (pp, "intraproc link");
1237 break;
1241 /* Get the function that was called at this interprocedural call/return
1242 edge. */
1244 function *
1245 callgraph_superedge::get_callee_function () const
1247 return get_ultimate_function_for_cgraph_edge (m_cedge);
1250 /* Get the calling function at this interprocedural call/return edge. */
1252 function *
1253 callgraph_superedge::get_caller_function () const
1255 return m_cedge->caller->get_fun ();
1258 /* Get the fndecl that was called at this interprocedural call/return
1259 edge. */
1261 tree
1262 callgraph_superedge::get_callee_decl () const
1264 return get_callee_function ()->decl;
1267 /* Get the gcall * of this interprocedural call/return edge. */
1269 gcall *
1270 callgraph_superedge::get_call_stmt () const
1272 if (m_cedge)
1273 return m_cedge->call_stmt;
1275 return m_src->get_final_call ();
1278 /* Get the calling fndecl at this interprocedural call/return edge. */
1280 tree
1281 callgraph_superedge::get_caller_decl () const
1283 return get_caller_function ()->decl;
1286 /* Given PARM_TO_FIND, a PARM_DECL, identify its index (writing it
1287 to *OUT if OUT is non-NULL), and return the corresponding argument
1288 at the callsite. */
1290 tree
1291 callgraph_superedge::get_arg_for_parm (tree parm_to_find,
1292 callsite_expr *out) const
1294 gcc_assert (TREE_CODE (parm_to_find) == PARM_DECL);
1296 tree callee = get_callee_decl ();
1297 const gcall *call_stmt = get_call_stmt ();
1299 unsigned i = 0;
1300 for (tree iter_parm = DECL_ARGUMENTS (callee); iter_parm;
1301 iter_parm = DECL_CHAIN (iter_parm), ++i)
1303 if (i >= gimple_call_num_args (call_stmt))
1304 return NULL_TREE;
1305 if (iter_parm == parm_to_find)
1307 if (out)
1308 *out = callsite_expr::from_zero_based_param (i);
1309 return gimple_call_arg (call_stmt, i);
1313 /* Not found. */
1314 return NULL_TREE;
1317 /* Look for a use of ARG_TO_FIND as an argument at this callsite.
1318 If found, return the default SSA def of the corresponding parm within
1319 the callee, and if OUT is non-NULL, write the index to *OUT.
1320 Only the first match is handled. */
1322 tree
1323 callgraph_superedge::get_parm_for_arg (tree arg_to_find,
1324 callsite_expr *out) const
1326 tree callee = get_callee_decl ();
1327 const gcall *call_stmt = get_call_stmt ();
1329 unsigned i = 0;
1330 for (tree iter_parm = DECL_ARGUMENTS (callee); iter_parm;
1331 iter_parm = DECL_CHAIN (iter_parm), ++i)
1333 if (i >= gimple_call_num_args (call_stmt))
1334 return NULL_TREE;
1335 tree param = gimple_call_arg (call_stmt, i);
1336 if (arg_to_find == param)
1338 if (out)
1339 *out = callsite_expr::from_zero_based_param (i);
1340 return ssa_default_def (get_callee_function (), iter_parm);
1344 /* Not found. */
1345 return NULL_TREE;
1348 /* Map caller_expr back to an expr within the callee, or return NULL_TREE.
1349 If non-NULL is returned, populate OUT. */
1351 tree
1352 callgraph_superedge::map_expr_from_caller_to_callee (tree caller_expr,
1353 callsite_expr *out) const
1355 /* Is it an argument (actual param)? If so, convert to
1356 parameter (formal param). */
1357 tree parm = get_parm_for_arg (caller_expr, out);
1358 if (parm)
1359 return parm;
1360 /* Otherwise try return value. */
1361 if (caller_expr == gimple_call_lhs (get_call_stmt ()))
1363 if (out)
1364 *out = callsite_expr::from_return_value ();
1365 return DECL_RESULT (get_callee_decl ());
1368 return NULL_TREE;
1371 /* Map callee_expr back to an expr within the caller, or return NULL_TREE.
1372 If non-NULL is returned, populate OUT. */
1374 tree
1375 callgraph_superedge::map_expr_from_callee_to_caller (tree callee_expr,
1376 callsite_expr *out) const
1378 if (callee_expr == NULL_TREE)
1379 return NULL_TREE;
1381 /* If it's a parameter (formal param), get the argument (actual param). */
1382 if (TREE_CODE (callee_expr) == PARM_DECL)
1383 return get_arg_for_parm (callee_expr, out);
1385 /* Similar for the default SSA name of the PARM_DECL. */
1386 if (TREE_CODE (callee_expr) == SSA_NAME
1387 && SSA_NAME_IS_DEFAULT_DEF (callee_expr)
1388 && TREE_CODE (SSA_NAME_VAR (callee_expr)) == PARM_DECL)
1389 return get_arg_for_parm (SSA_NAME_VAR (callee_expr), out);
1391 /* Otherwise try return value. */
1392 if (callee_expr == DECL_RESULT (get_callee_decl ()))
1394 if (out)
1395 *out = callsite_expr::from_return_value ();
1396 return gimple_call_lhs (get_call_stmt ());
1399 return NULL_TREE;
1402 } // namespace ana
1404 #endif /* #if ENABLE_ANALYZER */