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