1*0bfacb9bSmrg /* "Supergraph" classes that combine CFGs and callgraph into one digraph.
2*0bfacb9bSmrg    Copyright (C) 2019-2020 Free Software Foundation, Inc.
3*0bfacb9bSmrg    Contributed by David Malcolm <dmalcolm@redhat.com>.
4*0bfacb9bSmrg 
5*0bfacb9bSmrg This file is part of GCC.
6*0bfacb9bSmrg 
7*0bfacb9bSmrg GCC is free software; you can redistribute it and/or modify it
8*0bfacb9bSmrg under the terms of the GNU General Public License as published by
9*0bfacb9bSmrg the Free Software Foundation; either version 3, or (at your option)
10*0bfacb9bSmrg any later version.
11*0bfacb9bSmrg 
12*0bfacb9bSmrg GCC is distributed in the hope that it will be useful, but
13*0bfacb9bSmrg WITHOUT ANY WARRANTY; without even the implied warranty of
14*0bfacb9bSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*0bfacb9bSmrg General Public License for more details.
16*0bfacb9bSmrg 
17*0bfacb9bSmrg You should have received a copy of the GNU General Public License
18*0bfacb9bSmrg along with GCC; see the file COPYING3.  If not see
19*0bfacb9bSmrg <http://www.gnu.org/licenses/>.  */
20*0bfacb9bSmrg 
21*0bfacb9bSmrg #ifndef GCC_ANALYZER_SUPERGRAPH_H
22*0bfacb9bSmrg #define GCC_ANALYZER_SUPERGRAPH_H
23*0bfacb9bSmrg 
24*0bfacb9bSmrg using namespace ana;
25*0bfacb9bSmrg 
26*0bfacb9bSmrg namespace ana {
27*0bfacb9bSmrg 
28*0bfacb9bSmrg /* Forward decls, using indentation to show inheritance.  */
29*0bfacb9bSmrg 
30*0bfacb9bSmrg class supergraph;
31*0bfacb9bSmrg class supernode;
32*0bfacb9bSmrg class superedge;
33*0bfacb9bSmrg   class callgraph_superedge;
34*0bfacb9bSmrg     class call_superedge;
35*0bfacb9bSmrg     class return_superedge;
36*0bfacb9bSmrg   class cfg_superedge;
37*0bfacb9bSmrg     class switch_cfg_superedge;
38*0bfacb9bSmrg class supercluster;
39*0bfacb9bSmrg class dot_annotator;
40*0bfacb9bSmrg 
41*0bfacb9bSmrg class logger;
42*0bfacb9bSmrg 
43*0bfacb9bSmrg /* An enum for discriminating between superedge subclasses.  */
44*0bfacb9bSmrg 
45*0bfacb9bSmrg enum edge_kind
46*0bfacb9bSmrg {
47*0bfacb9bSmrg   SUPEREDGE_CFG_EDGE,
48*0bfacb9bSmrg   SUPEREDGE_CALL,
49*0bfacb9bSmrg   SUPEREDGE_RETURN,
50*0bfacb9bSmrg   SUPEREDGE_INTRAPROCEDURAL_CALL
51*0bfacb9bSmrg };
52*0bfacb9bSmrg 
53*0bfacb9bSmrg /* Flags for controlling the appearance of .dot dumps.  */
54*0bfacb9bSmrg 
55*0bfacb9bSmrg enum supergraph_dot_flags
56*0bfacb9bSmrg {
57*0bfacb9bSmrg   SUPERGRAPH_DOT_SHOW_BBS = (1 << 0)
58*0bfacb9bSmrg };
59*0bfacb9bSmrg 
60*0bfacb9bSmrg /* A traits struct describing the family of node, edge and digraph
61*0bfacb9bSmrg    classes for supergraphs.  */
62*0bfacb9bSmrg 
63*0bfacb9bSmrg struct supergraph_traits
64*0bfacb9bSmrg {
65*0bfacb9bSmrg   typedef supernode node_t;
66*0bfacb9bSmrg   typedef superedge edge_t;
67*0bfacb9bSmrg   typedef supergraph graph_t;
68*0bfacb9bSmrg   struct dump_args_t
69*0bfacb9bSmrg   {
dump_args_tsupergraph_traits::dump_args_t70*0bfacb9bSmrg     dump_args_t (enum supergraph_dot_flags flags,
71*0bfacb9bSmrg 		 const dot_annotator *node_annotator)
72*0bfacb9bSmrg     : m_flags (flags),
73*0bfacb9bSmrg       m_node_annotator (node_annotator)
74*0bfacb9bSmrg     {}
75*0bfacb9bSmrg 
76*0bfacb9bSmrg     enum supergraph_dot_flags m_flags;
77*0bfacb9bSmrg     const dot_annotator *m_node_annotator;
78*0bfacb9bSmrg   };
79*0bfacb9bSmrg   typedef supercluster cluster_t;
80*0bfacb9bSmrg };
81*0bfacb9bSmrg 
82*0bfacb9bSmrg /* A "supergraph" is a directed graph formed by joining together all CFGs,
83*0bfacb9bSmrg    linking them via interprocedural call and return edges.
84*0bfacb9bSmrg 
85*0bfacb9bSmrg    Basic blocks are split at callsites, so that a call statement occurs
86*0bfacb9bSmrg    twice: once at the end of a supernode, and a second instance at the
87*0bfacb9bSmrg    start of the next supernode (to handle the return).  */
88*0bfacb9bSmrg 
89*0bfacb9bSmrg class supergraph : public digraph<supergraph_traits>
90*0bfacb9bSmrg {
91*0bfacb9bSmrg public:
92*0bfacb9bSmrg   supergraph (logger *logger);
93*0bfacb9bSmrg 
get_node_for_function_entry(function * fun)94*0bfacb9bSmrg   supernode *get_node_for_function_entry (function *fun) const
95*0bfacb9bSmrg   {
96*0bfacb9bSmrg     return get_node_for_block (ENTRY_BLOCK_PTR_FOR_FN (fun));
97*0bfacb9bSmrg   }
98*0bfacb9bSmrg 
get_node_for_function_exit(function * fun)99*0bfacb9bSmrg   supernode *get_node_for_function_exit (function *fun) const
100*0bfacb9bSmrg   {
101*0bfacb9bSmrg     return get_node_for_block (EXIT_BLOCK_PTR_FOR_FN (fun));
102*0bfacb9bSmrg   }
103*0bfacb9bSmrg 
get_node_for_block(basic_block bb)104*0bfacb9bSmrg   supernode *get_node_for_block (basic_block bb) const
105*0bfacb9bSmrg   {
106*0bfacb9bSmrg     return *const_cast <bb_to_node_t &> (m_bb_to_initial_node).get (bb);
107*0bfacb9bSmrg   }
108*0bfacb9bSmrg 
109*0bfacb9bSmrg   /* Get the supernode containing the second half of the gcall *
110*0bfacb9bSmrg      at an interprocedural call, within the caller.  */
get_caller_next_node(cgraph_edge * edge)111*0bfacb9bSmrg   supernode *get_caller_next_node (cgraph_edge *edge) const
112*0bfacb9bSmrg   {
113*0bfacb9bSmrg     return (*const_cast <cgraph_edge_to_node_t &>
114*0bfacb9bSmrg 	      (m_cgraph_edge_to_caller_next_node).get (edge));
115*0bfacb9bSmrg   }
116*0bfacb9bSmrg 
get_edge_for_call(cgraph_edge * edge)117*0bfacb9bSmrg   call_superedge *get_edge_for_call (cgraph_edge *edge) const
118*0bfacb9bSmrg   {
119*0bfacb9bSmrg     return (*const_cast <cgraph_edge_to_call_superedge_t &>
120*0bfacb9bSmrg 	      (m_cgraph_edge_to_call_superedge).get (edge));
121*0bfacb9bSmrg   }
122*0bfacb9bSmrg 
get_edge_for_return(cgraph_edge * edge)123*0bfacb9bSmrg   return_superedge *get_edge_for_return (cgraph_edge *edge) const
124*0bfacb9bSmrg   {
125*0bfacb9bSmrg     return (*const_cast <cgraph_edge_to_return_superedge_t &>
126*0bfacb9bSmrg 	      (m_cgraph_edge_to_return_superedge).get (edge));
127*0bfacb9bSmrg   }
128*0bfacb9bSmrg 
get_intraprocedural_edge_for_call(cgraph_edge * edge)129*0bfacb9bSmrg   superedge *get_intraprocedural_edge_for_call (cgraph_edge *edge) const
130*0bfacb9bSmrg   {
131*0bfacb9bSmrg     return (*const_cast <cgraph_edge_to_intraproc_superedge_t &>
132*0bfacb9bSmrg 	      (m_cgraph_edge_to_intraproc_superedge).get (edge));
133*0bfacb9bSmrg   }
134*0bfacb9bSmrg 
get_edge_for_cfg_edge(edge e)135*0bfacb9bSmrg   cfg_superedge *get_edge_for_cfg_edge (edge e) const
136*0bfacb9bSmrg   {
137*0bfacb9bSmrg     return (*const_cast <cfg_edge_to_cfg_superedge_t &>
138*0bfacb9bSmrg 	      (m_cfg_edge_to_cfg_superedge).get (e));
139*0bfacb9bSmrg   }
140*0bfacb9bSmrg 
get_supernode_for_stmt(const gimple * stmt)141*0bfacb9bSmrg   supernode *get_supernode_for_stmt (const gimple *stmt) const
142*0bfacb9bSmrg   {
143*0bfacb9bSmrg     return (*const_cast <stmt_to_node_t &>(m_stmt_to_node_t).get
144*0bfacb9bSmrg 	    (const_cast <gimple *> (stmt)));
145*0bfacb9bSmrg   }
146*0bfacb9bSmrg 
147*0bfacb9bSmrg   void dump_dot_to_pp (pretty_printer *pp, const dump_args_t &) const;
148*0bfacb9bSmrg   void dump_dot_to_file (FILE *fp, const dump_args_t &) const;
149*0bfacb9bSmrg   void dump_dot (const char *path, const dump_args_t &) const;
150*0bfacb9bSmrg 
num_nodes()151*0bfacb9bSmrg   int num_nodes () const { return m_nodes.length (); }
num_edges()152*0bfacb9bSmrg   int num_edges () const { return m_edges.length (); }
153*0bfacb9bSmrg 
get_node_by_index(int idx)154*0bfacb9bSmrg   supernode *get_node_by_index (int idx) const
155*0bfacb9bSmrg   {
156*0bfacb9bSmrg     return m_nodes[idx];
157*0bfacb9bSmrg   }
158*0bfacb9bSmrg 
get_num_snodes(const function * fun)159*0bfacb9bSmrg   unsigned get_num_snodes (const function *fun) const
160*0bfacb9bSmrg   {
161*0bfacb9bSmrg     function_to_num_snodes_t &map
162*0bfacb9bSmrg       = const_cast <function_to_num_snodes_t &>(m_function_to_num_snodes);
163*0bfacb9bSmrg     return *map.get (fun);
164*0bfacb9bSmrg   }
165*0bfacb9bSmrg 
166*0bfacb9bSmrg private:
167*0bfacb9bSmrg   supernode *add_node (function *fun, basic_block bb, gcall *returning_call,
168*0bfacb9bSmrg 		       gimple_seq phi_nodes);
169*0bfacb9bSmrg   cfg_superedge *add_cfg_edge (supernode *src, supernode *dest, ::edge e, int idx);
170*0bfacb9bSmrg   call_superedge *add_call_superedge (supernode *src, supernode *dest,
171*0bfacb9bSmrg 				      cgraph_edge *cedge);
172*0bfacb9bSmrg   return_superedge *add_return_superedge (supernode *src, supernode *dest,
173*0bfacb9bSmrg 					  cgraph_edge *cedge);
174*0bfacb9bSmrg 
175*0bfacb9bSmrg   /* Data.  */
176*0bfacb9bSmrg 
177*0bfacb9bSmrg   typedef ordered_hash_map<basic_block, supernode *> bb_to_node_t;
178*0bfacb9bSmrg   bb_to_node_t m_bb_to_initial_node;
179*0bfacb9bSmrg   bb_to_node_t m_bb_to_final_node;
180*0bfacb9bSmrg 
181*0bfacb9bSmrg   typedef ordered_hash_map<cgraph_edge *, supernode *> cgraph_edge_to_node_t;
182*0bfacb9bSmrg   cgraph_edge_to_node_t m_cgraph_edge_to_caller_prev_node;
183*0bfacb9bSmrg   cgraph_edge_to_node_t m_cgraph_edge_to_caller_next_node;
184*0bfacb9bSmrg 
185*0bfacb9bSmrg   typedef ordered_hash_map< ::edge, cfg_superedge *>
186*0bfacb9bSmrg     cfg_edge_to_cfg_superedge_t;
187*0bfacb9bSmrg   cfg_edge_to_cfg_superedge_t m_cfg_edge_to_cfg_superedge;
188*0bfacb9bSmrg 
189*0bfacb9bSmrg   typedef ordered_hash_map<cgraph_edge *, call_superedge *>
190*0bfacb9bSmrg     cgraph_edge_to_call_superedge_t;
191*0bfacb9bSmrg   cgraph_edge_to_call_superedge_t m_cgraph_edge_to_call_superedge;
192*0bfacb9bSmrg 
193*0bfacb9bSmrg   typedef ordered_hash_map<cgraph_edge *, return_superedge *>
194*0bfacb9bSmrg     cgraph_edge_to_return_superedge_t;
195*0bfacb9bSmrg   cgraph_edge_to_return_superedge_t m_cgraph_edge_to_return_superedge;
196*0bfacb9bSmrg 
197*0bfacb9bSmrg   typedef ordered_hash_map<cgraph_edge *, superedge *>
198*0bfacb9bSmrg     cgraph_edge_to_intraproc_superedge_t;
199*0bfacb9bSmrg   cgraph_edge_to_intraproc_superedge_t m_cgraph_edge_to_intraproc_superedge;
200*0bfacb9bSmrg 
201*0bfacb9bSmrg   typedef ordered_hash_map<gimple *, supernode *> stmt_to_node_t;
202*0bfacb9bSmrg   stmt_to_node_t m_stmt_to_node_t;
203*0bfacb9bSmrg 
204*0bfacb9bSmrg   typedef hash_map<const function *, unsigned> function_to_num_snodes_t;
205*0bfacb9bSmrg   function_to_num_snodes_t m_function_to_num_snodes;
206*0bfacb9bSmrg };
207*0bfacb9bSmrg 
208*0bfacb9bSmrg /* A node within a supergraph.  */
209*0bfacb9bSmrg 
210*0bfacb9bSmrg class supernode : public dnode<supergraph_traits>
211*0bfacb9bSmrg {
212*0bfacb9bSmrg  public:
supernode(function * fun,basic_block bb,gcall * returning_call,gimple_seq phi_nodes,int index)213*0bfacb9bSmrg   supernode (function *fun, basic_block bb, gcall *returning_call,
214*0bfacb9bSmrg 	     gimple_seq phi_nodes, int index)
215*0bfacb9bSmrg   : m_fun (fun), m_bb (bb), m_returning_call (returning_call),
216*0bfacb9bSmrg     m_phi_nodes (phi_nodes), m_index (index)
217*0bfacb9bSmrg   {}
218*0bfacb9bSmrg 
get_function()219*0bfacb9bSmrg   function *get_function () const { return m_fun; }
220*0bfacb9bSmrg 
entry_p()221*0bfacb9bSmrg   bool entry_p () const
222*0bfacb9bSmrg   {
223*0bfacb9bSmrg     return m_bb == ENTRY_BLOCK_PTR_FOR_FN (m_fun);
224*0bfacb9bSmrg   }
225*0bfacb9bSmrg 
return_p()226*0bfacb9bSmrg   bool return_p () const
227*0bfacb9bSmrg   {
228*0bfacb9bSmrg     return m_bb == EXIT_BLOCK_PTR_FOR_FN (m_fun);
229*0bfacb9bSmrg   }
230*0bfacb9bSmrg 
231*0bfacb9bSmrg   void dump_dot (graphviz_out *gv, const dump_args_t &args) const OVERRIDE;
232*0bfacb9bSmrg   void dump_dot_id (pretty_printer *pp) const;
233*0bfacb9bSmrg 
234*0bfacb9bSmrg   location_t get_start_location () const;
235*0bfacb9bSmrg   location_t get_end_location () const;
236*0bfacb9bSmrg 
237*0bfacb9bSmrg   /* Returns iterator at the start of the list of phi nodes, if any.  */
start_phis()238*0bfacb9bSmrg   gphi_iterator start_phis ()
239*0bfacb9bSmrg   {
240*0bfacb9bSmrg     gimple_seq *pseq = &m_phi_nodes;
241*0bfacb9bSmrg 
242*0bfacb9bSmrg     /* Adapted from gsi_start_1. */
243*0bfacb9bSmrg     gphi_iterator i;
244*0bfacb9bSmrg 
245*0bfacb9bSmrg     i.ptr = gimple_seq_first (*pseq);
246*0bfacb9bSmrg     i.seq = pseq;
247*0bfacb9bSmrg     i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
248*0bfacb9bSmrg 
249*0bfacb9bSmrg     return i;
250*0bfacb9bSmrg   }
251*0bfacb9bSmrg 
get_last_stmt()252*0bfacb9bSmrg   gimple *get_last_stmt () const
253*0bfacb9bSmrg   {
254*0bfacb9bSmrg     if (m_stmts.length () == 0)
255*0bfacb9bSmrg       return NULL;
256*0bfacb9bSmrg     return m_stmts[m_stmts.length () - 1];
257*0bfacb9bSmrg   }
258*0bfacb9bSmrg 
get_final_call()259*0bfacb9bSmrg   gcall *get_final_call () const
260*0bfacb9bSmrg   {
261*0bfacb9bSmrg     gimple *stmt = get_last_stmt ();
262*0bfacb9bSmrg     if (stmt == NULL)
263*0bfacb9bSmrg       return NULL;
264*0bfacb9bSmrg     return dyn_cast<gcall *> (stmt);
265*0bfacb9bSmrg   }
266*0bfacb9bSmrg 
267*0bfacb9bSmrg   unsigned int get_stmt_index (const gimple *stmt) const;
268*0bfacb9bSmrg 
269*0bfacb9bSmrg   function * const m_fun; // alternatively could be stored as runs of indices within the supergraph
270*0bfacb9bSmrg   const basic_block m_bb;
271*0bfacb9bSmrg   gcall * const m_returning_call; // for handling the result of a returned call
272*0bfacb9bSmrg   gimple_seq m_phi_nodes; // ptr to that of the underlying BB, for the first supernode for the BB
273*0bfacb9bSmrg   auto_vec<gimple *> m_stmts;
274*0bfacb9bSmrg   const int m_index; /* unique within the supergraph as a whole.  */
275*0bfacb9bSmrg };
276*0bfacb9bSmrg 
277*0bfacb9bSmrg /* An abstract base class encapsulating an edge within a supergraph.
278*0bfacb9bSmrg    Edges can be CFG edges, or calls/returns for callgraph edges.  */
279*0bfacb9bSmrg 
280*0bfacb9bSmrg class superedge : public dedge<supergraph_traits>
281*0bfacb9bSmrg {
282*0bfacb9bSmrg  public:
~superedge()283*0bfacb9bSmrg   virtual ~superedge () {}
284*0bfacb9bSmrg 
285*0bfacb9bSmrg   void dump (pretty_printer *pp) const;
286*0bfacb9bSmrg   void dump () const;
287*0bfacb9bSmrg   void dump_dot (graphviz_out *gv, const dump_args_t &args) const;
288*0bfacb9bSmrg 
289*0bfacb9bSmrg   virtual void dump_label_to_pp (pretty_printer *pp,
290*0bfacb9bSmrg 				 bool user_facing) const = 0;
291*0bfacb9bSmrg 
get_kind()292*0bfacb9bSmrg   enum edge_kind get_kind () const { return m_kind; }
293*0bfacb9bSmrg 
dyn_cast_cfg_superedge()294*0bfacb9bSmrg   virtual cfg_superedge *dyn_cast_cfg_superedge () { return NULL; }
dyn_cast_cfg_superedge()295*0bfacb9bSmrg   virtual const cfg_superedge *dyn_cast_cfg_superedge () const { return NULL; }
dyn_cast_switch_cfg_superedge()296*0bfacb9bSmrg   virtual const switch_cfg_superedge *dyn_cast_switch_cfg_superedge () const { return NULL; }
dyn_cast_callgraph_superedge()297*0bfacb9bSmrg   virtual callgraph_superedge *dyn_cast_callgraph_superedge () { return NULL; }
dyn_cast_callgraph_superedge()298*0bfacb9bSmrg   virtual const callgraph_superedge *dyn_cast_callgraph_superedge () const { return NULL; }
dyn_cast_call_superedge()299*0bfacb9bSmrg   virtual call_superedge *dyn_cast_call_superedge () { return NULL; }
dyn_cast_call_superedge()300*0bfacb9bSmrg   virtual const call_superedge *dyn_cast_call_superedge () const { return NULL; }
dyn_cast_return_superedge()301*0bfacb9bSmrg   virtual return_superedge *dyn_cast_return_superedge () { return NULL; }
dyn_cast_return_superedge()302*0bfacb9bSmrg   virtual const return_superedge *dyn_cast_return_superedge () const { return NULL; }
303*0bfacb9bSmrg 
304*0bfacb9bSmrg   ::edge get_any_cfg_edge () const;
305*0bfacb9bSmrg   cgraph_edge *get_any_callgraph_edge () const;
306*0bfacb9bSmrg 
307*0bfacb9bSmrg   char *get_description (bool user_facing) const;
308*0bfacb9bSmrg 
309*0bfacb9bSmrg  protected:
superedge(supernode * src,supernode * dest,enum edge_kind kind)310*0bfacb9bSmrg   superedge (supernode *src, supernode *dest, enum edge_kind kind)
311*0bfacb9bSmrg   : dedge<supergraph_traits> (src, dest),
312*0bfacb9bSmrg     m_kind (kind)
313*0bfacb9bSmrg   {}
314*0bfacb9bSmrg 
315*0bfacb9bSmrg  public:
316*0bfacb9bSmrg   const enum edge_kind m_kind;
317*0bfacb9bSmrg };
318*0bfacb9bSmrg 
319*0bfacb9bSmrg /* An ID representing an expression at a callsite:
320*0bfacb9bSmrg    either a parameter index, or the return value (or unknown).  */
321*0bfacb9bSmrg 
322*0bfacb9bSmrg class callsite_expr
323*0bfacb9bSmrg {
324*0bfacb9bSmrg  public:
callsite_expr()325*0bfacb9bSmrg   callsite_expr () : m_val (-1) {}
326*0bfacb9bSmrg 
from_zero_based_param(int idx)327*0bfacb9bSmrg   static callsite_expr from_zero_based_param (int idx)
328*0bfacb9bSmrg   {
329*0bfacb9bSmrg     return callsite_expr (idx + 1);
330*0bfacb9bSmrg   }
331*0bfacb9bSmrg 
from_return_value()332*0bfacb9bSmrg   static callsite_expr from_return_value ()
333*0bfacb9bSmrg   {
334*0bfacb9bSmrg     return callsite_expr (0);
335*0bfacb9bSmrg   }
336*0bfacb9bSmrg 
param_p()337*0bfacb9bSmrg   bool param_p () const
338*0bfacb9bSmrg   {
339*0bfacb9bSmrg     return m_val > 0;
340*0bfacb9bSmrg   }
341*0bfacb9bSmrg 
return_value_p()342*0bfacb9bSmrg   bool return_value_p () const
343*0bfacb9bSmrg   {
344*0bfacb9bSmrg     return m_val == 0;
345*0bfacb9bSmrg   }
346*0bfacb9bSmrg 
347*0bfacb9bSmrg  private:
callsite_expr(int val)348*0bfacb9bSmrg   callsite_expr (int val) : m_val (val) {}
349*0bfacb9bSmrg 
350*0bfacb9bSmrg   int m_val; /* 1-based parm, 0 for return value, or -1 for "unknown".  */
351*0bfacb9bSmrg };
352*0bfacb9bSmrg 
353*0bfacb9bSmrg /* A subclass of superedge with an associated callgraph edge (either a
354*0bfacb9bSmrg    call or a return).  */
355*0bfacb9bSmrg 
356*0bfacb9bSmrg class callgraph_superedge : public superedge
357*0bfacb9bSmrg {
358*0bfacb9bSmrg  public:
callgraph_superedge(supernode * src,supernode * dst,enum edge_kind kind,cgraph_edge * cedge)359*0bfacb9bSmrg   callgraph_superedge (supernode *src, supernode *dst, enum edge_kind kind,
360*0bfacb9bSmrg 		       cgraph_edge *cedge)
361*0bfacb9bSmrg   : superedge (src, dst, kind),
362*0bfacb9bSmrg     m_cedge (cedge)
363*0bfacb9bSmrg   {}
364*0bfacb9bSmrg 
365*0bfacb9bSmrg   void dump_label_to_pp (pretty_printer *pp, bool user_facing) const
366*0bfacb9bSmrg     FINAL OVERRIDE;
367*0bfacb9bSmrg 
368*0bfacb9bSmrg   function *get_callee_function () const;
369*0bfacb9bSmrg   function *get_caller_function () const;
370*0bfacb9bSmrg   tree get_callee_decl () const;
371*0bfacb9bSmrg   tree get_caller_decl () const;
get_call_stmt()372*0bfacb9bSmrg   gcall *get_call_stmt () const { return m_cedge->call_stmt; }
373*0bfacb9bSmrg   tree get_arg_for_parm (tree parm, callsite_expr *out) const;
374*0bfacb9bSmrg   tree get_parm_for_arg (tree arg, callsite_expr *out) const;
375*0bfacb9bSmrg   tree map_expr_from_caller_to_callee (tree caller_expr,
376*0bfacb9bSmrg 				       callsite_expr *out) const;
377*0bfacb9bSmrg   tree map_expr_from_callee_to_caller (tree callee_expr,
378*0bfacb9bSmrg 				       callsite_expr *out) const;
379*0bfacb9bSmrg 
380*0bfacb9bSmrg   cgraph_edge *const m_cedge;
381*0bfacb9bSmrg };
382*0bfacb9bSmrg 
383*0bfacb9bSmrg } // namespace ana
384*0bfacb9bSmrg 
385*0bfacb9bSmrg template <>
386*0bfacb9bSmrg template <>
387*0bfacb9bSmrg inline bool
test(const superedge * sedge)388*0bfacb9bSmrg is_a_helper <const callgraph_superedge *>::test (const superedge *sedge)
389*0bfacb9bSmrg {
390*0bfacb9bSmrg   return (sedge->get_kind () == SUPEREDGE_INTRAPROCEDURAL_CALL
391*0bfacb9bSmrg 	  || sedge->get_kind () == SUPEREDGE_CALL
392*0bfacb9bSmrg 	  || sedge->get_kind () == SUPEREDGE_RETURN);
393*0bfacb9bSmrg }
394*0bfacb9bSmrg 
395*0bfacb9bSmrg namespace ana {
396*0bfacb9bSmrg 
397*0bfacb9bSmrg /* A subclass of superedge representing an interprocedural call.  */
398*0bfacb9bSmrg 
399*0bfacb9bSmrg class call_superedge : public callgraph_superedge
400*0bfacb9bSmrg {
401*0bfacb9bSmrg  public:
call_superedge(supernode * src,supernode * dst,cgraph_edge * cedge)402*0bfacb9bSmrg   call_superedge (supernode *src, supernode *dst, cgraph_edge *cedge)
403*0bfacb9bSmrg   : callgraph_superedge (src, dst, SUPEREDGE_CALL, cedge)
404*0bfacb9bSmrg   {}
405*0bfacb9bSmrg 
dyn_cast_callgraph_superedge()406*0bfacb9bSmrg   callgraph_superedge *dyn_cast_callgraph_superedge () FINAL OVERRIDE
407*0bfacb9bSmrg   {
408*0bfacb9bSmrg     return this;
409*0bfacb9bSmrg   }
dyn_cast_callgraph_superedge()410*0bfacb9bSmrg   const callgraph_superedge *dyn_cast_callgraph_superedge () const
411*0bfacb9bSmrg     FINAL OVERRIDE
412*0bfacb9bSmrg   {
413*0bfacb9bSmrg     return this;
414*0bfacb9bSmrg   }
415*0bfacb9bSmrg 
dyn_cast_call_superedge()416*0bfacb9bSmrg   call_superedge *dyn_cast_call_superedge () FINAL OVERRIDE
417*0bfacb9bSmrg   {
418*0bfacb9bSmrg     return this;
419*0bfacb9bSmrg   }
dyn_cast_call_superedge()420*0bfacb9bSmrg   const call_superedge *dyn_cast_call_superedge () const FINAL OVERRIDE
421*0bfacb9bSmrg   {
422*0bfacb9bSmrg     return this;
423*0bfacb9bSmrg   }
424*0bfacb9bSmrg 
get_edge_for_return(const supergraph & sg)425*0bfacb9bSmrg   return_superedge *get_edge_for_return (const supergraph &sg) const
426*0bfacb9bSmrg   {
427*0bfacb9bSmrg     return sg.get_edge_for_return (m_cedge);
428*0bfacb9bSmrg   }
429*0bfacb9bSmrg };
430*0bfacb9bSmrg 
431*0bfacb9bSmrg } // namespace ana
432*0bfacb9bSmrg 
433*0bfacb9bSmrg template <>
434*0bfacb9bSmrg template <>
435*0bfacb9bSmrg inline bool
test(const superedge * sedge)436*0bfacb9bSmrg is_a_helper <const call_superedge *>::test (const superedge *sedge)
437*0bfacb9bSmrg {
438*0bfacb9bSmrg   return sedge->get_kind () == SUPEREDGE_CALL;
439*0bfacb9bSmrg }
440*0bfacb9bSmrg 
441*0bfacb9bSmrg namespace ana {
442*0bfacb9bSmrg 
443*0bfacb9bSmrg /* A subclass of superedge represesnting an interprocedural return.  */
444*0bfacb9bSmrg 
445*0bfacb9bSmrg class return_superedge : public callgraph_superedge
446*0bfacb9bSmrg {
447*0bfacb9bSmrg  public:
return_superedge(supernode * src,supernode * dst,cgraph_edge * cedge)448*0bfacb9bSmrg   return_superedge (supernode *src, supernode *dst, cgraph_edge *cedge)
449*0bfacb9bSmrg   : callgraph_superedge (src, dst, SUPEREDGE_RETURN, cedge)
450*0bfacb9bSmrg   {}
451*0bfacb9bSmrg 
dyn_cast_callgraph_superedge()452*0bfacb9bSmrg   callgraph_superedge *dyn_cast_callgraph_superedge () FINAL OVERRIDE
453*0bfacb9bSmrg   {
454*0bfacb9bSmrg     return this;
455*0bfacb9bSmrg   }
dyn_cast_callgraph_superedge()456*0bfacb9bSmrg   const callgraph_superedge *dyn_cast_callgraph_superedge () const
457*0bfacb9bSmrg     FINAL OVERRIDE
458*0bfacb9bSmrg   { return this; }
459*0bfacb9bSmrg 
dyn_cast_return_superedge()460*0bfacb9bSmrg   return_superedge *dyn_cast_return_superedge () FINAL OVERRIDE { return this; }
dyn_cast_return_superedge()461*0bfacb9bSmrg   const return_superedge *dyn_cast_return_superedge () const FINAL OVERRIDE
462*0bfacb9bSmrg   {
463*0bfacb9bSmrg     return this;
464*0bfacb9bSmrg   }
465*0bfacb9bSmrg 
get_edge_for_call(const supergraph & sg)466*0bfacb9bSmrg   call_superedge *get_edge_for_call (const supergraph &sg) const
467*0bfacb9bSmrg   {
468*0bfacb9bSmrg     return sg.get_edge_for_call (m_cedge);
469*0bfacb9bSmrg   }
470*0bfacb9bSmrg };
471*0bfacb9bSmrg 
472*0bfacb9bSmrg } // namespace ana
473*0bfacb9bSmrg 
474*0bfacb9bSmrg template <>
475*0bfacb9bSmrg template <>
476*0bfacb9bSmrg inline bool
test(const superedge * sedge)477*0bfacb9bSmrg is_a_helper <const return_superedge *>::test (const superedge *sedge)
478*0bfacb9bSmrg {
479*0bfacb9bSmrg   return sedge->get_kind () == SUPEREDGE_RETURN;
480*0bfacb9bSmrg }
481*0bfacb9bSmrg 
482*0bfacb9bSmrg namespace ana {
483*0bfacb9bSmrg 
484*0bfacb9bSmrg /* A subclass of superedge that corresponds to a CFG edge.  */
485*0bfacb9bSmrg 
486*0bfacb9bSmrg class cfg_superedge : public superedge
487*0bfacb9bSmrg {
488*0bfacb9bSmrg  public:
cfg_superedge(supernode * src,supernode * dst,::edge e)489*0bfacb9bSmrg   cfg_superedge (supernode *src, supernode *dst, ::edge e)
490*0bfacb9bSmrg   : superedge (src, dst, SUPEREDGE_CFG_EDGE),
491*0bfacb9bSmrg     m_cfg_edge (e)
492*0bfacb9bSmrg   {}
493*0bfacb9bSmrg 
494*0bfacb9bSmrg   void dump_label_to_pp (pretty_printer *pp, bool user_facing) const OVERRIDE;
dyn_cast_cfg_superedge()495*0bfacb9bSmrg   cfg_superedge *dyn_cast_cfg_superedge () FINAL OVERRIDE { return this; }
dyn_cast_cfg_superedge()496*0bfacb9bSmrg   const cfg_superedge *dyn_cast_cfg_superedge () const FINAL OVERRIDE { return this; }
497*0bfacb9bSmrg 
get_cfg_edge()498*0bfacb9bSmrg   ::edge get_cfg_edge () const { return m_cfg_edge; }
get_flags()499*0bfacb9bSmrg   int get_flags () const { return m_cfg_edge->flags; }
true_value_p()500*0bfacb9bSmrg   int true_value_p () const { return get_flags () & EDGE_TRUE_VALUE; }
false_value_p()501*0bfacb9bSmrg   int false_value_p () const { return get_flags () & EDGE_FALSE_VALUE; }
back_edge_p()502*0bfacb9bSmrg   int back_edge_p () const { return get_flags () & EDGE_DFS_BACK; }
503*0bfacb9bSmrg 
504*0bfacb9bSmrg   tree get_phi_arg (const gphi *phi) const;
505*0bfacb9bSmrg 
506*0bfacb9bSmrg  private:
507*0bfacb9bSmrg   const ::edge m_cfg_edge;
508*0bfacb9bSmrg };
509*0bfacb9bSmrg 
510*0bfacb9bSmrg } // namespace ana
511*0bfacb9bSmrg 
512*0bfacb9bSmrg template <>
513*0bfacb9bSmrg template <>
514*0bfacb9bSmrg inline bool
test(const superedge * sedge)515*0bfacb9bSmrg is_a_helper <const cfg_superedge *>::test (const superedge *sedge)
516*0bfacb9bSmrg {
517*0bfacb9bSmrg   return sedge->get_kind () == SUPEREDGE_CFG_EDGE;
518*0bfacb9bSmrg }
519*0bfacb9bSmrg 
520*0bfacb9bSmrg namespace ana {
521*0bfacb9bSmrg 
522*0bfacb9bSmrg /* A subclass for edges from switch statements, retaining enough
523*0bfacb9bSmrg    information to identify the pertinent case, and for adding labels
524*0bfacb9bSmrg    when rendering via graphviz.  */
525*0bfacb9bSmrg 
526*0bfacb9bSmrg class switch_cfg_superedge : public cfg_superedge {
527*0bfacb9bSmrg  public:
switch_cfg_superedge(supernode * src,supernode * dst,::edge e,int idx)528*0bfacb9bSmrg   switch_cfg_superedge (supernode *src, supernode *dst, ::edge e, int idx)
529*0bfacb9bSmrg   : cfg_superedge (src, dst, e),
530*0bfacb9bSmrg     m_idx (idx)
531*0bfacb9bSmrg   {}
532*0bfacb9bSmrg 
dyn_cast_switch_cfg_superedge()533*0bfacb9bSmrg   const switch_cfg_superedge *dyn_cast_switch_cfg_superedge () const
534*0bfacb9bSmrg     FINAL OVERRIDE
535*0bfacb9bSmrg   {
536*0bfacb9bSmrg     return this;
537*0bfacb9bSmrg   }
538*0bfacb9bSmrg 
539*0bfacb9bSmrg   void dump_label_to_pp (pretty_printer *pp, bool user_facing) const
540*0bfacb9bSmrg     FINAL OVERRIDE;
541*0bfacb9bSmrg 
get_switch_stmt()542*0bfacb9bSmrg   gswitch *get_switch_stmt () const
543*0bfacb9bSmrg   {
544*0bfacb9bSmrg     return as_a <gswitch *> (m_src->get_last_stmt ());
545*0bfacb9bSmrg   }
546*0bfacb9bSmrg 
547*0bfacb9bSmrg   tree get_case_label () const;
548*0bfacb9bSmrg 
549*0bfacb9bSmrg  private:
550*0bfacb9bSmrg   const int m_idx;
551*0bfacb9bSmrg };
552*0bfacb9bSmrg 
553*0bfacb9bSmrg } // namespace ana
554*0bfacb9bSmrg 
555*0bfacb9bSmrg template <>
556*0bfacb9bSmrg template <>
557*0bfacb9bSmrg inline bool
test(const superedge * sedge)558*0bfacb9bSmrg is_a_helper <const switch_cfg_superedge *>::test (const superedge *sedge)
559*0bfacb9bSmrg {
560*0bfacb9bSmrg   return sedge->dyn_cast_switch_cfg_superedge () != NULL;
561*0bfacb9bSmrg }
562*0bfacb9bSmrg 
563*0bfacb9bSmrg namespace ana {
564*0bfacb9bSmrg 
565*0bfacb9bSmrg /* Base class for adding additional content to the .dot output
566*0bfacb9bSmrg    for a supergraph.  */
567*0bfacb9bSmrg 
568*0bfacb9bSmrg class dot_annotator
569*0bfacb9bSmrg {
570*0bfacb9bSmrg  public:
~dot_annotator()571*0bfacb9bSmrg   virtual ~dot_annotator () {}
add_node_annotations(graphviz_out * gv ATTRIBUTE_UNUSED,const supernode & n ATTRIBUTE_UNUSED,bool within_table ATTRIBUTE_UNUSED)572*0bfacb9bSmrg   virtual bool add_node_annotations (graphviz_out *gv ATTRIBUTE_UNUSED,
573*0bfacb9bSmrg 				     const supernode &n ATTRIBUTE_UNUSED,
574*0bfacb9bSmrg 				     bool within_table ATTRIBUTE_UNUSED)
575*0bfacb9bSmrg     const
576*0bfacb9bSmrg   {
577*0bfacb9bSmrg     return false;
578*0bfacb9bSmrg   }
add_stmt_annotations(graphviz_out * gv ATTRIBUTE_UNUSED,const gimple * stmt ATTRIBUTE_UNUSED,bool within_row ATTRIBUTE_UNUSED)579*0bfacb9bSmrg   virtual void add_stmt_annotations (graphviz_out *gv ATTRIBUTE_UNUSED,
580*0bfacb9bSmrg 				     const gimple *stmt ATTRIBUTE_UNUSED,
581*0bfacb9bSmrg 				     bool within_row ATTRIBUTE_UNUSED)
582*0bfacb9bSmrg     const {}
add_after_node_annotations(graphviz_out * gv ATTRIBUTE_UNUSED,const supernode & n ATTRIBUTE_UNUSED)583*0bfacb9bSmrg   virtual bool add_after_node_annotations (graphviz_out *gv ATTRIBUTE_UNUSED,
584*0bfacb9bSmrg 					   const supernode &n ATTRIBUTE_UNUSED)
585*0bfacb9bSmrg     const
586*0bfacb9bSmrg   {
587*0bfacb9bSmrg     return false;
588*0bfacb9bSmrg   }
589*0bfacb9bSmrg };
590*0bfacb9bSmrg 
591*0bfacb9bSmrg extern cgraph_edge *supergraph_call_edge (function *fun, gimple *stmt);
592*0bfacb9bSmrg 
593*0bfacb9bSmrg } // namespace ana
594*0bfacb9bSmrg 
595*0bfacb9bSmrg #endif /* GCC_ANALYZER_SUPERGRAPH_H */
596