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
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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
57namespace ana {
58
59/* Get the function of the ultimate alias target being called at EDGE,
60   if any.  */
61
62static function *
63get_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
73cgraph_edge *
74supergraph_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
94supergraph::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
257void
258supergraph::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
352void
353supergraph::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
369void
370supergraph::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
385supernode *
386supergraph::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
402cfg_superedge *
403supergraph::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
419call_superedge *
420supergraph::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
431return_superedge *
432supergraph::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
446void
447supernode::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
591void
592supernode::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
599location_t
600supernode::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
627location_t
628supernode::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
650unsigned int
651supernode::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
663void
664superedge::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
678DEBUG_FUNCTION void
679superedge::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
693void
694superedge::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
766superedge::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
776cgraph_edge *
777superedge::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
792char *
793superedge::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
808void
809cfg_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
846tree
847cfg_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
858void
859switch_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
883tree
884switch_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
892void
893callgraph_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
919function *
920callgraph_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
927function *
928callgraph_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
936tree
937callgraph_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
944tree
945callgraph_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
954tree
955callgraph_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
986tree
987callgraph_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
1015tree
1016callgraph_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
1038tree
1039callgraph_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