]>
Commit | Line | Data |
---|---|---|
2a837de2 MS |
1 | /* Definitions of the pointer_query and related classes. |
2 | ||
3 | Copyright (C) 2020-2021 Free Software Foundation, Inc. | |
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 | ||
69 | /* Return the object to which REF refers. */ | |
9a27acc3 MS |
70 | tree get_ref (vec<access_ref> *, access_ref * = nullptr, int = 1, |
71 | ssa_name_limit_t * = nullptr, pointer_query * = nullptr) const; | |
2a837de2 MS |
72 | |
73 | /* Return true if OFFRNG is the constant zero. */ | |
74 | bool offset_zero () const | |
75 | { | |
76 | return offrng[0] == 0 && offrng[1] == 0; | |
77 | } | |
78 | ||
79 | /* Return true if OFFRNG is bounded to a subrange of offset values | |
80 | valid for the largest possible object. */ | |
81 | bool offset_bounded () const; | |
82 | ||
83 | /* Return the maximum amount of space remaining and if non-null, set | |
84 | argument to the minimum. */ | |
9a27acc3 | 85 | offset_int size_remaining (offset_int * = nullptr) const; |
2a837de2 MS |
86 | |
87 | /* Return true if the offset and object size are in range for SIZE. */ | |
88 | bool offset_in_range (const offset_int &) const; | |
89 | ||
90 | /* Return true if *THIS is an access to a declared object. */ | |
91 | bool ref_declared () const | |
92 | { | |
93 | return DECL_P (ref) && base0 && deref < 1; | |
94 | } | |
95 | ||
96 | /* Set the size range to the maximum. */ | |
97 | void set_max_size_range () | |
98 | { | |
99 | sizrng[0] = 0; | |
100 | sizrng[1] = wi::to_offset (max_object_size ()); | |
101 | } | |
102 | ||
103 | /* Add OFF to the offset range. */ | |
104 | void add_offset (const offset_int &off) | |
105 | { | |
106 | add_offset (off, off); | |
107 | } | |
108 | ||
109 | /* Add the range [MIN, MAX] to the offset range. */ | |
110 | void add_offset (const offset_int &, const offset_int &); | |
111 | ||
112 | /* Add the maximum representable offset to the offset range. */ | |
113 | void add_max_offset () | |
114 | { | |
115 | offset_int maxoff = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node)); | |
116 | add_offset (-maxoff - 1, maxoff); | |
117 | } | |
118 | ||
119 | /* Issue an informational message describing the target of an access | |
120 | with the given mode. */ | |
121 | void inform_access (access_mode) const; | |
122 | ||
123 | /* Reference to the accessed object(s). */ | |
124 | tree ref; | |
125 | ||
126 | /* Range of byte offsets into and sizes of the object(s). */ | |
127 | offset_int offrng[2]; | |
128 | offset_int sizrng[2]; | |
129 | /* The minimum and maximum offset computed. */ | |
130 | offset_int offmax[2]; | |
2a837de2 MS |
131 | |
132 | /* Used to fold integer expressions when called from front ends. */ | |
133 | tree (*eval)(tree); | |
134 | /* Positive when REF is dereferenced, negative when its address is | |
135 | taken. */ | |
136 | int deref; | |
137 | /* Set if trailing one-element arrays should be treated as flexible | |
138 | array members. */ | |
139 | bool trail1special; | |
140 | /* Set if valid offsets must start at zero (for declared and allocated | |
141 | objects but not for others referenced by pointers). */ | |
142 | bool base0; | |
143 | /* Set if REF refers to a function array parameter not declared | |
144 | static. */ | |
145 | bool parmarray; | |
146 | }; | |
147 | ||
148 | class range_query; | |
149 | ||
150 | /* Queries and caches compute_objsize results. */ | |
151 | class pointer_query | |
152 | { | |
153 | DISABLE_COPY_AND_ASSIGN (pointer_query); | |
154 | ||
155 | public: | |
156 | /* Type of the two-level cache object defined by clients of the class | |
157 | to have pointer SSA_NAMEs cached for speedy access. */ | |
158 | struct cache_type | |
159 | { | |
160 | /* 1-based indices into cache. */ | |
161 | vec<unsigned> indices; | |
162 | /* The cache itself. */ | |
163 | vec<access_ref> access_refs; | |
164 | }; | |
165 | ||
166 | /* Construct an object with the given Ranger instance and cache. */ | |
9a27acc3 | 167 | explicit pointer_query (range_query * = nullptr, cache_type * = nullptr); |
2a837de2 MS |
168 | |
169 | /* Retrieve the access_ref for a variable from cache if it's there. */ | |
170 | const access_ref* get_ref (tree, int = 1) const; | |
171 | ||
172 | /* Retrieve the access_ref for a variable from cache or compute it. */ | |
9a27acc3 | 173 | bool get_ref (tree, gimple *, access_ref*, int = 1); |
2a837de2 MS |
174 | |
175 | /* Add an access_ref for the SSA_NAME to the cache. */ | |
176 | void put_ref (tree, const access_ref&, int = 1); | |
177 | ||
178 | /* Flush the cache. */ | |
179 | void flush_cache (); | |
180 | ||
ece28da9 MS |
181 | /* Dump statistics and optionally cache contents to DUMP_FILE. */ |
182 | void dump (FILE *, bool = false); | |
183 | ||
2a837de2 MS |
184 | /* A Ranger instance. May be null to use global ranges. */ |
185 | range_query *rvals; | |
186 | /* Cache of SSA_NAMEs. May be null to disable caching. */ | |
187 | cache_type *var_cache; | |
188 | ||
189 | /* Cache performance counters. */ | |
190 | mutable unsigned hits; | |
191 | mutable unsigned misses; | |
192 | mutable unsigned failures; | |
193 | mutable unsigned depth; | |
194 | mutable unsigned max_depth; | |
195 | }; | |
196 | ||
197 | /* Describes a pair of references used in an access by built-in | |
198 | functions like memcpy. */ | |
199 | struct access_data | |
200 | { | |
81d6cdd3 MS |
201 | /* Set the access to at most MAXWRITE and MAXREAD bytes, and |
202 | at least 1 when MINWRITE or MINREAD, respectively, is set. */ | |
f9379fcb MS |
203 | access_data (range_query *, gimple *, access_mode, |
204 | tree = NULL_TREE, bool = false, | |
205 | tree = NULL_TREE, bool = false); | |
81d6cdd3 | 206 | |
2a837de2 MS |
207 | /* Set the access to at most MAXWRITE and MAXREAD bytes, and |
208 | at least 1 when MINWRITE or MINREAD, respectively, is set. */ | |
f9379fcb MS |
209 | access_data (range_query *, tree, access_mode, |
210 | tree = NULL_TREE, bool = false, | |
211 | tree = NULL_TREE, bool = false); | |
212 | ||
213 | /* Constructor helper. */ | |
214 | static void set_bound (offset_int[2], tree, bool, range_query *, gimple *); | |
2a837de2 | 215 | |
81d6cdd3 MS |
216 | /* Access statement. */ |
217 | gimple *stmt; | |
2a837de2 MS |
218 | /* Built-in function call. */ |
219 | tree call; | |
220 | /* Destination and source of the access. */ | |
221 | access_ref dst, src; | |
f9379fcb MS |
222 | |
223 | /* Range of the bound of the access: denotes that the access is at | |
224 | least XXX_BNDRNG[0] bytes but no more than XXX_BNDRNG[1]. For | |
225 | string functions the size of the actual access is further | |
226 | constrained by the length of the string. */ | |
227 | offset_int dst_bndrng[2]; | |
228 | offset_int src_bndrng[2]; | |
229 | ||
2a837de2 MS |
230 | /* Read-only for functions like memcmp or strlen, write-only |
231 | for memset, read-write for memcpy or strcat. */ | |
232 | access_mode mode; | |
233 | }; | |
234 | ||
b48d4e68 MS |
235 | enum size_range_flags |
236 | { | |
237 | /* Set to consider zero a valid range. */ | |
238 | SR_ALLOW_ZERO = 1, | |
239 | /* Set to use the largest subrange of a set of ranges as opposed | |
240 | to the smallest. */ | |
241 | SR_USE_LARGEST = 2 | |
242 | }; | |
243 | extern bool get_size_range (tree, tree[2], int = 0); | |
244 | extern bool get_size_range (range_query *, tree, gimple *, tree[2], int = 0); | |
245 | ||
2a837de2 | 246 | class range_query; |
9a27acc3 MS |
247 | extern tree gimple_call_alloc_size (gimple *, wide_int[2] = nullptr, |
248 | range_query * = nullptr); | |
249 | ||
250 | /* Compute the size of an object referenced by the first argument in | |
251 | a statement given by second argument, using Object Size Type given | |
252 | by third argument. Store result in an access_ref. */ | |
253 | extern tree compute_objsize (tree, gimple *, int, access_ref *, | |
254 | range_query * = nullptr); | |
255 | extern tree compute_objsize (tree, gimple *, int, access_ref *, | |
256 | pointer_query *); | |
257 | inline tree compute_objsize (tree ptr, int ostype, access_ref *pref) | |
258 | { | |
259 | return compute_objsize (ptr, nullptr, ostype, pref, (range_query *)nullptr); | |
260 | } | |
2a837de2 | 261 | |
2a837de2 | 262 | /* Legacy/transitional API. Should not be used in new code. */ |
9a27acc3 MS |
263 | extern tree compute_objsize (tree, int, tree * = nullptr, tree * = nullptr, |
264 | range_query * = nullptr); | |
2a837de2 | 265 | |
1ff4dbdd MS |
266 | /* Return the field at the constant offset. */ |
267 | extern tree field_at_offset (tree, tree, HOST_WIDE_INT, | |
268 | HOST_WIDE_INT * = nullptr, | |
269 | HOST_WIDE_INT * = nullptr); | |
270 | /* Return the array at the constant offset. */ | |
271 | extern tree array_elt_at_offset (tree, HOST_WIDE_INT, | |
272 | HOST_WIDE_INT * = nullptr, | |
273 | HOST_WIDE_INT * = nullptr); | |
274 | ||
ea9e0d6c MS |
275 | /* Helper to build an array type that can be printed. */ |
276 | extern tree build_printable_array_type (tree, unsigned HOST_WIDE_INT); | |
277 | ||
2a837de2 | 278 | #endif // GCC_POINTER_QUERY_H |