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

source code of gcc/analyzer/program-point.h