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