Branch data Line data Source code
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 : :
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 : : #include "pretty-print.h"
25 : : #include "analyzer/call-string.h"
26 : :
27 : : namespace ana {
28 : :
29 : : class exploded_graph;
30 : :
31 : : /* An enum for distinguishing the various kinds of program_point. */
32 : :
33 : : enum 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 : :
48 : : extern const char *point_kind_to_string (enum point_kind pk);
49 : :
50 : : class format
51 : : {
52 : : public:
53 : 5575 : format (bool newlines) : m_newlines (newlines) {}
54 : :
55 : 6832 : void spacer (pretty_printer *pp) const
56 : : {
57 : 6832 : if (m_newlines)
58 : 1516 : pp_newline (pp);
59 : : else
60 : 5316 : pp_space (pp);
61 : 6832 : }
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 : :
72 : : class function_point
73 : : {
74 : : public:
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 : 22729124 : bool operator== (const function_point &other) const
86 : : {
87 : 22729124 : return (m_supernode == other.m_supernode
88 : 5781573 : && m_from_edge == other.m_from_edge
89 : : && m_stmt_idx == other.m_stmt_idx
90 : 17823338 : && m_kind == other.m_kind);
91 : : }
92 : :
93 : : /* Accessors. */
94 : :
95 : 5526032 : 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 : 3638667 : enum point_kind get_kind () const { return m_kind; }
100 : 1128768 : const superedge *get_from_edge () const
101 : : {
102 : 1128768 : return m_from_edge;
103 : : }
104 : 763174 : unsigned get_stmt_idx () const
105 : : {
106 : 763174 : gcc_assert (m_kind == PK_BEFORE_STMT);
107 : 763174 : 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 : 792308 : static function_point before_stmt (const supernode *supernode,
121 : : unsigned stmt_idx)
122 : : {
123 : 724386 : return function_point (supernode, NULL, stmt_idx, PK_BEFORE_STMT);
124 : : }
125 : :
126 : 303704 : static function_point after_supernode (const supernode *supernode)
127 : : {
128 : 273212 : return function_point (supernode, NULL, 0, PK_AFTER_SUPERNODE);
129 : : }
130 : :
131 : : /* Support for hash_map. */
132 : :
133 : 2267246 : static function_point empty ()
134 : : {
135 : 2267246 : 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 : :
174 : : class program_point
175 : : {
176 : : public:
177 : 639373 : program_point (const function_point &fn_point,
178 : : const call_string &call_string)
179 : 639373 : : m_function_point (fn_point),
180 : 639373 : m_call_string (&call_string)
181 : : {
182 : : }
183 : :
184 : : void print (pretty_printer *pp, const format &f) const;
185 : : void dump () const;
186 : :
187 : : std::unique_ptr<json::object> to_json () const;
188 : :
189 : : hashval_t hash () const;
190 : 9774239 : bool operator== (const program_point &other) const
191 : : {
192 : 10567844 : return (m_function_point == other.m_function_point
193 : 613824 : && m_call_string == other.m_call_string);
194 : : }
195 : 35870 : bool operator!= (const program_point &other) const
196 : : {
197 : 35870 : return !(*this == other);
198 : : }
199 : :
200 : : /* Accessors. */
201 : :
202 : 256104 : const function_point &get_function_point () const { return m_function_point; }
203 : 2417450 : const call_string &get_call_string () const { return *m_call_string; }
204 : :
205 : 4499530 : const supernode *get_supernode () const
206 : : {
207 : 4912770 : return m_function_point.get_supernode ();
208 : : }
209 : 5852849 : function *get_function () const
210 : : {
211 : 4704789 : return m_function_point.get_function ();
212 : : }
213 : : function *get_function_at_depth (unsigned depth) const;
214 : 48367 : tree get_fndecl () const
215 : : {
216 : 0 : gcc_assert (get_kind () != PK_ORIGIN);
217 : 48367 : return get_function ()->decl;
218 : : }
219 : 759968 : const gimple *get_stmt () const
220 : : {
221 : 759968 : return m_function_point.get_stmt ();
222 : : }
223 : 7394 : location_t get_location () const
224 : : {
225 : 7284 : return m_function_point.get_location ();
226 : : }
227 : 2930221 : enum point_kind get_kind () const
228 : : {
229 : 2024683 : return m_function_point.get_kind ();
230 : : }
231 : 368379 : const superedge *get_from_edge () const
232 : : {
233 : 368379 : return m_function_point.get_from_edge ();
234 : : }
235 : 475227 : unsigned get_stmt_idx () const
236 : : {
237 : 475227 : 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 : 898861 : int get_stack_depth () const
245 : : {
246 : 895012 : if (get_kind () == PK_ORIGIN)
247 : : return 0;
248 : 1136046 : 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 : 145402 : static program_point before_supernode (const supernode *supernode,
258 : : const superedge *from_edge,
259 : : const call_string &call_string)
260 : : {
261 : 145402 : return program_point (function_point::before_supernode (supernode,
262 : : from_edge),
263 : 145402 : call_string);
264 : : }
265 : :
266 : 294737 : static program_point before_stmt (const supernode *supernode,
267 : : unsigned stmt_idx,
268 : : const call_string &call_string)
269 : : {
270 : 294737 : return program_point (function_point::before_stmt (supernode, stmt_idx),
271 : 294737 : call_string);
272 : : }
273 : :
274 : 186364 : static program_point after_supernode (const supernode *supernode,
275 : : const call_string &call_string)
276 : : {
277 : 186364 : return program_point (function_point::after_supernode (supernode),
278 : 186364 : 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 : 73969 : 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 */
|