]>
Commit | Line | Data |
---|---|---|
2a837de2 MS |
1 | /* Definitions of the pointer_query and related classes. |
2 | ||
6441eb6d | 3 | Copyright (C) 2020-2025 Free Software Foundation, Inc. |
2a837de2 MS |
4 | |
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 3, or (at your option) any later | |
10 | version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | 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_POINTER_QUERY_H | |
22 | #define GCC_POINTER_QUERY_H | |
23 | ||
24 | /* Describes recursion limits used by functions that follow use-def | |
25 | chains of SSA_NAMEs. */ | |
26 | ||
27 | class ssa_name_limit_t | |
28 | { | |
29 | bitmap visited; /* Bitmap of visited SSA_NAMEs. */ | |
30 | unsigned ssa_def_max; /* Longest chain of SSA_NAMEs to follow. */ | |
31 | ||
32 | /* Not copyable or assignable. */ | |
33 | DISABLE_COPY_AND_ASSIGN (ssa_name_limit_t); | |
34 | ||
35 | public: | |
36 | ||
37 | ssa_name_limit_t () | |
38 | : visited (), | |
39 | ssa_def_max (param_ssa_name_def_chain_limit) { } | |
40 | ||
41 | /* Set a bit for the PHI in VISITED and return true if it wasn't | |
42 | already set. */ | |
43 | bool visit_phi (tree); | |
44 | /* Clear a bit for the PHI in VISITED. */ | |
45 | void leave_phi (tree); | |
46 | /* Return false if the SSA_NAME chain length counter has reached | |
47 | the limit, otherwise increment the counter and return true. */ | |
48 | bool next (); | |
49 | ||
50 | /* If the SSA_NAME has already been "seen" return a positive value. | |
51 | Otherwise add it to VISITED. If the SSA_NAME limit has been | |
52 | reached, return a negative value. Otherwise return zero. */ | |
53 | int next_phi (tree); | |
54 | ||
55 | ~ssa_name_limit_t (); | |
56 | }; | |
57 | ||
58 | class pointer_query; | |
59 | ||
60 | /* Describes a reference to an object used in an access. */ | |
61 | struct access_ref | |
62 | { | |
9a27acc3 | 63 | /* Set the bounds of the reference. */ |
f9379fcb | 64 | access_ref (); |
2a837de2 MS |
65 | |
66 | /* Return the PHI node REF refers to or null if it doesn't. */ | |
67 | gphi *phi () const; | |
68 | ||
10d185b9 | 69 | /* Merge the result for a pointer with *THIS. */ |
58ec0964 | 70 | void merge_ref (vec<access_ref> *all_refs, tree, gimple *, int, bool, |
10d185b9 MS |
71 | ssa_name_limit_t &, pointer_query &); |
72 | ||
2a837de2 | 73 | /* Return the object to which REF refers. */ |
9a27acc3 MS |
74 | tree get_ref (vec<access_ref> *, access_ref * = nullptr, int = 1, |
75 | ssa_name_limit_t * = nullptr, pointer_query * = nullptr) const; | |
2a837de2 MS |
76 | |
77 | /* Return true if OFFRNG is the constant zero. */ | |
78 | bool offset_zero () const | |
79 | { | |
80 | return offrng[0] == 0 && offrng[1] == 0; | |
81 | } | |
82 | ||
83 | /* Return true if OFFRNG is bounded to a subrange of offset values | |
84 | valid for the largest possible object. */ | |
85 | bool offset_bounded () const; | |
86 | ||
87 | /* Return the maximum amount of space remaining and if non-null, set | |
88 | argument to the minimum. */ | |
9a27acc3 | 89 | offset_int size_remaining (offset_int * = nullptr) const; |
2a837de2 | 90 | |
926f5059 | 91 | /* Return true if the offset and object size are in range for SIZE. */ |
2a837de2 MS |
92 | bool offset_in_range (const offset_int &) const; |
93 | ||
94 | /* Return true if *THIS is an access to a declared object. */ | |
95 | bool ref_declared () const | |
96 | { | |
97 | return DECL_P (ref) && base0 && deref < 1; | |
98 | } | |
99 | ||
100 | /* Set the size range to the maximum. */ | |
101 | void set_max_size_range () | |
102 | { | |
103 | sizrng[0] = 0; | |
104 | sizrng[1] = wi::to_offset (max_object_size ()); | |
105 | } | |
106 | ||
107 | /* Add OFF to the offset range. */ | |
108 | void add_offset (const offset_int &off) | |
109 | { | |
110 | add_offset (off, off); | |
111 | } | |
112 | ||
113 | /* Add the range [MIN, MAX] to the offset range. */ | |
114 | void add_offset (const offset_int &, const offset_int &); | |
115 | ||
116 | /* Add the maximum representable offset to the offset range. */ | |
117 | void add_max_offset () | |
118 | { | |
119 | offset_int maxoff = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node)); | |
120 | add_offset (-maxoff - 1, maxoff); | |
121 | } | |
122 | ||
123 | /* Issue an informational message describing the target of an access | |
124 | with the given mode. */ | |
1334d889 | 125 | void inform_access (access_mode, int = 1) const; |
2a837de2 | 126 | |
6dfb1059 MS |
127 | /* Dump *THIS to a file. */ |
128 | void dump (FILE *) const; | |
129 | ||
2a837de2 MS |
130 | /* Reference to the accessed object(s). */ |
131 | tree ref; | |
132 | ||
133 | /* Range of byte offsets into and sizes of the object(s). */ | |
134 | offset_int offrng[2]; | |
135 | offset_int sizrng[2]; | |
136 | /* The minimum and maximum offset computed. */ | |
137 | offset_int offmax[2]; | |
2a837de2 MS |
138 | |
139 | /* Used to fold integer expressions when called from front ends. */ | |
140 | tree (*eval)(tree); | |
141 | /* Positive when REF is dereferenced, negative when its address is | |
142 | taken. */ | |
143 | int deref; | |
926f5059 RB |
144 | /* The following indicates if heuristics interpreted 'ref' is interpreted |
145 | as (offsetted) nullptr. */ | |
146 | bool ref_nullptr_p; | |
2a837de2 MS |
147 | /* Set if trailing one-element arrays should be treated as flexible |
148 | array members. */ | |
149 | bool trail1special; | |
150 | /* Set if valid offsets must start at zero (for declared and allocated | |
151 | objects but not for others referenced by pointers). */ | |
152 | bool base0; | |
153 | /* Set if REF refers to a function array parameter not declared | |
154 | static. */ | |
155 | bool parmarray; | |
156 | }; | |
157 | ||
158 | class range_query; | |
159 | ||
160 | /* Queries and caches compute_objsize results. */ | |
161 | class pointer_query | |
162 | { | |
163 | DISABLE_COPY_AND_ASSIGN (pointer_query); | |
164 | ||
2a837de2 MS |
165 | /* Type of the two-level cache object defined by clients of the class |
166 | to have pointer SSA_NAMEs cached for speedy access. */ | |
167 | struct cache_type | |
168 | { | |
169 | /* 1-based indices into cache. */ | |
e78d98f7 | 170 | auto_vec<unsigned> indices; |
2a837de2 | 171 | /* The cache itself. */ |
e78d98f7 | 172 | auto_vec<access_ref> access_refs; |
2a837de2 MS |
173 | }; |
174 | ||
68e9b7b6 MS |
175 | public: |
176 | /* Construct an object with the given Ranger instance. */ | |
177 | explicit pointer_query (range_query * = nullptr); | |
2a837de2 MS |
178 | |
179 | /* Retrieve the access_ref for a variable from cache if it's there. */ | |
180 | const access_ref* get_ref (tree, int = 1) const; | |
181 | ||
182 | /* Retrieve the access_ref for a variable from cache or compute it. */ | |
9a27acc3 | 183 | bool get_ref (tree, gimple *, access_ref*, int = 1); |
2a837de2 MS |
184 | |
185 | /* Add an access_ref for the SSA_NAME to the cache. */ | |
186 | void put_ref (tree, const access_ref&, int = 1); | |
187 | ||
188 | /* Flush the cache. */ | |
189 | void flush_cache (); | |
190 | ||
ece28da9 MS |
191 | /* Dump statistics and optionally cache contents to DUMP_FILE. */ |
192 | void dump (FILE *, bool = false); | |
193 | ||
2a837de2 MS |
194 | /* A Ranger instance. May be null to use global ranges. */ |
195 | range_query *rvals; | |
2a837de2 MS |
196 | |
197 | /* Cache performance counters. */ | |
198 | mutable unsigned hits; | |
199 | mutable unsigned misses; | |
200 | mutable unsigned failures; | |
201 | mutable unsigned depth; | |
202 | mutable unsigned max_depth; | |
68e9b7b6 MS |
203 | |
204 | private: | |
205 | /* Cache of SSA_NAMEs. May be null to disable caching. */ | |
206 | cache_type var_cache; | |
2a837de2 MS |
207 | }; |
208 | ||
209 | /* Describes a pair of references used in an access by built-in | |
210 | functions like memcpy. */ | |
211 | struct access_data | |
212 | { | |
81d6cdd3 MS |
213 | /* Set the access to at most MAXWRITE and MAXREAD bytes, and |
214 | at least 1 when MINWRITE or MINREAD, respectively, is set. */ | |
f9379fcb MS |
215 | access_data (range_query *, gimple *, access_mode, |
216 | tree = NULL_TREE, bool = false, | |
217 | tree = NULL_TREE, bool = false); | |
81d6cdd3 | 218 | |
2a837de2 MS |
219 | /* Set the access to at most MAXWRITE and MAXREAD bytes, and |
220 | at least 1 when MINWRITE or MINREAD, respectively, is set. */ | |
f9379fcb MS |
221 | access_data (range_query *, tree, access_mode, |
222 | tree = NULL_TREE, bool = false, | |
223 | tree = NULL_TREE, bool = false); | |
224 | ||
225 | /* Constructor helper. */ | |
226 | static void set_bound (offset_int[2], tree, bool, range_query *, gimple *); | |
2a837de2 | 227 | |
81d6cdd3 MS |
228 | /* Access statement. */ |
229 | gimple *stmt; | |
2a837de2 MS |
230 | /* Built-in function call. */ |
231 | tree call; | |
232 | /* Destination and source of the access. */ | |
233 | access_ref dst, src; | |
f9379fcb MS |
234 | |
235 | /* Range of the bound of the access: denotes that the access is at | |
236 | least XXX_BNDRNG[0] bytes but no more than XXX_BNDRNG[1]. For | |
237 | string functions the size of the actual access is further | |
238 | constrained by the length of the string. */ | |
239 | offset_int dst_bndrng[2]; | |
240 | offset_int src_bndrng[2]; | |
241 | ||
2a837de2 MS |
242 | /* Read-only for functions like memcmp or strlen, write-only |
243 | for memset, read-write for memcpy or strcat. */ | |
244 | access_mode mode; | |
1334d889 MS |
245 | /* The object size type. */ |
246 | int ostype; | |
2a837de2 MS |
247 | }; |
248 | ||
b48d4e68 MS |
249 | enum size_range_flags |
250 | { | |
251 | /* Set to consider zero a valid range. */ | |
252 | SR_ALLOW_ZERO = 1, | |
253 | /* Set to use the largest subrange of a set of ranges as opposed | |
254 | to the smallest. */ | |
255 | SR_USE_LARGEST = 2 | |
256 | }; | |
257 | extern bool get_size_range (tree, tree[2], int = 0); | |
258 | extern bool get_size_range (range_query *, tree, gimple *, tree[2], int = 0); | |
259 | ||
2a837de2 | 260 | class range_query; |
9a27acc3 MS |
261 | extern tree gimple_call_alloc_size (gimple *, wide_int[2] = nullptr, |
262 | range_query * = nullptr); | |
263 | ||
264 | /* Compute the size of an object referenced by the first argument in | |
265 | a statement given by second argument, using Object Size Type given | |
266 | by third argument. Store result in an access_ref. */ | |
267 | extern tree compute_objsize (tree, gimple *, int, access_ref *, | |
268 | range_query * = nullptr); | |
269 | extern tree compute_objsize (tree, gimple *, int, access_ref *, | |
270 | pointer_query *); | |
271 | inline tree compute_objsize (tree ptr, int ostype, access_ref *pref) | |
272 | { | |
273 | return compute_objsize (ptr, nullptr, ostype, pref, (range_query *)nullptr); | |
274 | } | |
2a837de2 | 275 | |
2a837de2 | 276 | /* Legacy/transitional API. Should not be used in new code. */ |
9354a7d7 MS |
277 | extern tree compute_objsize (tree, gimple *, int, tree * = nullptr, |
278 | tree * = nullptr, range_query * = nullptr); | |
279 | inline tree compute_objsize (tree ptr, int ostype, tree *pdecl = nullptr, | |
280 | tree *poff = nullptr, range_query *rvals = nullptr) | |
281 | { | |
282 | return compute_objsize (ptr, nullptr, ostype, pdecl, poff, rvals); | |
283 | } | |
2a837de2 | 284 | |
1ff4dbdd MS |
285 | /* Return the field at the constant offset. */ |
286 | extern tree field_at_offset (tree, tree, HOST_WIDE_INT, | |
287 | HOST_WIDE_INT * = nullptr, | |
288 | HOST_WIDE_INT * = nullptr); | |
289 | /* Return the array at the constant offset. */ | |
290 | extern tree array_elt_at_offset (tree, HOST_WIDE_INT, | |
291 | HOST_WIDE_INT * = nullptr, | |
292 | HOST_WIDE_INT * = nullptr); | |
293 | ||
ea9e0d6c MS |
294 | /* Helper to build an array type that can be printed. */ |
295 | extern tree build_printable_array_type (tree, unsigned HOST_WIDE_INT); | |
296 | ||
2a837de2 | 297 | #endif // GCC_POINTER_QUERY_H |