Branch data Line data Source code
1 : : /* Handling of fnspec attribute specifiers
2 : : Copyright (C) 2008-2025 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 : 855978915 : unsigned int arg_idx (int i)
78 : : {
79 : 343704928 : return return_desc_size + arg_desc_size * i;
80 : : }
81 : :
82 : : public:
83 : 2586480 : attr_fnspec (const char *str, unsigned len)
84 : 2586480 : : str (str), len (len)
85 : : {
86 : 2586480 : if (flag_checking)
87 : 2586480 : verify ();
88 : : }
89 : 340957321 : attr_fnspec (const char *str)
90 : 340957321 : : str (str), len (strlen (str))
91 : : {
92 : 340957321 : if (flag_checking)
93 : 340956385 : verify ();
94 : 340957321 : }
95 : 54595849 : attr_fnspec (const_tree identifier)
96 : 54595849 : : str (TREE_STRING_POINTER (identifier)),
97 : 54595849 : len (TREE_STRING_LENGTH (identifier))
98 : : {
99 : 54595849 : if (flag_checking)
100 : 54595849 : verify ();
101 : 54595849 : }
102 : : attr_fnspec ()
103 : : : str (NULL), len (0)
104 : : {
105 : : }
106 : :
107 : : /* Return true if fn spec is known. */
108 : : bool
109 : 315874631 : known_p ()
110 : : {
111 : 315874631 : return len;
112 : : }
113 : :
114 : : /* Return true if arg I is specified. */
115 : : bool
116 : 602955551 : arg_specified_p (unsigned int i)
117 : : {
118 : 557803235 : 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 : 13264153 : arg_direct_p (unsigned int i)
125 : : {
126 : 13264153 : unsigned int idx = arg_idx (i);
127 : 13264153 : gcc_checking_assert (arg_specified_p (i));
128 : 13264153 : return str[idx] == 'R' || str[idx] == 'O'
129 : 13264153 : || str[idx] == 'W' || (str[idx] >= '1' && str[idx] <= '9');
130 : : }
131 : :
132 : : /* True if argument is used. */
133 : : bool
134 : 13376937 : arg_used_p (unsigned int i)
135 : : {
136 : 13376937 : unsigned int idx = arg_idx (i);
137 : 13376937 : gcc_checking_assert (arg_specified_p (i));
138 : 13376937 : return str[idx] != 'x' && str[idx] != 'X';
139 : : }
140 : :
141 : : /* True if memory reached by the argument is readonly (not clobbered). */
142 : : bool
143 : 13361801 : arg_readonly_p (unsigned int i)
144 : : {
145 : 13361801 : unsigned int idx = arg_idx (i);
146 : 13361801 : gcc_checking_assert (arg_specified_p (i));
147 : 13361801 : 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 : 7213848 : arg_maybe_read_p (unsigned int i)
153 : : {
154 : 7213848 : unsigned int idx = arg_idx (i);
155 : 7213848 : gcc_checking_assert (arg_specified_p (i));
156 : 7213848 : return str[idx] != 'o' && str[idx] != 'O'
157 : 7213848 : && 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 : 30574164 : arg_maybe_written_p (unsigned int i)
164 : : {
165 : 30574164 : unsigned int idx = arg_idx (i);
166 : 30574164 : gcc_checking_assert (arg_specified_p (i));
167 : 30574164 : return str[idx] != 'r' && str[idx] != 'R'
168 : 30567061 : && (str[idx] < '1' || str[idx] > '9')
169 : 50216450 : && 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 : 20666326 : arg_max_access_size_given_by_arg_p (unsigned int i, unsigned int *arg)
176 : : {
177 : 20666326 : unsigned int idx = arg_idx (i);
178 : 20666326 : gcc_checking_assert (arg_specified_p (i));
179 : 20666326 : if (str[idx + 1] >= '1' && str[idx + 1] <= '9')
180 : : {
181 : 13921804 : *arg = str[idx + 1] - '1';
182 : 13921804 : 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 : 6744522 : arg_access_size_given_by_type_p (unsigned int i)
192 : : {
193 : 6744522 : unsigned int idx = arg_idx (i);
194 : 6744522 : gcc_checking_assert (arg_specified_p (i));
195 : 6744522 : 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)
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 : 13264153 : arg_noescape_p (unsigned int i)
216 : : {
217 : 13264153 : unsigned int idx = arg_idx (i);
218 : 13264153 : gcc_checking_assert (arg_specified_p (i));
219 : 13264153 : return str[idx] == 'w' || str[idx] == 'W'
220 : : || str[idx] == 'r' || str[idx] == 'R'
221 : 13264153 : || 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 : 75623965 : returns_arg (unsigned int *arg_no)
228 : : {
229 : 75623965 : if (str[0] >= '1' && str[0] <= '4')
230 : : {
231 : 2232418 : if (arg_no)
232 : 2232418 : *arg_no = str[0] - '1';
233 : 2232418 : 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 ()
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 : 17967517 : global_memory_read_p ()
249 : : {
250 : 17967517 : 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 : 63792916 : global_memory_written_p ()
257 : : {
258 : 63792916 : return str[1] != 'c' && str[1] != 'C' && str[1] != 'p' && str[1] != 'P';
259 : : }
260 : :
261 : : bool
262 : 22580067 : errno_maybe_written_p ()
263 : : {
264 : 22580067 : return str[1] == 'C' || str[1] == 'P';
265 : : }
266 : :
267 : : /* Return EAF flags for arg I. */
268 : : int
269 : 25757223 : arg_eaf_flags (unsigned int i)
270 : : {
271 : 25757223 : int flags = 0;
272 : :
273 : 25757223 : if (!arg_specified_p (i))
274 : : ;
275 : 13376937 : else if (!arg_used_p (i))
276 : : flags = EAF_UNUSED;
277 : : else
278 : : {
279 : 13264153 : if (arg_direct_p (i))
280 : 6375521 : flags |= EAF_NO_INDIRECT_READ | EAF_NO_INDIRECT_ESCAPE
281 : : | EAF_NOT_RETURNED_INDIRECTLY | EAF_NO_INDIRECT_CLOBBER;
282 : 13264153 : if (arg_noescape_p (i))
283 : 10536524 : flags |= EAF_NO_DIRECT_ESCAPE | EAF_NO_INDIRECT_ESCAPE;
284 : 13264153 : if (arg_readonly_p (i))
285 : 6097367 : flags |= EAF_NO_DIRECT_CLOBBER | EAF_NO_INDIRECT_CLOBBER;
286 : : }
287 : 25757223 : 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 ()
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 */
|