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>.
4 
5 This file is part of GCC.
6 
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.
11 
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.
16 
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/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "tm.h"
26 #include "toplev.h"
27 #include "hash-table.h"
28 #include "vec.h"
29 #include "ggc.h"
30 #include "basic-block.h"
31 #include "function.h"
32 #include "gimple-fold.h"
33 #include "tree-eh.h"
34 #include "gimple-expr.h"
35 #include "is-a.h"
36 #include "timevar.h"
37 #include "gimple.h"
38 #include "gimple-iterator.h"
39 #include "gimple-pretty-print.h"
40 #include "tree-pretty-print.h"
41 #include "graphviz.h"
42 #include "cgraph.h"
43 #include "tree-dfa.h"
44 #include "cfganal.h"
45 #include "function.h"
46 #include "analyzer/analyzer.h"
47 #include "ordered-hash-map.h"
48 #include "options.h"
49 #include "cgraph.h"
50 #include "cfg.h"
51 #include "digraph.h"
52 #include "analyzer/supergraph.h"
53 #include "analyzer/analyzer-logging.h"
54 
55 #if ENABLE_ANALYZER
56 
57 namespace ana {
58 
59 /* Get the function of the ultimate alias target being called at EDGE,
60    if any.  */
61 
62 static function *
get_ultimate_function_for_cgraph_edge(cgraph_edge * edge)63 get_ultimate_function_for_cgraph_edge (cgraph_edge *edge)
64 {
65   cgraph_node *ultimate_node = edge->callee->ultimate_alias_target ();
66   if (!ultimate_node)
67     return NULL;
68   return ultimate_node->get_fun ();
69 }
70 
71 /* Get the cgraph_edge, but only if there's an underlying function body.  */
72 
73 cgraph_edge *
supergraph_call_edge(function * fun,gimple * stmt)74 supergraph_call_edge (function *fun, gimple *stmt)
75 {
76   gcall *call = dyn_cast<gcall *> (stmt);
77   if (!call)
78     return NULL;
79   cgraph_edge *edge = cgraph_node::get (fun->decl)->get_edge (stmt);
80   if (!edge)
81     return NULL;
82   if (!edge->callee)
83     return NULL; /* e.g. for a function pointer.  */
84   if (!get_ultimate_function_for_cgraph_edge (edge))
85     return NULL;
86   return edge;
87 }
88 
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.  */
93 
supergraph(logger * logger)94 supergraph::supergraph (logger *logger)
95 {
96   auto_timevar tv (TV_ANALYZER_SUPERGRAPH);
97 
98   LOG_FUNC (logger);
99 
100   /* First pass: make supernodes.  */
101   {
102     /* Sort the cgraph_nodes?  */
103     cgraph_node *node;
104     FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
105     {
106       function *fun = node->get_fun ();
107 
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 ();
112 
113       const int start_idx = m_nodes.length ();
114 
115       basic_block bb;
116       FOR_ALL_BB_FN (bb, fun)
117 	{
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);
122 	       gsi_next (&gpi))
123 	    {
124 	      gimple *stmt = gsi_stmt (gpi);
125 	      m_stmt_to_node_t.put (stmt, node_for_stmts);
126 	    }
127 
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))
133 	    {
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))
138 		{
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);
142 		}
143 	    }
144 
145 	  m_bb_to_final_node.put (bb, node_for_stmts);
146 	}
147 
148       const unsigned num_snodes = m_nodes.length () - start_idx;
149       m_function_to_num_snodes.put (fun, num_snodes);
150 
151       if (logger)
152 	{
153 	  const int end_idx = m_nodes.length () - 1;
154 	  logger->log ("SN: %i...%i: function %qD",
155 		       start_idx, end_idx, fun->decl);
156 	}
157     }
158   }
159 
160   /* Second pass: make superedges.  */
161   {
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 ();
165 	 ++iter)
166       {
167 	basic_block bb = (*iter).first;
168 	supernode *src_supernode = (*iter).second;
169 
170 	::edge cfg_edge;
171 	int idx;
172 	if (bb->succs)
173 	  FOR_EACH_VEC_ELT (*bb->succs, idx, cfg_edge)
174 	    {
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);
181 	    }
182       }
183 
184     /* Make interprocedural superedges for calls.  */
185     {
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 ();
189 	   ++iter)
190 	{
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)
195 	    continue;
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,
201 				  callee_supernode,
202 				  edge);
203 	  m_cgraph_edge_to_call_superedge.put (edge, sedge);
204 	}
205     }
206 
207     /* Make interprocedural superedges for returns.  */
208     {
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 ();
212 	   ++iter)
213 	{
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)
218 	    continue;
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,
225 				    edge);
226 	  m_cgraph_edge_to_return_superedge.put (edge, sedge);
227 	}
228     }
229 
230     /* Make intraprocedural superedges linking the two halves of a call.  */
231     {
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 ();
235 	   ++iter)
236 	{
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);
241 	  superedge *sedge
242 	    = new callgraph_superedge (caller_prev_supernode,
243 				       caller_next_supernode,
244 				       SUPEREDGE_INTRAPROCEDURAL_CALL,
245 				       edge);
246 	  add_edge (sedge);
247 	  m_cgraph_edge_to_intraproc_superedge.put (edge, sedge);
248 	}
249 
250     }
251   }
252 }
253 
254 /* Dump this graph in .dot format to PP, using DUMP_ARGS.
255    Cluster the supernodes by function, then by BB from original CFG.  */
256 
257 void
dump_dot_to_pp(pretty_printer * pp,const dump_args_t & dump_args) const258 supergraph::dump_dot_to_pp (pretty_printer *pp,
259 			    const dump_args_t &dump_args) const
260 {
261   graphviz_out gv (pp);
262 
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");
268   gv.indent ();
269 
270   gv.println ("overlap=false;");
271   gv.println ("compound=true;");
272 
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
275   */
276 
277   /* Break out the supernodes into clusters by function.  */
278   {
279     cgraph_node *node;
280     FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
281     {
282       function *fun = node->get_fun ();
283       const char *funcname = function_name (fun);
284       gv.println ("subgraph \"cluster_%s\" {",
285 		  funcname);
286       gv.indent ();
287       pp_printf (pp,
288 		 ("style=\"dashed\";"
289 		  " color=\"black\";"
290 		  " label=\"%s\";\n"),
291 		 funcname);
292 
293       /* Break out the nodes into clusters by BB from original CFG.  */
294       {
295 	basic_block bb;
296 	FOR_ALL_BB_FN (bb, fun)
297 	  {
298 	    if (dump_args.m_flags & SUPERGRAPH_DOT_SHOW_BBS)
299 	      {
300 		gv.println ("subgraph \"cluster_%s_bb_%i\" {",
301 			    funcname, bb->index);
302 		gv.indent ();
303 		pp_printf (pp,
304 			   ("style=\"dashed\";"
305 			    " color=\"black\";"
306 			    " label=\"bb: %i\";\n"),
307 			   bb->index);
308 	      }
309 
310 	    // TODO: maybe keep an index per-function/per-bb to speed this up???
311 	    int i;
312 	    supernode *n;
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);
316 
317 	    if (dump_args.m_flags & SUPERGRAPH_DOT_SHOW_BBS)
318 	      {
319 		/* Terminate per-bb "subgraph" */
320 		gv.outdent ();
321 		gv.println ("}");
322 	      }
323 	  }
324       }
325 
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");
332 
333       /* Terminate per-function "subgraph" */
334       gv.outdent ();
335       gv.println ("}");
336     }
337   }
338 
339   /* Superedges.  */
340   int i;
341   superedge *e;
342   FOR_EACH_VEC_ELT (m_edges, i, e)
343     e->dump_dot (&gv, dump_args);
344 
345   /* Terminate "digraph" */
346   gv.outdent ();
347   gv.println ("}");
348 }
349 
350 /* Dump this graph in .dot format to FP, using DUMP_ARGS.  */
351 
352 void
dump_dot_to_file(FILE * fp,const dump_args_t & dump_args) const353 supergraph::dump_dot_to_file (FILE *fp, const dump_args_t &dump_args) const
354 {
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;
360 
361   pp->buffer->stream = fp;
362   dump_dot_to_pp (pp, dump_args);
363   pp_flush (pp);
364   delete pp;
365 }
366 
367 /* Dump this graph in .dot format to PATH, using DUMP_ARGS.  */
368 
369 void
dump_dot(const char * path,const dump_args_t & dump_args) const370 supergraph::dump_dot (const char *path, const dump_args_t &dump_args) const
371 {
372   FILE *fp = fopen (path, "w");
373   dump_dot_to_file (fp, dump_args);
374   fclose (fp);
375 }
376 
377 /* Create a supernode for BB within FUN and add it to this supergraph.
378 
379    If RETURNING_CALL is non-NULL, the supernode represents the resumption
380    of the basic block after returning from that call.
381 
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.  */
384 
385 supernode *
add_node(function * fun,basic_block bb,gcall * returning_call,gimple_seq phi_nodes)386 supergraph::add_node (function *fun, basic_block bb, gcall *returning_call,
387 		      gimple_seq phi_nodes)
388 {
389   supernode *n = new supernode (fun, bb, returning_call, phi_nodes,
390 				m_nodes.length ());
391   m_nodes.safe_push (n);
392   return n;
393 }
394 
395 /* Create a new cfg_superedge from SRC to DEST for the underlying CFG edge E,
396    adding it to this supergraph.
397 
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).  */
401 
402 cfg_superedge *
add_cfg_edge(supernode * src,supernode * dest,::edge e,int idx)403 supergraph::add_cfg_edge (supernode *src, supernode *dest, ::edge e, int idx)
404 {
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);
410   else
411     new_edge = new cfg_superedge (src, dest, e);
412   add_edge (new_edge);
413   return new_edge;
414 }
415 
416 /* Create and add a call_superedge representing an interprocedural call
417    from SRC to DEST, using CEDGE.  */
418 
419 call_superedge *
add_call_superedge(supernode * src,supernode * dest,cgraph_edge * cedge)420 supergraph::add_call_superedge (supernode *src, supernode *dest,
421 				cgraph_edge *cedge)
422 {
423   call_superedge *new_edge = new call_superedge (src, dest, cedge);
424   add_edge (new_edge);
425   return new_edge;
426 }
427 
428 /* Create and add a return_superedge representing returning from an
429    interprocedural call, returning from SRC to DEST, using CEDGE.  */
430 
431 return_superedge *
add_return_superedge(supernode * src,supernode * dest,cgraph_edge * cedge)432 supergraph::add_return_superedge (supernode *src, supernode *dest,
433 				  cgraph_edge *cedge)
434 {
435   return_superedge *new_edge = new return_superedge (src, dest, cedge);
436   add_edge (new_edge);
437   return new_edge;
438 }
439 
440 /* Implementation of dnode::dump_dot vfunc for supernodes.
441 
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.  */
445 
446 void
dump_dot(graphviz_out * gv,const dump_args_t & args) const447 supernode::dump_dot (graphviz_out *gv, const dump_args_t &args) const
448 {
449   gv->println ("subgraph cluster_node_%i {",
450 	       m_index);
451   gv->indent ();
452 
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);
457 
458   pretty_printer *pp = gv->get_pp ();
459 
460   if (args.m_node_annotator)
461     args.m_node_annotator->add_node_annotations (gv, *this, false);
462 
463   gv->write_indent ();
464   dump_dot_id (pp);
465   pp_printf (pp,
466 	     " [shape=none,margin=0,style=filled,fillcolor=%s,label=<",
467 	     "lightgrey");
468   pp_string (pp, "<TABLE BORDER=\"0\">");
469   pp_write_text_to_stream (pp);
470 
471   bool had_row = false;
472 
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))
476       had_row = true;
477 
478   if (m_returning_call)
479     {
480       gv->begin_trtd ();
481       pp_string (pp, "returning call: ");
482       gv->end_tdtr ();
483 
484       gv->begin_tr ();
485       gv->begin_td ();
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);
488       gv->end_td ();
489       /* Give any annotator the chance to add per-stmt TD elements to
490 	 this row.  */
491       if (args.m_node_annotator)
492 	args.m_node_annotator->add_stmt_annotations (gv, m_returning_call,
493 						     true);
494       gv->end_tr ();
495 
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,
499 						     false);
500       pp_newline (pp);
501 
502       had_row = true;
503     }
504 
505   if (entry_p ())
506     {
507       pp_string (pp, "<TR><TD>ENTRY</TD></TR>");
508       pp_newline (pp);
509       had_row = true;
510     }
511 
512   if (return_p ())
513     {
514       pp_string (pp, "<TR><TD>EXIT</TD></TR>");
515       pp_newline (pp);
516       had_row = true;
517     }
518 
519   /* Phi nodes.  */
520   for (gphi_iterator gpi = const_cast<supernode *> (this)->start_phis ();
521        !gsi_end_p (gpi); gsi_next (&gpi))
522     {
523       const gimple *stmt = gsi_stmt (gpi);
524       gv->begin_tr ();
525       gv->begin_td ();
526       pp_gimple_stmt_1 (pp, stmt, 0, (dump_flags_t)0);
527       pp_write_text_as_html_like_dot_to_stream (pp);
528       gv->end_td ();
529       /* Give any annotator the chance to add per-phi TD elements to
530 	 this row.  */
531       if (args.m_node_annotator)
532 	args.m_node_annotator->add_stmt_annotations (gv, stmt, true);
533       gv->end_tr ();
534 
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);
538 
539       pp_newline (pp);
540       had_row = true;
541     }
542 
543   /* Statements.  */
544   int i;
545   gimple *stmt;
546   FOR_EACH_VEC_ELT (m_stmts, i, stmt)
547     {
548       gv->begin_tr ();
549       gv->begin_td ();
550       pp_gimple_stmt_1 (pp, stmt, 0, (dump_flags_t)0);
551       pp_write_text_as_html_like_dot_to_stream (pp);
552       gv->end_td ();
553       /* Give any annotator the chance to add per-stmt TD elements to
554 	 this row.  */
555       if (args.m_node_annotator)
556 	args.m_node_annotator->add_stmt_annotations (gv, stmt, true);
557       gv->end_tr ();
558 
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);
562 
563       pp_newline (pp);
564       had_row = true;
565     }
566 
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))
571       had_row = true;
572 
573   /* Graphviz requires a TABLE element to have at least one TR
574      (and each TR to have at least one TD).  */
575   if (!had_row)
576     {
577       pp_string (pp, "<TR><TD>(empty)</TD></TR>");
578       pp_newline (pp);
579     }
580 
581   pp_string (pp, "</TABLE>>];\n\n");
582   pp_flush (pp);
583 
584   /* Terminate "subgraph" */
585   gv->outdent ();
586   gv->println ("}");
587 }
588 
589 /* Write an ID for this node to PP, for use in .dot output.  */
590 
591 void
dump_dot_id(pretty_printer * pp) const592 supernode::dump_dot_id (pretty_printer *pp) const
593 {
594   pp_printf (pp, "node_%i", m_index);
595 }
596 
597 /* Get a location_t for the start of this supernode.  */
598 
599 location_t
get_start_location() const600 supernode::get_start_location () const
601 {
602   if (m_returning_call
603       && get_pure_location (m_returning_call->location) != UNKNOWN_LOCATION)
604     return m_returning_call->location;
605 
606   int i;
607   gimple *stmt;
608   FOR_EACH_VEC_ELT (m_stmts, i, stmt)
609     if (get_pure_location (stmt->location) != UNKNOWN_LOCATION)
610       return stmt->location;
611 
612   if (entry_p ())
613     {
614       // TWEAK: show the decl instead; this leads to more readable output:
615       return DECL_SOURCE_LOCATION (m_fun->decl);
616 
617       return m_fun->function_start_locus;
618     }
619   if (return_p ())
620     return m_fun->function_end_locus;
621 
622   return UNKNOWN_LOCATION;
623 }
624 
625 /* Get a location_t for the end of this supernode.  */
626 
627 location_t
get_end_location() const628 supernode::get_end_location () const
629 {
630   int i;
631   gimple *stmt;
632   FOR_EACH_VEC_ELT_REVERSE (m_stmts, i, stmt)
633     if (get_pure_location (stmt->location) != UNKNOWN_LOCATION)
634       return stmt->location;
635 
636   if (m_returning_call
637       && get_pure_location (m_returning_call->location) != UNKNOWN_LOCATION)
638     return m_returning_call->location;
639 
640   if (entry_p ())
641     return m_fun->function_start_locus;
642   if (return_p ())
643     return m_fun->function_end_locus;
644 
645   return UNKNOWN_LOCATION;
646 }
647 
648 /* Given STMT within this supernode, return its index within m_stmts.  */
649 
650 unsigned int
get_stmt_index(const gimple * stmt) const651 supernode::get_stmt_index (const gimple *stmt) const
652 {
653   unsigned i;
654   gimple *iter_stmt;
655   FOR_EACH_VEC_ELT (m_stmts, i, iter_stmt)
656     if (iter_stmt == stmt)
657       return i;
658   gcc_unreachable ();
659 }
660 
661 /* Dump this superedge to PP.  */
662 
663 void
dump(pretty_printer * pp) const664 superedge::dump (pretty_printer *pp) const
665 {
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)
669     {
670       pp_space (pp);
671       pp_string (pp, desc);
672     }
673   free (desc);
674 }
675 
676 /* Dump this superedge to stderr.  */
677 
678 DEBUG_FUNCTION void
dump() const679 superedge::dump () const
680 {
681   pretty_printer pp;
682   pp_format_decoder (&pp) = default_tree_printer;
683   pp_show_color (&pp) = pp_show_color (global_dc->printer);
684   pp.buffer->stream = stderr;
685   dump (&pp);
686   pp_newline (&pp);
687   pp_flush (&pp);
688 }
689 
690 /* Implementation of dedge::dump_dot for superedges.
691    Write a .dot edge to GV representing this superedge.  */
692 
693 void
dump_dot(graphviz_out * gv,const dump_args_t &) const694 superedge::dump_dot (graphviz_out *gv, const dump_args_t &) const
695 {
696   const char *style = "\"solid,bold\"";
697   const char *color = "black";
698   int weight = 10;
699   const char *constraint = "true";
700 
701   switch (m_kind)
702     {
703     default:
704       gcc_unreachable ();
705     case SUPEREDGE_CFG_EDGE:
706       break;
707     case SUPEREDGE_CALL:
708       color = "red";
709       break;
710     case SUPEREDGE_RETURN:
711       color = "green";
712       break;
713     case SUPEREDGE_INTRAPROCEDURAL_CALL:
714       style = "\"dotted\"";
715       break;
716     }
717 
718   /* Adapted from graph.c:draw_cfg_node_succ_edges.  */
719   if (::edge cfg_edge = get_any_cfg_edge ())
720     {
721       if (cfg_edge->flags & EDGE_FAKE)
722 	{
723 	  style = "dotted";
724 	  color = "green";
725 	  weight = 0;
726 	}
727       else if (cfg_edge->flags & EDGE_DFS_BACK)
728 	{
729 	  style = "\"dotted,bold\"";
730 	  color = "blue";
731 	  weight = 10;
732 	}
733       else if (cfg_edge->flags & EDGE_FALLTHRU)
734 	{
735 	  color = "blue";
736 	  weight = 100;
737 	}
738 
739       if (cfg_edge->flags & EDGE_ABNORMAL)
740 	color = "red";
741     }
742 
743   gv->write_indent ();
744 
745   pretty_printer *pp = gv->get_pp ();
746 
747   m_src->dump_dot_id (pp);
748   pp_string (pp, " -> ");
749   m_dest->dump_dot_id (pp);
750   pp_printf (pp,
751 	     (" [style=%s, color=%s, weight=%d, constraint=%s,"
752 	      " ltail=\"cluster_node_%i\", lhead=\"cluster_node_%i\""
753 	      " headlabel=\""),
754 	     style, color, weight, constraint,
755 	     m_src->m_index, m_dest->m_index);
756 
757   dump_label_to_pp (pp, false);
758 
759   pp_printf (pp, "\"];\n");
760 }
761 
762 /* If this is an intraprocedural superedge, return the associated
763    CFG edge.  Otherwise, return NULL.  */
764 
765 ::edge
get_any_cfg_edge() const766 superedge::get_any_cfg_edge () const
767 {
768   if (const cfg_superedge *sub = dyn_cast_cfg_superedge ())
769     return sub->get_cfg_edge ();
770   return NULL;
771 }
772 
773 /* If this is an interprocedural superedge, return the associated
774    cgraph_edge *.  Otherwise, return NULL.  */
775 
776 cgraph_edge *
get_any_callgraph_edge() const777 superedge::get_any_callgraph_edge () const
778 {
779   if (const callgraph_superedge *sub = dyn_cast_callgraph_superedge ())
780     return sub->m_cedge;
781   return NULL;
782 }
783 
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).
786 
787    The caller is responsible for freeing the result.
788 
789    If USER_FACING is false, the result also contains any underlying
790    CFG edge flags. e.g. " (flags FALLTHRU | DFS_BACK)".  */
791 
792 char *
get_description(bool user_facing) const793 superedge::get_description (bool user_facing) const
794 {
795   pretty_printer pp;
796   dump_label_to_pp (&pp, user_facing);
797   return xstrdup (pp_formatted_text (&pp));
798 }
799 
800 /* Implementation of superedge::dump_label_to_pp for non-switch CFG
801    superedges.
802 
803    For true/false edges, print "true" or "false" to PP.
804 
805    If USER_FACING is false, also print flags on the underlying CFG edge to
806    PP.  */
807 
808 void
dump_label_to_pp(pretty_printer * pp,bool user_facing) const809 cfg_superedge::dump_label_to_pp (pretty_printer *pp,
810 				 bool user_facing) const
811 {
812   if (true_value_p ())
813     pp_printf (pp, "true");
814   else if (false_value_p ())
815     pp_printf (pp, "false");
816 
817   if (user_facing)
818     return;
819 
820   /* Express edge flags as a string with " | " separator.
821      e.g. " (flags FALLTHRU | DFS_BACK)".  */
822   if (get_flags ())
823     {
824       pp_string (pp, " (flags ");
825       bool seen_flag = false;
826 #define DEF_EDGE_FLAG(NAME,IDX)			\
827   do {						\
828     if (get_flags () & EDGE_##NAME)			\
829       {						\
830 	if (seen_flag)				\
831 	  pp_string (pp, " | ");			\
832 	pp_printf (pp, "%s", (#NAME));		\
833 	seen_flag = true;			\
834       }						\
835   } while (0);
836 #include "cfg-flags.def"
837 #undef DEF_EDGE_FLAG
838       pp_string (pp, ")");
839     }
840 
841   /* Otherwise, no label.  */
842 }
843 
844 /* Get the phi argument for PHI for this CFG edge.  */
845 
846 tree
get_phi_arg(const gphi * phi) const847 cfg_superedge::get_phi_arg (const gphi *phi) const
848 {
849   size_t index = m_cfg_edge->dest_idx;
850   return gimple_phi_arg_def (phi, index);
851 }
852 
853 /* Implementation of superedge::dump_label_to_pp for CFG superedges for
854    "switch" statements.
855 
856    Print "case VAL:", "case LOWER ... UPPER:", or "default:" to PP.  */
857 
858 void
dump_label_to_pp(pretty_printer * pp,bool user_facing ATTRIBUTE_UNUSED) const859 switch_cfg_superedge::dump_label_to_pp (pretty_printer *pp,
860 					bool user_facing ATTRIBUTE_UNUSED) const
861 {
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);
866   if (lower_bound)
867     {
868       pp_printf (pp, "case ");
869       dump_generic_node (pp, lower_bound, 0, (dump_flags_t)0, false);
870       if (upper_bound)
871 	{
872 	  pp_printf (pp, " ... ");
873 	  dump_generic_node (pp, upper_bound, 0, (dump_flags_t)0, false);
874 	}
875       pp_printf (pp, ":");
876     }
877   else
878     pp_printf (pp, "default:");
879 }
880 
881 /* Get the case label for this "switch" superedge.  */
882 
883 tree
get_case_label() const884 switch_cfg_superedge::get_case_label () const
885 {
886   return gimple_switch_label (get_switch_stmt (), m_idx);
887 }
888 
889 /* Implementation of superedge::dump_label_to_pp for interprocedural
890    superedges.  */
891 
892 void
dump_label_to_pp(pretty_printer * pp,bool user_facing ATTRIBUTE_UNUSED) const893 callgraph_superedge::dump_label_to_pp (pretty_printer *pp,
894 				       bool user_facing ATTRIBUTE_UNUSED) const
895 {
896   switch (m_kind)
897     {
898     default:
899     case SUPEREDGE_CFG_EDGE:
900       gcc_unreachable ();
901 
902     case SUPEREDGE_CALL:
903       pp_printf (pp, "call");
904       break;
905 
906     case SUPEREDGE_RETURN:
907       pp_printf (pp, "return");
908       break;
909 
910     case SUPEREDGE_INTRAPROCEDURAL_CALL:
911       pp_printf (pp, "intraproc link");
912       break;
913     }
914 }
915 
916 /* Get the function that was called at this interprocedural call/return
917    edge.  */
918 
919 function *
get_callee_function() const920 callgraph_superedge::get_callee_function () const
921 {
922   return get_ultimate_function_for_cgraph_edge (m_cedge);
923 }
924 
925 /* Get the calling function at this interprocedural call/return edge.  */
926 
927 function *
get_caller_function() const928 callgraph_superedge::get_caller_function () const
929 {
930   return m_cedge->caller->get_fun ();
931 }
932 
933 /* Get the fndecl that was called at this interprocedural call/return
934    edge.  */
935 
936 tree
get_callee_decl() const937 callgraph_superedge::get_callee_decl () const
938 {
939   return get_callee_function ()->decl;
940 }
941 
942 /* Get the calling fndecl at this interprocedural call/return edge.  */
943 
944 tree
get_caller_decl() const945 callgraph_superedge::get_caller_decl () const
946 {
947   return get_caller_function ()->decl;
948 }
949 
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
952    at the callsite.  */
953 
954 tree
get_arg_for_parm(tree parm_to_find,callsite_expr * out) const955 callgraph_superedge::get_arg_for_parm (tree parm_to_find,
956 				       callsite_expr *out) const
957 {
958   gcc_assert  (TREE_CODE (parm_to_find) == PARM_DECL);
959 
960   tree callee = get_callee_decl ();
961   const gcall *call_stmt = get_call_stmt ();
962 
963   unsigned i = 0;
964   for (tree iter_parm = DECL_ARGUMENTS (callee); iter_parm;
965        iter_parm = DECL_CHAIN (iter_parm), ++i)
966     {
967       if (i >= gimple_call_num_args (call_stmt))
968 	return NULL_TREE;
969       if (iter_parm == parm_to_find)
970 	{
971 	  if (out)
972 	    *out = callsite_expr::from_zero_based_param (i);
973 	  return gimple_call_arg (call_stmt, i);
974 	}
975     }
976 
977   /* Not found.  */
978   return NULL_TREE;
979 }
980 
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.  */
985 
986 tree
get_parm_for_arg(tree arg_to_find,callsite_expr * out) const987 callgraph_superedge::get_parm_for_arg (tree arg_to_find,
988 				       callsite_expr *out) const
989 {
990   tree callee = get_callee_decl ();
991   const gcall *call_stmt = get_call_stmt ();
992 
993   unsigned i = 0;
994   for (tree iter_parm = DECL_ARGUMENTS (callee); iter_parm;
995        iter_parm = DECL_CHAIN (iter_parm), ++i)
996     {
997       if (i >= gimple_call_num_args (call_stmt))
998 	return NULL_TREE;
999       tree param = gimple_call_arg (call_stmt, i);
1000       if (arg_to_find == param)
1001 	{
1002 	  if (out)
1003 	    *out = callsite_expr::from_zero_based_param (i);
1004 	  return ssa_default_def (get_callee_function (), iter_parm);
1005 	}
1006     }
1007 
1008   /* Not found.  */
1009   return NULL_TREE;
1010 }
1011 
1012 /* Map caller_expr back to an expr within the callee, or return NULL_TREE.
1013    If non-NULL is returned, populate OUT.  */
1014 
1015 tree
map_expr_from_caller_to_callee(tree caller_expr,callsite_expr * out) const1016 callgraph_superedge::map_expr_from_caller_to_callee (tree caller_expr,
1017 						     callsite_expr *out) const
1018 {
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);
1022   if (parm)
1023     return parm;
1024   /* Otherwise try return value.  */
1025   if (caller_expr == gimple_call_lhs (get_call_stmt ()))
1026     {
1027       if (out)
1028 	*out = callsite_expr::from_return_value ();
1029       return DECL_RESULT (get_callee_decl ());
1030     }
1031 
1032   return NULL_TREE;
1033 }
1034 
1035 /* Map callee_expr back to an expr within the caller, or return NULL_TREE.
1036    If non-NULL is returned, populate OUT.  */
1037 
1038 tree
map_expr_from_callee_to_caller(tree callee_expr,callsite_expr * out) const1039 callgraph_superedge::map_expr_from_callee_to_caller (tree callee_expr,
1040 						     callsite_expr *out) const
1041 {
1042   if (callee_expr == NULL_TREE)
1043     return NULL_TREE;
1044 
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);
1048 
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);
1054 
1055   /* Otherwise try return value.  */
1056   if (callee_expr == DECL_RESULT (get_callee_decl ()))
1057     {
1058       if (out)
1059 	*out = callsite_expr::from_return_value ();
1060       return gimple_call_lhs (get_call_stmt ());
1061     }
1062 
1063   return NULL_TREE;
1064 }
1065 
1066 } // namespace ana
1067 
1068 #endif /* #if ENABLE_ANALYZER */
1069