Line data Source code
1 : /* Handling of fnspec attribute specifiers
2 : Copyright (C) 2008-2026 Free Software Foundation, Inc.
3 : Contributed by Richard Guenther <rguenther@suse.de>
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify
8 : under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : GCC is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU 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 : /* Parse string of attribute "fn spec". This is an internal attribute
22 : describing side effects of a function as follows:
23 :
24 : character 0 specifies properties of return values as follows:
25 : '1'...'4' specifies number of argument function returns (as in memset)
26 : 'm' specifies that returned value is noalias (as in malloc)
27 : '.' specifies that nothing is known.
28 : character 1 specifies additional function properties
29 : ' ' specifies that nothing is known
30 : 'p' or 'P' specifies that function is pure except for described side
31 : effects.
32 : 'c' or 'C' specifies that function is const except for described side
33 : effects.
34 : The uppercase letter in addition specifies that function clobbers errno.
35 :
36 : character 2+2i specifies properties of argument number i as follows:
37 : 'x' or 'X' specifies that parameter is unused.
38 : 'r' or 'R' specifies that the memory pointed to by the parameter is only
39 : read and does not escape
40 : 'o' or 'O' specifies that the memory pointed to by the parameter is only
41 : written and does not escape
42 : 'w' or 'W' specifies that the memory pointed to by the parameter does not
43 : escape
44 : '1'....'9' specifies that the memory pointed to by the parameter is
45 : copied to memory pointed to by different parameter
46 : (as in memcpy).
47 : '.' specifies that nothing is known.
48 : The uppercase letter in addition specifies that the memory pointed to
49 : by the parameter is not dereferenced. For 'r' only read applies
50 : transitively to pointers read from the pointed-to memory.
51 :
52 : character 3+2i specifies additional properties of argument number i
53 : as follows:
54 : ' ' nothing is known
55 : 't' the size of value written/read corresponds to the size of
56 : of the pointed-to type of the argument type
57 : '1'...'9' specifies the size of value written/read is bound by the
58 : specified argument
59 : */
60 :
61 : #ifndef ATTR_FNSPEC_H
62 : #define ATTR_FNSPEC_H
63 :
64 : class attr_fnspec
65 : {
66 : private:
67 : /* fn spec attribute string. */
68 : const char *str;
69 : /* length of the fn spec string. */
70 : const unsigned len;
71 : /* Number of characters specifying return value. */
72 : const unsigned int return_desc_size = 2;
73 : /* Number of characters specifying size. */
74 : const unsigned int arg_desc_size = 2;
75 :
76 : /* Return start of specifier of arg i. */
77 971274823 : unsigned int arg_idx (int i) const
78 : {
79 391187573 : return return_desc_size + arg_desc_size * i;
80 : }
81 :
82 : public:
83 2740122 : attr_fnspec (const char *str, unsigned len)
84 2740122 : : str (str), len (len)
85 : {
86 2740122 : if (flag_checking)
87 2740122 : verify ();
88 : }
89 380485125 : attr_fnspec (const char *str)
90 380485125 : : str (str), len (strlen (str))
91 : {
92 380485125 : if (flag_checking)
93 380484104 : verify ();
94 380485125 : }
95 60451086 : attr_fnspec (const_tree identifier)
96 60451086 : : str (TREE_STRING_POINTER (identifier)),
97 60451086 : len (TREE_STRING_LENGTH (identifier))
98 : {
99 60451086 : if (flag_checking)
100 60451086 : verify ();
101 60451086 : }
102 : attr_fnspec ()
103 : : str (NULL), len (0)
104 : {
105 : }
106 :
107 : /* Return true if fn spec is known. */
108 : bool
109 355109990 : known_p () const
110 : {
111 355109990 : return len;
112 : }
113 :
114 : /* Return true if arg I is specified. */
115 : bool
116 685319566 : arg_specified_p (unsigned int i) const
117 : {
118 633474748 : return len >= arg_idx (i + 1);
119 : }
120 :
121 : /* True if the argument is not dereferenced recursively, thus only
122 : directly reachable memory is read or written. */
123 : bool
124 15594369 : arg_direct_p (unsigned int i) const
125 : {
126 15594369 : unsigned int idx = arg_idx (i);
127 15594369 : gcc_checking_assert (arg_specified_p (i));
128 15594369 : return str[idx] == 'R' || str[idx] == 'O'
129 15594369 : || str[idx] == 'W' || (str[idx] >= '1' && str[idx] <= '9');
130 : }
131 :
132 : /* True if argument is used. */
133 : bool
134 15723611 : arg_used_p (unsigned int i) const
135 : {
136 15723611 : unsigned int idx = arg_idx (i);
137 15723611 : gcc_checking_assert (arg_specified_p (i));
138 15723611 : return str[idx] != 'x' && str[idx] != 'X';
139 : }
140 :
141 : /* True if memory reached by the argument is readonly (not clobbered). */
142 : bool
143 15699786 : arg_readonly_p (unsigned int i) const
144 : {
145 15699786 : unsigned int idx = arg_idx (i);
146 15699786 : gcc_checking_assert (arg_specified_p (i));
147 15699786 : return str[idx] == 'r' || str[idx] == 'R' || (str[idx] >= '1' && str[idx] <= '9');
148 : }
149 :
150 : /* True if memory reached by the argument is read (directly or indirectly) */
151 : bool
152 8737830 : arg_maybe_read_p (unsigned int i) const
153 : {
154 8737830 : unsigned int idx = arg_idx (i);
155 8737830 : gcc_checking_assert (arg_specified_p (i));
156 8737830 : return str[idx] != 'o' && str[idx] != 'O'
157 8737830 : && str[idx] != 'x' && str[idx] != 'X';
158 : }
159 :
160 : /* True if memory reached by the argument is written.
161 : (directly or indirectly) */
162 : bool
163 34535628 : arg_maybe_written_p (unsigned int i) const
164 : {
165 34535628 : unsigned int idx = arg_idx (i);
166 34535628 : gcc_checking_assert (arg_specified_p (i));
167 34535628 : return str[idx] != 'r' && str[idx] != 'R'
168 34527610 : && (str[idx] < '1' || str[idx] > '9')
169 56925615 : && str[idx] != 'x' && str[idx] != 'X';
170 : }
171 :
172 : /* Return true if load of memory pointed to by argument I is bound
173 : by another argument. In this case set ARG. */
174 : bool
175 23809221 : arg_max_access_size_given_by_arg_p (unsigned int i, unsigned int *arg) const
176 : {
177 23809221 : unsigned int idx = arg_idx (i);
178 23809221 : gcc_checking_assert (arg_specified_p (i));
179 23809221 : if (str[idx + 1] >= '1' && str[idx + 1] <= '9')
180 : {
181 15890375 : *arg = str[idx + 1] - '1';
182 15890375 : return true;
183 : }
184 : else
185 : return false;
186 : }
187 :
188 : /* Return true if the pointed-to type of the argument correspond to the
189 : size of the memory acccess. */
190 : bool
191 7918846 : arg_access_size_given_by_type_p (unsigned int i) const
192 : {
193 7918846 : unsigned int idx = arg_idx (i);
194 7918846 : gcc_checking_assert (arg_specified_p (i));
195 7918846 : return str[idx + 1] == 't';
196 : }
197 :
198 : /* Return true if memory pointer to by argument is copied to a memory
199 : pointed to by a different argument (as in memcpy).
200 : In this case set ARG. */
201 : bool
202 0 : arg_copied_to_arg_p (unsigned int i, unsigned int *arg) const
203 : {
204 0 : unsigned int idx = arg_idx (i);
205 0 : gcc_checking_assert (arg_specified_p (i));
206 0 : if (str[idx] < '1' || str[idx] > '9')
207 : return false;
208 0 : *arg = str[idx] - '1';
209 0 : return true;
210 : }
211 :
212 :
213 : /* True if the argument does not escape. */
214 : bool
215 15594369 : arg_noescape_p (unsigned int i) const
216 : {
217 15594369 : unsigned int idx = arg_idx (i);
218 15594369 : gcc_checking_assert (arg_specified_p (i));
219 15594369 : return str[idx] == 'w' || str[idx] == 'W'
220 : || str[idx] == 'r' || str[idx] == 'R'
221 15594369 : || str[idx] == 'o' || str[idx] == 'O';
222 : }
223 :
224 : /* Return true if function returns value of its parameter. If ARG_NO is
225 : non-NULL return initialize it to the argument returned. */
226 : bool
227 81527018 : returns_arg (unsigned int *arg_no) const
228 : {
229 81527018 : if (str[0] >= '1' && str[0] <= '4')
230 : {
231 2719053 : if (arg_no)
232 2719053 : *arg_no = str[0] - '1';
233 2719053 : return true;
234 : }
235 : return false;
236 : }
237 :
238 : /* Nonzero if the return value does not alias with anything. Functions
239 : with the malloc attribute have this set on their return value. */
240 : bool
241 : returns_noalias_p () const
242 : {
243 : return str[0] == 'm';
244 : }
245 :
246 : /* Return true if all memory read by the function is specified by fnspec. */
247 : bool
248 20424704 : global_memory_read_p () const
249 : {
250 20424704 : return str[1] != 'c' && str[1] != 'C';
251 : }
252 :
253 : /* Return true if all memory written by the function
254 : is specified by fnspec. */
255 : bool
256 72158586 : global_memory_written_p () const
257 : {
258 72158586 : return str[1] != 'c' && str[1] != 'C' && str[1] != 'p' && str[1] != 'P';
259 : }
260 :
261 : bool
262 26072440 : errno_maybe_written_p () const
263 : {
264 26072440 : return str[1] == 'C' || str[1] == 'P';
265 : }
266 :
267 : /* Return EAF flags for arg I. */
268 : int
269 29839427 : arg_eaf_flags (unsigned int i) const
270 : {
271 29839427 : int flags = 0;
272 :
273 29839427 : if (!arg_specified_p (i))
274 : ;
275 15723611 : else if (!arg_used_p (i))
276 : flags = EAF_UNUSED;
277 : else
278 : {
279 15594369 : if (arg_direct_p (i))
280 7797694 : flags |= EAF_NO_INDIRECT_READ | EAF_NO_INDIRECT_ESCAPE
281 : | EAF_NOT_RETURNED_INDIRECTLY | EAF_NO_INDIRECT_CLOBBER;
282 15594369 : if (arg_noescape_p (i))
283 12237506 : flags |= EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE;
284 15594369 : if (arg_readonly_p (i))
285 7288840 : flags |= EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER;
286 : }
287 29839427 : return flags;
288 : }
289 :
290 : /* Check validity of the string. */
291 : void verify ();
292 :
293 : /* Return the fnspec string. */
294 : const char *
295 : get_str () const
296 : {
297 : return str;
298 : }
299 : };
300 :
301 : extern attr_fnspec gimple_call_fnspec (const gcall *stmt);
302 : extern attr_fnspec builtin_fnspec (tree);
303 :
304 : #endif /* ATTR_FNSPEC_H */
|