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