1*0bfacb9bSmrg /* Classes for representing locations within the program.
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_PROGRAM_POINT_H
22*0bfacb9bSmrg #define GCC_ANALYZER_PROGRAM_POINT_H
23*0bfacb9bSmrg 
24*0bfacb9bSmrg namespace ana {
25*0bfacb9bSmrg 
26*0bfacb9bSmrg class exploded_graph;
27*0bfacb9bSmrg 
28*0bfacb9bSmrg /* An enum for distinguishing the various kinds of program_point.  */
29*0bfacb9bSmrg 
30*0bfacb9bSmrg enum point_kind {
31*0bfacb9bSmrg   /* A "fake" node which has edges to all entrypoints.  */
32*0bfacb9bSmrg   PK_ORIGIN,
33*0bfacb9bSmrg 
34*0bfacb9bSmrg   PK_BEFORE_SUPERNODE,
35*0bfacb9bSmrg   PK_BEFORE_STMT,
36*0bfacb9bSmrg   PK_AFTER_SUPERNODE,
37*0bfacb9bSmrg 
38*0bfacb9bSmrg   /* Special values used for hash_map:  */
39*0bfacb9bSmrg   PK_EMPTY,
40*0bfacb9bSmrg   PK_DELETED,
41*0bfacb9bSmrg 
42*0bfacb9bSmrg   NUM_POINT_KINDS
43*0bfacb9bSmrg };
44*0bfacb9bSmrg 
45*0bfacb9bSmrg extern const char *point_kind_to_string (enum point_kind pk);
46*0bfacb9bSmrg 
47*0bfacb9bSmrg class format
48*0bfacb9bSmrg {
49*0bfacb9bSmrg public:
format(bool newlines)50*0bfacb9bSmrg   format (bool newlines) : m_newlines (newlines) {}
51*0bfacb9bSmrg 
spacer(pretty_printer * pp)52*0bfacb9bSmrg   void spacer (pretty_printer *pp) const
53*0bfacb9bSmrg   {
54*0bfacb9bSmrg     if (m_newlines)
55*0bfacb9bSmrg       pp_newline (pp);
56*0bfacb9bSmrg     else
57*0bfacb9bSmrg       pp_space (pp);
58*0bfacb9bSmrg   }
59*0bfacb9bSmrg 
60*0bfacb9bSmrg   bool m_newlines;
61*0bfacb9bSmrg };
62*0bfacb9bSmrg 
63*0bfacb9bSmrg /* A class for representing a location within the program, without
64*0bfacb9bSmrg    interprocedural information.
65*0bfacb9bSmrg 
66*0bfacb9bSmrg    This represents a fine-grained location within the supergraph (or
67*0bfacb9bSmrg    within one of its nodes).  */
68*0bfacb9bSmrg 
69*0bfacb9bSmrg class function_point
70*0bfacb9bSmrg {
71*0bfacb9bSmrg public:
function_point(const supernode * supernode,const superedge * from_edge,unsigned stmt_idx,enum point_kind kind)72*0bfacb9bSmrg   function_point (const supernode *supernode,
73*0bfacb9bSmrg 		  const superedge *from_edge,
74*0bfacb9bSmrg 		  unsigned stmt_idx,
75*0bfacb9bSmrg 		  enum point_kind kind)
76*0bfacb9bSmrg   : m_supernode (supernode), m_from_edge (from_edge),
77*0bfacb9bSmrg     m_stmt_idx (stmt_idx), m_kind (kind)
78*0bfacb9bSmrg   {
79*0bfacb9bSmrg     if (from_edge)
80*0bfacb9bSmrg       {
81*0bfacb9bSmrg 	gcc_checking_assert (m_kind == PK_BEFORE_SUPERNODE);
82*0bfacb9bSmrg 	gcc_checking_assert (from_edge->get_kind () == SUPEREDGE_CFG_EDGE);
83*0bfacb9bSmrg       }
84*0bfacb9bSmrg     if (stmt_idx)
85*0bfacb9bSmrg       gcc_checking_assert (m_kind == PK_BEFORE_STMT);
86*0bfacb9bSmrg   }
87*0bfacb9bSmrg 
88*0bfacb9bSmrg   void print (pretty_printer *pp, const format &f) const;
89*0bfacb9bSmrg   void print_source_line (pretty_printer *pp) const;
90*0bfacb9bSmrg   void dump () const;
91*0bfacb9bSmrg 
92*0bfacb9bSmrg   hashval_t hash () const;
93*0bfacb9bSmrg   bool operator== (const function_point &other) const
94*0bfacb9bSmrg   {
95*0bfacb9bSmrg     return (m_supernode == other.m_supernode
96*0bfacb9bSmrg 	    && m_from_edge == other.m_from_edge
97*0bfacb9bSmrg 	    && m_stmt_idx == other.m_stmt_idx
98*0bfacb9bSmrg 	    && m_kind == other.m_kind);
99*0bfacb9bSmrg   }
100*0bfacb9bSmrg 
101*0bfacb9bSmrg   /* Accessors.  */
102*0bfacb9bSmrg 
get_supernode()103*0bfacb9bSmrg   const supernode *get_supernode () const { return m_supernode; }
get_function()104*0bfacb9bSmrg   function *get_function () const
105*0bfacb9bSmrg   {
106*0bfacb9bSmrg     if (m_supernode)
107*0bfacb9bSmrg       return m_supernode->m_fun;
108*0bfacb9bSmrg     else
109*0bfacb9bSmrg       return NULL;
110*0bfacb9bSmrg   }
111*0bfacb9bSmrg   const gimple *get_stmt () const;
112*0bfacb9bSmrg   location_t get_location () const;
get_kind()113*0bfacb9bSmrg   enum point_kind get_kind () const { return m_kind; }
get_from_edge()114*0bfacb9bSmrg   const superedge *get_from_edge () const
115*0bfacb9bSmrg   {
116*0bfacb9bSmrg     return m_from_edge;
117*0bfacb9bSmrg   }
get_stmt_idx()118*0bfacb9bSmrg   unsigned get_stmt_idx () const
119*0bfacb9bSmrg   {
120*0bfacb9bSmrg     gcc_assert (m_kind == PK_BEFORE_STMT);
121*0bfacb9bSmrg     return m_stmt_idx;
122*0bfacb9bSmrg   }
123*0bfacb9bSmrg 
124*0bfacb9bSmrg   /* Factory functions for making various kinds of program_point.  */
125*0bfacb9bSmrg 
from_function_entry(const supergraph & sg,function * fun)126*0bfacb9bSmrg   static function_point from_function_entry (const supergraph &sg,
127*0bfacb9bSmrg 					    function *fun)
128*0bfacb9bSmrg   {
129*0bfacb9bSmrg     return before_supernode (sg.get_node_for_function_entry (fun),
130*0bfacb9bSmrg 			     NULL);
131*0bfacb9bSmrg   }
132*0bfacb9bSmrg 
before_supernode(const supernode * supernode,const superedge * from_edge)133*0bfacb9bSmrg   static function_point before_supernode (const supernode *supernode,
134*0bfacb9bSmrg 					  const superedge *from_edge)
135*0bfacb9bSmrg   {
136*0bfacb9bSmrg     if (from_edge && from_edge->get_kind () != SUPEREDGE_CFG_EDGE)
137*0bfacb9bSmrg       from_edge = NULL;
138*0bfacb9bSmrg     return function_point (supernode, from_edge, 0, PK_BEFORE_SUPERNODE);
139*0bfacb9bSmrg   }
140*0bfacb9bSmrg 
before_stmt(const supernode * supernode,unsigned stmt_idx)141*0bfacb9bSmrg   static function_point before_stmt (const supernode *supernode,
142*0bfacb9bSmrg 				     unsigned stmt_idx)
143*0bfacb9bSmrg   {
144*0bfacb9bSmrg     return function_point (supernode, NULL, stmt_idx, PK_BEFORE_STMT);
145*0bfacb9bSmrg   }
146*0bfacb9bSmrg 
after_supernode(const supernode * supernode)147*0bfacb9bSmrg   static function_point after_supernode (const supernode *supernode)
148*0bfacb9bSmrg   {
149*0bfacb9bSmrg     return function_point (supernode, NULL, 0, PK_AFTER_SUPERNODE);
150*0bfacb9bSmrg   }
151*0bfacb9bSmrg 
152*0bfacb9bSmrg   /* Support for hash_map.  */
153*0bfacb9bSmrg 
empty()154*0bfacb9bSmrg   static function_point empty ()
155*0bfacb9bSmrg   {
156*0bfacb9bSmrg     return function_point (NULL, NULL, 0, PK_EMPTY);
157*0bfacb9bSmrg   }
deleted()158*0bfacb9bSmrg   static function_point deleted ()
159*0bfacb9bSmrg   {
160*0bfacb9bSmrg     return function_point (NULL, NULL, 0, PK_DELETED);
161*0bfacb9bSmrg   }
162*0bfacb9bSmrg 
163*0bfacb9bSmrg   static int cmp_within_supernode_1 (const function_point &point_a,
164*0bfacb9bSmrg 				     const function_point &point_b);
165*0bfacb9bSmrg   static int cmp_within_supernode (const function_point &point_a,
166*0bfacb9bSmrg 				   const function_point &point_b);
167*0bfacb9bSmrg 
168*0bfacb9bSmrg  private:
169*0bfacb9bSmrg   const supernode *m_supernode;
170*0bfacb9bSmrg 
171*0bfacb9bSmrg   /* For PK_BEFORE_SUPERNODE, and only for CFG edges.  */
172*0bfacb9bSmrg   const superedge *m_from_edge;
173*0bfacb9bSmrg 
174*0bfacb9bSmrg   /* Only for PK_BEFORE_STMT.  */
175*0bfacb9bSmrg   unsigned m_stmt_idx;
176*0bfacb9bSmrg 
177*0bfacb9bSmrg   enum point_kind m_kind;
178*0bfacb9bSmrg };
179*0bfacb9bSmrg 
180*0bfacb9bSmrg /* A class for representing a location within the program, including
181*0bfacb9bSmrg    interprocedural information.
182*0bfacb9bSmrg 
183*0bfacb9bSmrg    This represents a fine-grained location within the supergraph (or
184*0bfacb9bSmrg    within one of its nodes), along with a call string giving the
185*0bfacb9bSmrg    interprocedural context.  */
186*0bfacb9bSmrg 
187*0bfacb9bSmrg class program_point
188*0bfacb9bSmrg {
189*0bfacb9bSmrg public:
program_point(const function_point & fn_point,const call_string & call_string)190*0bfacb9bSmrg   program_point (const function_point &fn_point,
191*0bfacb9bSmrg 		 const call_string &call_string)
192*0bfacb9bSmrg   : m_function_point (fn_point),
193*0bfacb9bSmrg     m_call_string (call_string)
194*0bfacb9bSmrg   {
195*0bfacb9bSmrg   }
196*0bfacb9bSmrg 
197*0bfacb9bSmrg   void print (pretty_printer *pp, const format &f) const;
198*0bfacb9bSmrg   void print_source_line (pretty_printer *pp) const;
199*0bfacb9bSmrg   void dump () const;
200*0bfacb9bSmrg 
201*0bfacb9bSmrg   hashval_t hash () const;
202*0bfacb9bSmrg   bool operator== (const program_point &other) const
203*0bfacb9bSmrg   {
204*0bfacb9bSmrg     return (m_function_point == other.m_function_point
205*0bfacb9bSmrg 	    && m_call_string == other.m_call_string);
206*0bfacb9bSmrg   }
207*0bfacb9bSmrg 
208*0bfacb9bSmrg   /* Accessors.  */
209*0bfacb9bSmrg 
get_function_point()210*0bfacb9bSmrg   const function_point &get_function_point () const { return m_function_point; }
get_call_string()211*0bfacb9bSmrg   const call_string &get_call_string () const { return m_call_string; }
212*0bfacb9bSmrg 
get_supernode()213*0bfacb9bSmrg   const supernode *get_supernode () const
214*0bfacb9bSmrg   {
215*0bfacb9bSmrg     return m_function_point.get_supernode ();
216*0bfacb9bSmrg   }
get_function()217*0bfacb9bSmrg   function *get_function () const
218*0bfacb9bSmrg   {
219*0bfacb9bSmrg     return m_function_point.get_function ();
220*0bfacb9bSmrg   }
221*0bfacb9bSmrg   function *get_function_at_depth (unsigned depth) const;
get_fndecl()222*0bfacb9bSmrg   tree get_fndecl () const
223*0bfacb9bSmrg   {
224*0bfacb9bSmrg     gcc_assert (get_kind () != PK_ORIGIN);
225*0bfacb9bSmrg     return get_function ()->decl;
226*0bfacb9bSmrg   }
get_stmt()227*0bfacb9bSmrg   const gimple *get_stmt () const
228*0bfacb9bSmrg   {
229*0bfacb9bSmrg     return m_function_point.get_stmt ();
230*0bfacb9bSmrg   }
get_location()231*0bfacb9bSmrg   location_t get_location () const
232*0bfacb9bSmrg   {
233*0bfacb9bSmrg     return m_function_point.get_location ();
234*0bfacb9bSmrg   }
get_kind()235*0bfacb9bSmrg   enum point_kind get_kind () const
236*0bfacb9bSmrg   {
237*0bfacb9bSmrg     return m_function_point.get_kind ();
238*0bfacb9bSmrg   }
get_from_edge()239*0bfacb9bSmrg   const superedge *get_from_edge () const
240*0bfacb9bSmrg   {
241*0bfacb9bSmrg     return m_function_point.get_from_edge ();
242*0bfacb9bSmrg   }
get_stmt_idx()243*0bfacb9bSmrg   unsigned get_stmt_idx () const
244*0bfacb9bSmrg   {
245*0bfacb9bSmrg     return m_function_point.get_stmt_idx ();
246*0bfacb9bSmrg   }
247*0bfacb9bSmrg 
248*0bfacb9bSmrg   /* Get the number of frames we expect at this program point.
249*0bfacb9bSmrg      This will be one more than the length of the call_string
250*0bfacb9bSmrg      (which stores the parent callsites), apart from the origin
251*0bfacb9bSmrg      node, which doesn't have any frames.  */
get_stack_depth()252*0bfacb9bSmrg   int get_stack_depth () const
253*0bfacb9bSmrg   {
254*0bfacb9bSmrg     if (get_kind () == PK_ORIGIN)
255*0bfacb9bSmrg       return 0;
256*0bfacb9bSmrg     return m_call_string.length () + 1;
257*0bfacb9bSmrg   }
258*0bfacb9bSmrg 
259*0bfacb9bSmrg   /* Factory functions for making various kinds of program_point.  */
260*0bfacb9bSmrg 
from_function_entry(const supergraph & sg,function * fun)261*0bfacb9bSmrg   static program_point from_function_entry (const supergraph &sg,
262*0bfacb9bSmrg 					    function *fun)
263*0bfacb9bSmrg   {
264*0bfacb9bSmrg     return program_point (function_point::from_function_entry (sg, fun),
265*0bfacb9bSmrg 			  call_string ());
266*0bfacb9bSmrg   }
267*0bfacb9bSmrg 
before_supernode(const supernode * supernode,const superedge * from_edge,const call_string & call_string)268*0bfacb9bSmrg   static program_point before_supernode (const supernode *supernode,
269*0bfacb9bSmrg 					 const superedge *from_edge,
270*0bfacb9bSmrg 					 const call_string &call_string)
271*0bfacb9bSmrg   {
272*0bfacb9bSmrg     return program_point (function_point::before_supernode (supernode,
273*0bfacb9bSmrg 							    from_edge),
274*0bfacb9bSmrg 			  call_string);
275*0bfacb9bSmrg   }
276*0bfacb9bSmrg 
before_stmt(const supernode * supernode,unsigned stmt_idx,const call_string & call_string)277*0bfacb9bSmrg   static program_point before_stmt (const supernode *supernode,
278*0bfacb9bSmrg 				    unsigned stmt_idx,
279*0bfacb9bSmrg 				    const call_string &call_string)
280*0bfacb9bSmrg   {
281*0bfacb9bSmrg     return program_point (function_point::before_stmt (supernode, stmt_idx),
282*0bfacb9bSmrg 			  call_string);
283*0bfacb9bSmrg   }
284*0bfacb9bSmrg 
after_supernode(const supernode * supernode,const call_string & call_string)285*0bfacb9bSmrg   static program_point after_supernode (const supernode *supernode,
286*0bfacb9bSmrg 					const call_string &call_string)
287*0bfacb9bSmrg   {
288*0bfacb9bSmrg     return program_point (function_point::after_supernode (supernode),
289*0bfacb9bSmrg 			  call_string);
290*0bfacb9bSmrg   }
291*0bfacb9bSmrg 
292*0bfacb9bSmrg   /* Support for hash_map.  */
293*0bfacb9bSmrg 
empty()294*0bfacb9bSmrg   static program_point empty ()
295*0bfacb9bSmrg   {
296*0bfacb9bSmrg     return program_point (function_point::empty (), call_string ());
297*0bfacb9bSmrg   }
deleted()298*0bfacb9bSmrg   static program_point deleted ()
299*0bfacb9bSmrg   {
300*0bfacb9bSmrg     return program_point (function_point::deleted (), call_string ());
301*0bfacb9bSmrg   }
302*0bfacb9bSmrg 
303*0bfacb9bSmrg   bool on_edge (exploded_graph &eg, const superedge *succ);
304*0bfacb9bSmrg 
305*0bfacb9bSmrg   void validate () const;
306*0bfacb9bSmrg 
307*0bfacb9bSmrg  private:
308*0bfacb9bSmrg   const function_point m_function_point;
309*0bfacb9bSmrg   call_string m_call_string;
310*0bfacb9bSmrg };
311*0bfacb9bSmrg 
312*0bfacb9bSmrg } // namespace ana
313*0bfacb9bSmrg 
314*0bfacb9bSmrg #endif /* GCC_ANALYZER_PROGRAM_POINT_H */
315