Branch data Line data Source code
1 : : /* __builtin_object_size (ptr, object_size_type) computation
2 : : Copyright (C) 2004-2024 Free Software Foundation, Inc.
3 : : Contributed by Jakub Jelinek <jakub@redhat.com>
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify
8 : : it under the terms of the GNU General Public License as published by
9 : : the Free Software Foundation; either version 3, or (at your option)
10 : : 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 : : #include "config.h"
22 : : #include "system.h"
23 : : #include "coretypes.h"
24 : : #include "backend.h"
25 : : #include "tree.h"
26 : : #include "gimple.h"
27 : : #include "tree-pass.h"
28 : : #include "ssa.h"
29 : : #include "gimple-pretty-print.h"
30 : : #include "fold-const.h"
31 : : #include "tree-object-size.h"
32 : : #include "gimple-iterator.h"
33 : : #include "gimple-fold.h"
34 : : #include "tree-cfg.h"
35 : : #include "tree-dfa.h"
36 : : #include "stringpool.h"
37 : : #include "attribs.h"
38 : : #include "builtins.h"
39 : : #include "gimplify-me.h"
40 : :
41 : : struct object_size_info
42 : : {
43 : : int object_size_type;
44 : : unsigned char pass;
45 : : bool changed;
46 : : bitmap visited, reexamine;
47 : : unsigned int *depths;
48 : : unsigned int *stack, *tos;
49 : : };
50 : :
51 : : struct GTY(()) object_size
52 : : {
53 : : /* Estimate of bytes till the end of the object. */
54 : : tree size;
55 : : /* Estimate of the size of the whole object. */
56 : : tree wholesize;
57 : : };
58 : :
59 : : static tree compute_object_offset (tree, const_tree);
60 : : static bool addr_object_size (struct object_size_info *,
61 : : const_tree, int, tree *, tree *t = NULL);
62 : : static tree alloc_object_size (const gcall *, int);
63 : : static tree pass_through_call (const gcall *);
64 : : static void collect_object_sizes_for (struct object_size_info *, tree);
65 : : static void expr_object_size (struct object_size_info *, tree, tree);
66 : : static bool merge_object_sizes (struct object_size_info *, tree, tree);
67 : : static bool plus_stmt_object_size (struct object_size_info *, tree, gimple *);
68 : : static bool cond_expr_object_size (struct object_size_info *, tree, gimple *);
69 : : static void init_offset_limit (void);
70 : : static void check_for_plus_in_loops (struct object_size_info *, tree);
71 : : static void check_for_plus_in_loops_1 (struct object_size_info *, tree,
72 : : unsigned int);
73 : :
74 : : /* object_sizes[0] is upper bound for the object size and number of bytes till
75 : : the end of the object.
76 : : object_sizes[1] is upper bound for the object size and number of bytes till
77 : : the end of the subobject (innermost array or field with address taken).
78 : : object_sizes[2] is lower bound for the object size and number of bytes till
79 : : the end of the object and object_sizes[3] lower bound for subobject.
80 : :
81 : : For static object sizes, the object size and the bytes till the end of the
82 : : object are both INTEGER_CST. In the dynamic case, they are finally either a
83 : : gimple variable or an INTEGER_CST. */
84 : : static vec<object_size> object_sizes[OST_END];
85 : :
86 : : /* Bitmaps what object sizes have been computed already. */
87 : : static bitmap computed[OST_END];
88 : :
89 : : /* Maximum value of offset we consider to be addition. */
90 : : static unsigned HOST_WIDE_INT offset_limit;
91 : :
92 : : /* Tell the generic SSA updater what kind of update is needed after the pass
93 : : executes. */
94 : : static unsigned todo;
95 : :
96 : : /* Return true if VAL represents an initial size for OBJECT_SIZE_TYPE. */
97 : :
98 : : static inline bool
99 : 5442 : size_initval_p (tree val, int object_size_type)
100 : : {
101 : 5442 : return ((object_size_type & OST_MINIMUM)
102 : 5442 : ? integer_all_onesp (val) : integer_zerop (val));
103 : : }
104 : :
105 : : /* Return true if VAL represents an unknown size for OBJECT_SIZE_TYPE. */
106 : :
107 : : static inline bool
108 : 99206 : size_unknown_p (tree val, int object_size_type)
109 : : {
110 : 99206 : return ((object_size_type & OST_MINIMUM)
111 : 98488 : ? integer_zerop (val) : integer_all_onesp (val));
112 : : }
113 : :
114 : : /* Return true if VAL represents a valid size for OBJECT_SIZE_TYPE. */
115 : :
116 : : static inline bool
117 : 53775 : size_valid_p (tree val, int object_size_type)
118 : : {
119 : 52789 : return ((object_size_type & OST_DYNAMIC) || TREE_CODE (val) == INTEGER_CST);
120 : : }
121 : :
122 : : /* Return true if VAL is usable as an object size in the object_sizes
123 : : vectors. */
124 : :
125 : : static inline bool
126 : 10145 : size_usable_p (tree val)
127 : : {
128 : 9264 : return TREE_CODE (val) == SSA_NAME || TREE_CODE (val) == INTEGER_CST;
129 : : }
130 : :
131 : : /* Return a tree with initial value for OBJECT_SIZE_TYPE. */
132 : :
133 : : static inline tree
134 : 11516 : size_initval (int object_size_type)
135 : : {
136 : 11516 : return ((object_size_type & OST_MINIMUM)
137 : 11516 : ? TYPE_MAX_VALUE (sizetype) : size_zero_node);
138 : : }
139 : :
140 : : /* Return a tree with unknown value for OBJECT_SIZE_TYPE. */
141 : :
142 : : static inline tree
143 : 182280 : size_unknown (int object_size_type)
144 : : {
145 : 182280 : return ((object_size_type & OST_MINIMUM)
146 : 182280 : ? size_zero_node : TYPE_MAX_VALUE (sizetype));
147 : : }
148 : :
149 : : /* Grow object_sizes[OBJECT_SIZE_TYPE] to num_ssa_names. */
150 : :
151 : : static inline void
152 : 29638 : object_sizes_grow (int object_size_type)
153 : : {
154 : 68778 : if (num_ssa_names > object_sizes[object_size_type].length ())
155 : 22454 : object_sizes[object_size_type].safe_grow (num_ssa_names, true);
156 : 29638 : }
157 : :
158 : : /* Release object_sizes[OBJECT_SIZE_TYPE]. */
159 : :
160 : : static inline void
161 : 25707224 : object_sizes_release (int object_size_type)
162 : : {
163 : 25707224 : object_sizes[object_size_type].release ();
164 : : }
165 : :
166 : : /* Return true if object_sizes[OBJECT_SIZE_TYPE][VARNO] is unknown. */
167 : :
168 : : static inline bool
169 : 18945 : object_sizes_unknown_p (int object_size_type, unsigned varno)
170 : : {
171 : 18945 : return size_unknown_p (object_sizes[object_size_type][varno].size,
172 : 18945 : object_size_type);
173 : : }
174 : :
175 : : /* Return the raw size expression for VARNO corresponding to OSI. This returns
176 : : the TREE_VEC as is and should only be used during gimplification. */
177 : :
178 : : static inline object_size
179 : 576 : object_sizes_get_raw (struct object_size_info *osi, unsigned varno)
180 : : {
181 : 576 : gcc_assert (osi->pass != 0);
182 : 576 : return object_sizes[osi->object_size_type][varno];
183 : : }
184 : :
185 : : /* Return a size tree for VARNO corresponding to OSI. If WHOLE is true, return
186 : : the whole object size. Use this for building size expressions based on size
187 : : of VARNO. */
188 : :
189 : : static inline tree
190 : 24663 : object_sizes_get (struct object_size_info *osi, unsigned varno,
191 : : bool whole = false)
192 : : {
193 : 24663 : tree ret;
194 : 24663 : int object_size_type = osi->object_size_type;
195 : :
196 : 24663 : if (whole)
197 : 4561 : ret = object_sizes[object_size_type][varno].wholesize;
198 : : else
199 : 20102 : ret = object_sizes[object_size_type][varno].size;
200 : :
201 : 24663 : if (object_size_type & OST_DYNAMIC)
202 : : {
203 : 6917 : if (TREE_CODE (ret) == MODIFY_EXPR)
204 : 299 : return TREE_OPERAND (ret, 0);
205 : 6618 : else if (TREE_CODE (ret) == TREE_VEC)
206 : 334 : return TREE_VEC_ELT (ret, TREE_VEC_LENGTH (ret) - 1);
207 : : else
208 : 6284 : gcc_checking_assert (size_usable_p (ret));
209 : : }
210 : :
211 : : return ret;
212 : : }
213 : :
214 : : /* Set size for VARNO corresponding to OSI to VAL. */
215 : :
216 : : static inline void
217 : 11804 : object_sizes_initialize (struct object_size_info *osi, unsigned varno,
218 : : tree val, tree wholeval)
219 : : {
220 : 11804 : int object_size_type = osi->object_size_type;
221 : :
222 : 11804 : object_sizes[object_size_type][varno].size = val;
223 : 11804 : object_sizes[object_size_type][varno].wholesize = wholeval;
224 : 11804 : }
225 : :
226 : : /* Return a MODIFY_EXPR for cases where SSA and EXPR have the same type. The
227 : : TREE_VEC is returned only in case of PHI nodes. */
228 : :
229 : : static tree
230 : 379 : bundle_sizes (tree name, tree expr)
231 : : {
232 : 379 : gcc_checking_assert (TREE_TYPE (name) == sizetype);
233 : :
234 : 379 : if (TREE_CODE (expr) == TREE_VEC)
235 : : {
236 : 219 : TREE_VEC_ELT (expr, TREE_VEC_LENGTH (expr) - 1) = name;
237 : 219 : return expr;
238 : : }
239 : :
240 : 160 : gcc_checking_assert (types_compatible_p (TREE_TYPE (expr), sizetype));
241 : 160 : return build2 (MODIFY_EXPR, sizetype, name, expr);
242 : : }
243 : :
244 : : /* Set size for VARNO corresponding to OSI to VAL if it is the new minimum or
245 : : maximum. For static sizes, each element of TREE_VEC is always INTEGER_CST
246 : : throughout the computation. For dynamic sizes, each element may either be a
247 : : gimple variable, a MODIFY_EXPR or a TREE_VEC. The MODIFY_EXPR is for
248 : : expressions that need to be gimplified. TREE_VECs are special, they're
249 : : emitted only for GIMPLE_PHI and the PHI result variable is the last element
250 : : of the vector. */
251 : :
252 : : static bool
253 : 13926 : object_sizes_set (struct object_size_info *osi, unsigned varno, tree val,
254 : : tree wholeval)
255 : : {
256 : 13926 : int object_size_type = osi->object_size_type;
257 : 13926 : object_size osize = object_sizes[object_size_type][varno];
258 : 13926 : bool changed = true;
259 : :
260 : 13926 : tree oldval = osize.size;
261 : 13926 : tree old_wholeval = osize.wholesize;
262 : :
263 : 13926 : if (object_size_type & OST_DYNAMIC)
264 : : {
265 : 2748 : if (bitmap_bit_p (osi->reexamine, varno))
266 : : {
267 : 62 : val = bundle_sizes (oldval, val);
268 : 62 : wholeval = bundle_sizes (old_wholeval, wholeval);
269 : : }
270 : : else
271 : : {
272 : 2686 : gcc_checking_assert (size_initval_p (oldval, object_size_type));
273 : 2686 : gcc_checking_assert (size_initval_p (old_wholeval,
274 : : object_size_type));
275 : : /* For dynamic object sizes, all object sizes that are not gimple
276 : : variables will need to be gimplified. */
277 : 2686 : if (wholeval != val && !size_usable_p (wholeval))
278 : : {
279 : 42 : bitmap_set_bit (osi->reexamine, varno);
280 : 42 : wholeval = bundle_sizes (make_ssa_name (sizetype), wholeval);
281 : : }
282 : 2686 : if (!size_usable_p (val))
283 : : {
284 : 213 : bitmap_set_bit (osi->reexamine, varno);
285 : 213 : tree newval = bundle_sizes (make_ssa_name (sizetype), val);
286 : 213 : if (val == wholeval)
287 : 62 : wholeval = newval;
288 : : val = newval;
289 : : }
290 : : /* If the new value is a temporary variable, mark it for
291 : : reexamination. */
292 : 2473 : else if (TREE_CODE (val) == SSA_NAME && !SSA_NAME_DEF_STMT (val))
293 : 69 : bitmap_set_bit (osi->reexamine, varno);
294 : : }
295 : : }
296 : : else
297 : : {
298 : 22356 : enum tree_code code = (object_size_type & OST_MINIMUM
299 : 11178 : ? MIN_EXPR : MAX_EXPR);
300 : :
301 : 11178 : val = size_binop (code, val, oldval);
302 : 11178 : wholeval = size_binop (code, wholeval, old_wholeval);
303 : 11178 : changed = (tree_int_cst_compare (val, oldval) != 0
304 : 11178 : || tree_int_cst_compare (old_wholeval, wholeval) != 0);
305 : : }
306 : :
307 : 13926 : object_sizes[object_size_type][varno].size = val;
308 : 13926 : object_sizes[object_size_type][varno].wholesize = wholeval;
309 : :
310 : 13926 : return changed;
311 : : }
312 : :
313 : : /* Set temporary SSA names for object size and whole size to resolve dependency
314 : : loops in dynamic size computation. */
315 : :
316 : : static inline void
317 : 70 : object_sizes_set_temp (struct object_size_info *osi, unsigned varno)
318 : : {
319 : 70 : tree val = object_sizes_get (osi, varno);
320 : :
321 : 70 : if (size_initval_p (val, osi->object_size_type))
322 : 62 : object_sizes_set (osi, varno,
323 : : make_ssa_name (sizetype),
324 : : make_ssa_name (sizetype));
325 : 70 : }
326 : :
327 : : /* Initialize OFFSET_LIMIT variable. */
328 : : static void
329 : 3519 : init_offset_limit (void)
330 : : {
331 : 3519 : if (tree_fits_uhwi_p (TYPE_MAX_VALUE (sizetype)))
332 : 3519 : offset_limit = tree_to_uhwi (TYPE_MAX_VALUE (sizetype));
333 : : else
334 : 0 : offset_limit = -1;
335 : 3519 : offset_limit /= 2;
336 : 3519 : }
337 : :
338 : : /* Bytes at end of the object with SZ from offset OFFSET. If WHOLESIZE is not
339 : : NULL_TREE, use it to get the net offset of the pointer, which should always
340 : : be positive and hence, be within OFFSET_LIMIT for valid offsets. */
341 : :
342 : : static tree
343 : 13051 : size_for_offset (tree sz, tree offset, tree wholesize = NULL_TREE)
344 : : {
345 : 13051 : gcc_checking_assert (types_compatible_p (TREE_TYPE (sz), sizetype));
346 : :
347 : : /* For negative offsets, if we have a distinct WHOLESIZE, use it to get a net
348 : : offset from the whole object. */
349 : 13051 : if (wholesize && wholesize != sz
350 : 13051 : && (TREE_CODE (sz) != INTEGER_CST
351 : 240 : || TREE_CODE (wholesize) != INTEGER_CST
352 : 240 : || tree_int_cst_compare (sz, wholesize)))
353 : : {
354 : 311 : gcc_checking_assert (types_compatible_p (TREE_TYPE (wholesize),
355 : : sizetype));
356 : :
357 : : /* Restructure SZ - OFFSET as
358 : : WHOLESIZE - (WHOLESIZE + OFFSET - SZ) so that the offset part, i.e.
359 : : WHOLESIZE + OFFSET - SZ is only allowed to be positive. */
360 : 311 : tree tmp = size_binop (MAX_EXPR, wholesize, sz);
361 : 311 : offset = fold_build2 (PLUS_EXPR, sizetype, tmp, offset);
362 : 311 : offset = fold_build2 (MINUS_EXPR, sizetype, offset, sz);
363 : 311 : sz = tmp;
364 : : }
365 : :
366 : : /* Safe to convert now, since a valid net offset should be non-negative. */
367 : 13051 : if (!useless_type_conversion_p (sizetype, TREE_TYPE (offset)))
368 : 3242 : offset = fold_convert (sizetype, offset);
369 : :
370 : 13051 : if (TREE_CODE (offset) == INTEGER_CST)
371 : : {
372 : 12964 : if (integer_zerop (offset))
373 : : return sz;
374 : :
375 : : /* Negative or too large offset even after adjustment, cannot be within
376 : : bounds of an object. */
377 : 6478 : if (compare_tree_int (offset, offset_limit) > 0)
378 : 28 : return size_zero_node;
379 : : }
380 : :
381 : 6537 : return size_binop (MINUS_EXPR, size_binop (MAX_EXPR, sz, offset), offset);
382 : : }
383 : :
384 : : /* Compute offset of EXPR within VAR. Return error_mark_node
385 : : if unknown. */
386 : :
387 : : static tree
388 : 20756 : compute_object_offset (tree expr, const_tree var)
389 : : {
390 : 20764 : enum tree_code code = PLUS_EXPR;
391 : 20764 : tree base, off, t;
392 : :
393 : 20764 : if (expr == var)
394 : 9129 : return size_zero_node;
395 : :
396 : 11635 : switch (TREE_CODE (expr))
397 : : {
398 : 7146 : case COMPONENT_REF:
399 : 7146 : base = compute_object_offset (TREE_OPERAND (expr, 0), var);
400 : 7146 : if (base == error_mark_node)
401 : : return base;
402 : :
403 : 7146 : t = TREE_OPERAND (expr, 1);
404 : 7146 : off = size_binop (PLUS_EXPR,
405 : : component_ref_field_offset (expr),
406 : : size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
407 : : / BITS_PER_UNIT));
408 : 7146 : break;
409 : :
410 : 8 : case REALPART_EXPR:
411 : 8 : CASE_CONVERT:
412 : 8 : case VIEW_CONVERT_EXPR:
413 : 8 : case NON_LVALUE_EXPR:
414 : 8 : return compute_object_offset (TREE_OPERAND (expr, 0), var);
415 : :
416 : 8 : case IMAGPART_EXPR:
417 : 8 : base = compute_object_offset (TREE_OPERAND (expr, 0), var);
418 : 8 : if (base == error_mark_node)
419 : : return base;
420 : :
421 : 8 : off = TYPE_SIZE_UNIT (TREE_TYPE (expr));
422 : 8 : break;
423 : :
424 : 4472 : case ARRAY_REF:
425 : 4472 : base = compute_object_offset (TREE_OPERAND (expr, 0), var);
426 : 4472 : if (base == error_mark_node)
427 : : return base;
428 : :
429 : 4472 : t = TREE_OPERAND (expr, 1);
430 : 4472 : tree low_bound, unit_size;
431 : 4472 : low_bound = array_ref_low_bound (CONST_CAST_TREE (expr));
432 : 4472 : unit_size = array_ref_element_size (CONST_CAST_TREE (expr));
433 : 4472 : if (! integer_zerop (low_bound))
434 : 5 : t = fold_build2 (MINUS_EXPR, TREE_TYPE (t), t, low_bound);
435 : 4472 : if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
436 : : {
437 : 24 : code = MINUS_EXPR;
438 : 24 : t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
439 : : }
440 : 4472 : t = fold_convert (sizetype, t);
441 : 4472 : off = size_binop (MULT_EXPR, unit_size, t);
442 : 4472 : break;
443 : :
444 : 0 : case MEM_REF:
445 : 0 : gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR);
446 : 0 : return wide_int_to_tree (sizetype, mem_ref_offset (expr));
447 : :
448 : 1 : default:
449 : 1 : return error_mark_node;
450 : : }
451 : :
452 : 11626 : return size_binop (code, base, off);
453 : : }
454 : :
455 : : /* Returns the size of the object designated by DECL considering its
456 : : initializer if it either has one or if it would not affect its size,
457 : : otherwise the size of the object without the initializer when MIN
458 : : is true, else null. An object's initializer affects the object's
459 : : size if it's a struct type with a flexible array member. */
460 : :
461 : : tree
462 : 4757243 : decl_init_size (tree decl, bool min)
463 : : {
464 : 4757243 : tree size = DECL_SIZE_UNIT (decl);
465 : 4757243 : tree type = TREE_TYPE (decl);
466 : 4757243 : if (TREE_CODE (type) != RECORD_TYPE)
467 : : return size;
468 : :
469 : 2492556 : tree last = last_field (type);
470 : 2492556 : if (!last)
471 : : return size;
472 : :
473 : 2490676 : tree last_type = TREE_TYPE (last);
474 : 2490676 : if (TREE_CODE (last_type) != ARRAY_TYPE
475 : 2490676 : || TYPE_SIZE (last_type))
476 : : return size;
477 : :
478 : : /* Use TYPE_SIZE_UNIT; DECL_SIZE_UNIT sometimes reflects the size
479 : : of the initializer and sometimes doesn't. */
480 : 2390 : size = TYPE_SIZE_UNIT (type);
481 : 2390 : tree ref = build3 (COMPONENT_REF, type, decl, last, NULL_TREE);
482 : 2390 : tree compsize = component_ref_size (ref);
483 : 2390 : if (!compsize)
484 : 1004 : return min ? size : NULL_TREE;
485 : :
486 : : /* The size includes tail padding and initializer elements. */
487 : 1882 : tree pos = byte_position (last);
488 : 1882 : size = fold_build2 (PLUS_EXPR, TREE_TYPE (size), pos, compsize);
489 : 1882 : return size;
490 : : }
491 : :
492 : : /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
493 : : OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
494 : : If unknown, return size_unknown (object_size_type). */
495 : :
496 : : static bool
497 : 26022 : addr_object_size (struct object_size_info *osi, const_tree ptr,
498 : : int object_size_type, tree *psize, tree *pwholesize)
499 : : {
500 : 26022 : tree pt_var, pt_var_size = NULL_TREE, pt_var_wholesize = NULL_TREE;
501 : 26022 : tree var_size, bytes, wholebytes;
502 : :
503 : 26022 : gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
504 : :
505 : : /* Set to unknown and overwrite just before returning if the size
506 : : could be determined. */
507 : 26022 : *psize = size_unknown (object_size_type);
508 : 26022 : if (pwholesize)
509 : 7181 : *pwholesize = size_unknown (object_size_type);
510 : :
511 : 26022 : pt_var = TREE_OPERAND (ptr, 0);
512 : 43483 : while (handled_component_p (pt_var))
513 : 17461 : pt_var = TREE_OPERAND (pt_var, 0);
514 : :
515 : 26022 : if (!pt_var)
516 : : return false;
517 : :
518 : 26022 : if (TREE_CODE (pt_var) == MEM_REF)
519 : : {
520 : 6057 : tree sz, wholesize;
521 : :
522 : 5140 : if (!osi || (object_size_type & OST_SUBOBJECT) != 0
523 : 7540 : || TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
524 : : {
525 : 4575 : compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
526 : : object_size_type & ~OST_SUBOBJECT, &sz);
527 : 4575 : wholesize = sz;
528 : : }
529 : : else
530 : : {
531 : 1482 : tree var = TREE_OPERAND (pt_var, 0);
532 : 1482 : if (osi->pass == 0)
533 : 1482 : collect_object_sizes_for (osi, var);
534 : 2964 : if (bitmap_bit_p (computed[object_size_type],
535 : 1482 : SSA_NAME_VERSION (var)))
536 : : {
537 : 1482 : sz = object_sizes_get (osi, SSA_NAME_VERSION (var));
538 : 1482 : wholesize = object_sizes_get (osi, SSA_NAME_VERSION (var), true);
539 : : }
540 : : else
541 : 0 : sz = wholesize = size_unknown (object_size_type);
542 : : }
543 : 6057 : if (!size_unknown_p (sz, object_size_type))
544 : 3242 : sz = size_for_offset (sz, TREE_OPERAND (pt_var, 1), wholesize);
545 : :
546 : 6057 : if (!size_unknown_p (sz, object_size_type)
547 : 6057 : && (TREE_CODE (sz) != INTEGER_CST
548 : 3204 : || compare_tree_int (sz, offset_limit) < 0))
549 : : {
550 : 3232 : pt_var_size = sz;
551 : 3232 : pt_var_wholesize = wholesize;
552 : : }
553 : : }
554 : 19965 : else if (DECL_P (pt_var))
555 : : {
556 : 39724 : pt_var_size = pt_var_wholesize
557 : 19862 : = decl_init_size (pt_var, object_size_type & OST_MINIMUM);
558 : 19862 : if (!pt_var_size)
559 : : return false;
560 : : }
561 : 103 : else if (TREE_CODE (pt_var) == STRING_CST)
562 : 103 : pt_var_size = pt_var_wholesize = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
563 : : else
564 : : return false;
565 : :
566 : 6160 : if (pt_var_size)
567 : : {
568 : : /* Validate the size determined above if it is a constant. */
569 : 23079 : if (TREE_CODE (pt_var_size) == INTEGER_CST
570 : 23079 : && compare_tree_int (pt_var_size, offset_limit) >= 0)
571 : : return false;
572 : : }
573 : :
574 : 25868 : if (pt_var != TREE_OPERAND (ptr, 0))
575 : : {
576 : 9618 : tree var;
577 : :
578 : 9618 : if (object_size_type & OST_SUBOBJECT)
579 : : {
580 : 4206 : var = TREE_OPERAND (ptr, 0);
581 : :
582 : 4206 : while (var != pt_var
583 : 4206 : && TREE_CODE (var) != BIT_FIELD_REF
584 : : && TREE_CODE (var) != COMPONENT_REF
585 : : && TREE_CODE (var) != ARRAY_REF
586 : : && TREE_CODE (var) != ARRAY_RANGE_REF
587 : : && TREE_CODE (var) != REALPART_EXPR
588 : 4206 : && TREE_CODE (var) != IMAGPART_EXPR)
589 : 0 : var = TREE_OPERAND (var, 0);
590 : 4206 : if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
591 : 1947 : var = TREE_OPERAND (var, 0);
592 : 4206 : if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
593 : 4162 : || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var)))
594 : 8348 : || (pt_var_size && TREE_CODE (pt_var_size) == INTEGER_CST
595 : 1917 : && tree_int_cst_lt (pt_var_size,
596 : 1917 : TYPE_SIZE_UNIT (TREE_TYPE (var)))))
597 : : var = pt_var;
598 : 4002 : else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF)
599 : : {
600 : : tree v = var;
601 : : /* For &X->fld, compute object size if fld isn't a flexible array
602 : : member. */
603 : 6962 : bool is_flexible_array_mem_ref = false;
604 : 6962 : while (v && v != pt_var)
605 : 3483 : switch (TREE_CODE (v))
606 : : {
607 : 0 : case ARRAY_REF:
608 : 0 : if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0))))
609 : : {
610 : 0 : tree domain
611 : 0 : = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0)));
612 : 0 : if (domain && TYPE_MAX_VALUE (domain))
613 : : {
614 : : v = NULL_TREE;
615 : : break;
616 : : }
617 : : }
618 : 0 : v = TREE_OPERAND (v, 0);
619 : 0 : break;
620 : : case REALPART_EXPR:
621 : : case IMAGPART_EXPR:
622 : : v = NULL_TREE;
623 : : break;
624 : 3483 : case COMPONENT_REF:
625 : : /* When the ref is not to an aggregate type, i.e, an array,
626 : : a record or a union, it will not have flexible size,
627 : : compute the object size directly. */
628 : 3483 : if (!AGGREGATE_TYPE_P (TREE_TYPE (v)))
629 : : {
630 : : v = NULL_TREE;
631 : : break;
632 : : }
633 : : /* if the ref is to a record or union type, but the type
634 : : does not include a flexible array recursively, compute
635 : : the object size directly. */
636 : 2513 : if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (v)))
637 : : {
638 : 52 : if (!TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (v)))
639 : : {
640 : : v = NULL_TREE;
641 : : break;
642 : : }
643 : : else
644 : : {
645 : 16 : v = TREE_OPERAND (v, 0);
646 : 16 : break;
647 : : }
648 : : }
649 : : /* Now the ref is to an array type. */
650 : 2461 : gcc_assert (TREE_CODE (TREE_TYPE (v)) == ARRAY_TYPE);
651 : 2461 : is_flexible_array_mem_ref = array_ref_flexible_size_p (v);
652 : 5967 : while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
653 : 3261 : if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
654 : : != UNION_TYPE
655 : 3261 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
656 : : != QUAL_UNION_TYPE)
657 : : break;
658 : : else
659 : 1045 : v = TREE_OPERAND (v, 0);
660 : 2461 : if (TREE_CODE (v) == COMPONENT_REF
661 : 2461 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
662 : : == RECORD_TYPE)
663 : : {
664 : : /* compute object size only if v is not a
665 : : flexible array member. */
666 : 2216 : if (!is_flexible_array_mem_ref)
667 : : {
668 : : v = NULL_TREE;
669 : : break;
670 : : }
671 : 1063 : v = TREE_OPERAND (v, 0);
672 : : }
673 : 1638 : while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
674 : 482 : if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
675 : : != UNION_TYPE
676 : 482 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
677 : : != QUAL_UNION_TYPE)
678 : : break;
679 : : else
680 : 330 : v = TREE_OPERAND (v, 0);
681 : 1308 : if (v != pt_var)
682 : : v = NULL_TREE;
683 : : else
684 : 3483 : v = pt_var;
685 : : break;
686 : : default:
687 : 6962 : v = pt_var;
688 : : break;
689 : : }
690 : 3479 : if (v == pt_var)
691 : 6784 : var = pt_var;
692 : : }
693 : : }
694 : : else
695 : : var = pt_var;
696 : :
697 : 9618 : if (var != pt_var)
698 : : {
699 : 2719 : var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
700 : 2719 : if (!TREE_CONSTANT (var_size))
701 : 0 : var_size = get_or_create_ssa_default_def (cfun, var_size);
702 : 2719 : if (!var_size)
703 : : return false;
704 : : }
705 : 6899 : else if (!pt_var_size)
706 : : return false;
707 : : else
708 : : var_size = pt_var_size;
709 : 8257 : bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
710 : 8257 : if (bytes != error_mark_node)
711 : : {
712 : 8256 : bytes = size_for_offset (var_size, bytes);
713 : 8256 : if (var != pt_var && pt_var_size && TREE_CODE (pt_var) == MEM_REF)
714 : : {
715 : 873 : tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0),
716 : : pt_var);
717 : 873 : if (bytes2 != error_mark_node)
718 : : {
719 : 873 : bytes2 = size_for_offset (pt_var_size, bytes2);
720 : 873 : bytes = size_binop (MIN_EXPR, bytes, bytes2);
721 : : }
722 : : }
723 : : }
724 : : else
725 : 1 : bytes = size_unknown (object_size_type);
726 : :
727 : 8257 : wholebytes
728 : 8257 : = object_size_type & OST_SUBOBJECT ? var_size : pt_var_wholesize;
729 : : }
730 : 16250 : else if (!pt_var_size)
731 : : return false;
732 : : else
733 : : {
734 : : bytes = pt_var_size;
735 : : wholebytes = pt_var_wholesize;
736 : : }
737 : :
738 : 24481 : if (!size_unknown_p (bytes, object_size_type)
739 : 50390 : && size_valid_p (bytes, object_size_type)
740 : 24368 : && !size_unknown_p (bytes, object_size_type)
741 : 24481 : && size_valid_p (wholebytes, object_size_type))
742 : : {
743 : 24368 : *psize = bytes;
744 : 24368 : if (pwholesize)
745 : 5782 : *pwholesize = wholebytes;
746 : 24368 : return true;
747 : : }
748 : :
749 : : return false;
750 : : }
751 : :
752 : :
753 : : /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
754 : : Handles calls to functions declared with attribute alloc_size.
755 : : OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
756 : : If unknown, return size_unknown (object_size_type). */
757 : :
758 : : static tree
759 : 1808 : alloc_object_size (const gcall *call, int object_size_type)
760 : : {
761 : 1808 : gcc_assert (is_gimple_call (call));
762 : :
763 : 1808 : tree calltype;
764 : 1808 : tree callfn = gimple_call_fndecl (call);
765 : 1808 : if (callfn)
766 : 1664 : calltype = TREE_TYPE (callfn);
767 : : else
768 : 144 : calltype = gimple_call_fntype (call);
769 : :
770 : 1808 : if (!calltype)
771 : 0 : return size_unknown (object_size_type);
772 : :
773 : : /* Set to positions of alloc_size arguments. */
774 : 1808 : int arg1 = -1, arg2 = -1;
775 : 1808 : tree alloc_size = lookup_attribute ("alloc_size",
776 : 1808 : TYPE_ATTRIBUTES (calltype));
777 : 3460 : if (alloc_size && TREE_VALUE (alloc_size))
778 : : {
779 : 1652 : tree p = TREE_VALUE (alloc_size);
780 : :
781 : 1652 : arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1;
782 : 1652 : if (TREE_CHAIN (p))
783 : 184 : arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
784 : : }
785 : 156 : else if (gimple_call_builtin_p (call, BUILT_IN_NORMAL)
786 : 115 : && callfn
787 : 271 : && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (callfn)))
788 : : arg1 = 0;
789 : :
790 : : /* Non-const arguments are OK here, let the caller handle constness. */
791 : 1652 : if (arg1 < 0
792 : 1735 : || (unsigned) arg1 >= gimple_call_num_args (call)
793 : 3387 : || (arg2 >= 0 && (unsigned) arg2 >= gimple_call_num_args (call)))
794 : 73 : return size_unknown (object_size_type);
795 : :
796 : 1735 : tree targ1 = gimple_call_arg (call, arg1);
797 : 3470 : if (!INTEGRAL_TYPE_P (TREE_TYPE (targ1))
798 : 3468 : || TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (sizetype))
799 : 2 : return size_unknown (object_size_type);
800 : 1733 : targ1 = fold_convert (sizetype, targ1);
801 : 1733 : tree bytes = NULL_TREE;
802 : 1733 : if (arg2 >= 0)
803 : : {
804 : 184 : tree targ2 = gimple_call_arg (call, arg2);
805 : 368 : if (!INTEGRAL_TYPE_P (TREE_TYPE (targ2))
806 : 368 : || TYPE_PRECISION (TREE_TYPE (targ2)) > TYPE_PRECISION (sizetype))
807 : 0 : return size_unknown (object_size_type);
808 : 184 : targ2 = fold_convert (sizetype, targ2);
809 : 184 : bytes = size_binop (MULT_EXPR, targ1, targ2);
810 : : }
811 : : else
812 : : bytes = targ1;
813 : :
814 : 1733 : return bytes ? bytes : size_unknown (object_size_type);
815 : : }
816 : :
817 : : /* Compute __builtin_object_size for CALL, which is a call to either
818 : : BUILT_IN_STRDUP or BUILT_IN_STRNDUP; IS_STRNDUP indicates which it is.
819 : : OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
820 : : If unknown, return size_unknown (object_size_type). */
821 : :
822 : : static tree
823 : 160 : strdup_object_size (const gcall *call, int object_size_type, bool is_strndup)
824 : : {
825 : 160 : tree src = gimple_call_arg (call, 0);
826 : 160 : tree sz = size_unknown (object_size_type);
827 : 160 : tree n = NULL_TREE;
828 : :
829 : 160 : if (is_strndup)
830 : 110 : n = fold_build2 (PLUS_EXPR, sizetype, size_one_node,
831 : : gimple_call_arg (call, 1));
832 : : /* For strdup, simply emit strlen (SRC) + 1 and let the optimizer fold it the
833 : : way it likes. */
834 : : else
835 : : {
836 : 50 : tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
837 : 50 : if (strlen_fn)
838 : : {
839 : 50 : sz = fold_build2 (PLUS_EXPR, sizetype, size_one_node,
840 : : build_call_expr (strlen_fn, 1, src));
841 : 50 : todo = TODO_update_ssa_only_virtuals;
842 : : }
843 : : }
844 : :
845 : : /* In all other cases, return the size of SRC since the object size cannot
846 : : exceed that. We cannot do this for OST_MINIMUM unless SRC points into a
847 : : string constant since otherwise the object size could go all the way down
848 : : to zero. */
849 : 160 : if (!size_valid_p (sz, object_size_type)
850 : 152 : || size_unknown_p (sz, object_size_type))
851 : : {
852 : 118 : tree wholesrc = NULL_TREE;
853 : 118 : if (TREE_CODE (src) == ADDR_EXPR)
854 : 48 : wholesrc = get_base_address (TREE_OPERAND (src, 0));
855 : :
856 : : /* If the source points within a string constant, we try to get its
857 : : length. */
858 : 48 : if (wholesrc && TREE_CODE (wholesrc) == STRING_CST)
859 : : {
860 : 48 : tree len = c_strlen (src, 0);
861 : 48 : if (len)
862 : 48 : sz = fold_build2 (PLUS_EXPR, sizetype, size_one_node, len);
863 : : }
864 : :
865 : : /* For maximum estimate, our next best guess is the object size of the
866 : : source. */
867 : 118 : if (size_unknown_p (sz, object_size_type)
868 : 118 : && !(object_size_type & OST_MINIMUM))
869 : 31 : compute_builtin_object_size (src, object_size_type, &sz);
870 : : }
871 : :
872 : : /* String duplication allocates at least one byte, so we should never fail
873 : : for OST_MINIMUM. */
874 : 160 : if ((!size_valid_p (sz, object_size_type)
875 : 152 : || size_unknown_p (sz, object_size_type))
876 : 40 : && (object_size_type & OST_MINIMUM))
877 : 35 : sz = size_one_node;
878 : :
879 : : /* Factor in the N. */
880 : 160 : return n ? fold_build2 (MIN_EXPR, sizetype, n, sz) : sz;
881 : : }
882 : :
883 : : /* If object size is propagated from one of function's arguments directly
884 : : to its return value, return that argument for GIMPLE_CALL statement CALL.
885 : : Otherwise return NULL. */
886 : :
887 : : static tree
888 : 2043 : pass_through_call (const gcall *call)
889 : : {
890 : 2043 : unsigned rf = gimple_call_return_flags (call);
891 : 2043 : if (rf & ERF_RETURNS_ARG)
892 : : {
893 : 75 : unsigned argnum = rf & ERF_RETURN_ARG_MASK;
894 : 75 : if (argnum < gimple_call_num_args (call))
895 : 75 : return gimple_call_arg (call, argnum);
896 : : }
897 : :
898 : : /* __builtin_assume_aligned is intentionally not marked RET1. */
899 : 1968 : if (gimple_call_builtin_p (call, BUILT_IN_ASSUME_ALIGNED))
900 : 0 : return gimple_call_arg (call, 0);
901 : :
902 : : return NULL_TREE;
903 : : }
904 : :
905 : : /* Emit PHI nodes for size expressions fo. */
906 : :
907 : : static void
908 : 116 : emit_phi_nodes (gimple *stmt, tree size, tree wholesize)
909 : : {
910 : 116 : tree phires;
911 : 116 : gphi *wholephi = NULL;
912 : :
913 : 116 : if (wholesize != size)
914 : : {
915 : 103 : phires = TREE_VEC_ELT (wholesize, TREE_VEC_LENGTH (wholesize) - 1);
916 : 103 : wholephi = create_phi_node (phires, gimple_bb (stmt));
917 : : }
918 : :
919 : 116 : phires = TREE_VEC_ELT (size, TREE_VEC_LENGTH (size) - 1);
920 : 116 : gphi *phi = create_phi_node (phires, gimple_bb (stmt));
921 : 116 : gphi *obj_phi = as_a <gphi *> (stmt);
922 : :
923 : 116 : gcc_checking_assert (TREE_CODE (wholesize) == TREE_VEC);
924 : 116 : gcc_checking_assert (TREE_CODE (size) == TREE_VEC);
925 : :
926 : 378 : for (unsigned i = 0; i < gimple_phi_num_args (stmt); i++)
927 : : {
928 : 262 : gimple_seq seq = NULL;
929 : 262 : tree wsz = TREE_VEC_ELT (wholesize, i);
930 : 262 : tree sz = TREE_VEC_ELT (size, i);
931 : :
932 : : /* If we built an expression, we will need to build statements
933 : : and insert them on the edge right away. */
934 : 262 : if (TREE_CODE (wsz) != SSA_NAME)
935 : 127 : wsz = force_gimple_operand (wsz, &seq, true, NULL);
936 : 262 : if (TREE_CODE (sz) != SSA_NAME)
937 : : {
938 : 139 : gimple_seq s;
939 : 139 : sz = force_gimple_operand (sz, &s, true, NULL);
940 : 139 : gimple_seq_add_seq (&seq, s);
941 : : }
942 : :
943 : 262 : if (seq)
944 : 0 : gsi_insert_seq_on_edge (gimple_phi_arg_edge (obj_phi, i), seq);
945 : :
946 : 262 : if (wholephi)
947 : 236 : add_phi_arg (wholephi, wsz,
948 : : gimple_phi_arg_edge (obj_phi, i),
949 : : gimple_phi_arg_location (obj_phi, i));
950 : :
951 : 262 : add_phi_arg (phi, sz,
952 : : gimple_phi_arg_edge (obj_phi, i),
953 : : gimple_phi_arg_location (obj_phi, i));
954 : : }
955 : 116 : }
956 : :
957 : : /* Descend through EXPR and return size_unknown if it uses any SSA variable
958 : : object_size_set or object_size_set_temp generated, which turned out to be
959 : : size_unknown, as noted in UNKNOWNS. */
960 : :
961 : : static tree
962 : 2418 : propagate_unknowns (object_size_info *osi, tree expr, bitmap unknowns)
963 : : {
964 : 2418 : int object_size_type = osi->object_size_type;
965 : :
966 : 2418 : switch (TREE_CODE (expr))
967 : : {
968 : 939 : case SSA_NAME:
969 : 939 : if (bitmap_bit_p (unknowns, SSA_NAME_VERSION (expr)))
970 : 0 : return size_unknown (object_size_type);
971 : : return expr;
972 : :
973 : 265 : case MIN_EXPR:
974 : 265 : case MAX_EXPR:
975 : 265 : {
976 : 265 : tree res = propagate_unknowns (osi, TREE_OPERAND (expr, 0),
977 : : unknowns);
978 : 265 : if (size_unknown_p (res, object_size_type))
979 : : return res;
980 : :
981 : 265 : res = propagate_unknowns (osi, TREE_OPERAND (expr, 1), unknowns);
982 : 265 : if (size_unknown_p (res, object_size_type))
983 : : return res;
984 : :
985 : : return expr;
986 : : }
987 : 209 : case MODIFY_EXPR:
988 : 209 : {
989 : 209 : tree res = propagate_unknowns (osi, TREE_OPERAND (expr, 1),
990 : : unknowns);
991 : 209 : if (size_unknown_p (res, object_size_type))
992 : : return res;
993 : : return expr;
994 : : }
995 : : case TREE_VEC:
996 : 988 : for (int i = 0; i < TREE_VEC_LENGTH (expr); i++)
997 : : {
998 : 756 : tree res = propagate_unknowns (osi, TREE_VEC_ELT (expr, i),
999 : : unknowns);
1000 : 756 : if (size_unknown_p (res, object_size_type))
1001 : 0 : return res;
1002 : : }
1003 : : return expr;
1004 : 347 : case PLUS_EXPR:
1005 : 347 : case MINUS_EXPR:
1006 : 347 : {
1007 : 347 : tree res = propagate_unknowns (osi, TREE_OPERAND (expr, 0),
1008 : : unknowns);
1009 : 347 : if (size_unknown_p (res, object_size_type))
1010 : : return res;
1011 : :
1012 : : return expr;
1013 : : }
1014 : : default:
1015 : : return expr;
1016 : : }
1017 : : }
1018 : :
1019 : : /* Walk through size expressions that need reexamination and generate
1020 : : statements for them. */
1021 : :
1022 : : static void
1023 : 2127 : gimplify_size_expressions (object_size_info *osi)
1024 : : {
1025 : 2127 : int object_size_type = osi->object_size_type;
1026 : 2127 : bitmap_iterator bi;
1027 : 2127 : unsigned int i;
1028 : 2127 : bool changed;
1029 : :
1030 : : /* Step 1: Propagate unknowns into expressions. */
1031 : 2127 : bitmap reexamine = BITMAP_ALLOC (NULL);
1032 : 2127 : bitmap_copy (reexamine, osi->reexamine);
1033 : 2127 : bitmap unknowns = BITMAP_ALLOC (NULL);
1034 : 2127 : do
1035 : : {
1036 : 2127 : changed = false;
1037 : 2415 : EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
1038 : : {
1039 : 288 : object_size cur = object_sizes_get_raw (osi, i);
1040 : :
1041 : 288 : if (size_unknown_p (propagate_unknowns (osi, cur.size, unknowns),
1042 : : object_size_type)
1043 : 288 : || size_unknown_p (propagate_unknowns (osi, cur.wholesize,
1044 : : unknowns),
1045 : : object_size_type))
1046 : : {
1047 : : /* Record the SSAs we're overwriting to propagate the
1048 : : unknwons. */
1049 : 0 : tree oldval = object_sizes_get (osi, i);
1050 : 0 : tree old_wholeval = object_sizes_get (osi, i, true);
1051 : :
1052 : 0 : bitmap_set_bit (unknowns, SSA_NAME_VERSION (oldval));
1053 : 0 : bitmap_set_bit (unknowns, SSA_NAME_VERSION (old_wholeval));
1054 : 0 : object_sizes_initialize (osi, i,
1055 : : size_unknown (object_size_type),
1056 : : size_unknown (object_size_type));
1057 : 0 : bitmap_clear_bit (osi->reexamine, i);
1058 : 0 : changed = true;
1059 : : }
1060 : : }
1061 : 2127 : bitmap_copy (reexamine, osi->reexamine);
1062 : : }
1063 : : while (changed);
1064 : :
1065 : : /* Release all unknowns. */
1066 : 2127 : EXECUTE_IF_SET_IN_BITMAP (unknowns, 0, i, bi)
1067 : 0 : release_ssa_name (ssa_name (i));
1068 : :
1069 : 2127 : BITMAP_FREE (unknowns);
1070 : 2127 : BITMAP_FREE (reexamine);
1071 : :
1072 : : /* Expand all size expressions to put their definitions close to the objects
1073 : : for which size is being computed. */
1074 : 2415 : EXECUTE_IF_SET_IN_BITMAP (osi->reexamine, 0, i, bi)
1075 : : {
1076 : 288 : gimple_seq seq = NULL;
1077 : 288 : object_size osize = object_sizes_get_raw (osi, i);
1078 : :
1079 : 288 : gimple *stmt = SSA_NAME_DEF_STMT (ssa_name (i));
1080 : 288 : enum gimple_code code = gimple_code (stmt);
1081 : :
1082 : : /* PHI nodes need special attention. */
1083 : 288 : if (code == GIMPLE_PHI)
1084 : 116 : emit_phi_nodes (stmt, osize.size, osize.wholesize);
1085 : : else
1086 : : {
1087 : 172 : tree size_expr = NULL_TREE;
1088 : :
1089 : : /* Bundle wholesize in with the size to gimplify if needed. */
1090 : 172 : if (osize.wholesize != osize.size
1091 : 172 : && !size_usable_p (osize.wholesize))
1092 : 1 : size_expr = size_binop (COMPOUND_EXPR,
1093 : : osize.wholesize,
1094 : : osize.size);
1095 : 171 : else if (!size_usable_p (osize.size))
1096 : : size_expr = osize.size;
1097 : :
1098 : 159 : if (size_expr)
1099 : : {
1100 : 159 : gimple_stmt_iterator gsi;
1101 : 159 : if (code == GIMPLE_NOP)
1102 : 22 : gsi = gsi_start_bb (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
1103 : : else
1104 : 148 : gsi = gsi_for_stmt (stmt);
1105 : :
1106 : 159 : force_gimple_operand (size_expr, &seq, true, NULL);
1107 : 159 : gsi_insert_seq_before (&gsi, seq, GSI_CONTINUE_LINKING);
1108 : : }
1109 : : }
1110 : :
1111 : : /* We're done, so replace the MODIFY_EXPRs with the SSA names. */
1112 : 288 : object_sizes_initialize (osi, i,
1113 : : object_sizes_get (osi, i),
1114 : : object_sizes_get (osi, i, true));
1115 : : }
1116 : 2127 : }
1117 : :
1118 : : /* Compute __builtin_object_size value for PTR and set *PSIZE to
1119 : : the resulting value. If the declared object is known and PDECL
1120 : : is nonnull, sets *PDECL to the object's DECL. OBJECT_SIZE_TYPE
1121 : : is the second argument to __builtin_object_size.
1122 : : Returns true on success and false when the object size could not
1123 : : be determined. */
1124 : :
1125 : : bool
1126 : 146359 : compute_builtin_object_size (tree ptr, int object_size_type,
1127 : : tree *psize)
1128 : : {
1129 : 146359 : gcc_assert (object_size_type >= 0 && object_size_type < OST_END);
1130 : :
1131 : : /* Set to unknown and overwrite just before returning if the size
1132 : : could be determined. */
1133 : 146359 : *psize = size_unknown (object_size_type);
1134 : :
1135 : 146359 : if (! offset_limit)
1136 : 1002 : init_offset_limit ();
1137 : :
1138 : 146359 : if (TREE_CODE (ptr) == ADDR_EXPR)
1139 : 18841 : return addr_object_size (NULL, ptr, object_size_type, psize);
1140 : :
1141 : 127518 : if (TREE_CODE (ptr) != SSA_NAME
1142 : 127518 : || !POINTER_TYPE_P (TREE_TYPE (ptr)))
1143 : : return false;
1144 : :
1145 : 127207 : if (computed[object_size_type] == NULL)
1146 : : {
1147 : 111770 : if (optimize || object_size_type & OST_SUBOBJECT)
1148 : : return false;
1149 : :
1150 : : /* When not optimizing, rather than failing, make a small effort
1151 : : to determine the object size without the full benefit of
1152 : : the (costly) computation below. */
1153 : 2142 : gimple *def = SSA_NAME_DEF_STMT (ptr);
1154 : 2142 : if (gimple_code (def) == GIMPLE_ASSIGN)
1155 : : {
1156 : 1497 : tree_code code = gimple_assign_rhs_code (def);
1157 : 1497 : if (code == POINTER_PLUS_EXPR)
1158 : : {
1159 : 945 : tree offset = gimple_assign_rhs2 (def);
1160 : 945 : ptr = gimple_assign_rhs1 (def);
1161 : :
1162 : 945 : if (((object_size_type & OST_DYNAMIC)
1163 : 823 : || (tree_fits_shwi_p (offset)
1164 : 505 : && compare_tree_int (offset, offset_limit) <= 0))
1165 : 1450 : && compute_builtin_object_size (ptr, object_size_type,
1166 : : psize))
1167 : : {
1168 : 243 : *psize = size_for_offset (*psize, offset);
1169 : 243 : return true;
1170 : : }
1171 : : }
1172 : : }
1173 : 1899 : return false;
1174 : : }
1175 : :
1176 : 15437 : struct object_size_info osi;
1177 : 15437 : osi.object_size_type = object_size_type;
1178 : 15437 : if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
1179 : : {
1180 : 9502 : bitmap_iterator bi;
1181 : 9502 : unsigned int i;
1182 : :
1183 : 9502 : object_sizes_grow (object_size_type);
1184 : 9502 : if (dump_file)
1185 : : {
1186 : 12 : fprintf (dump_file, "Computing %s %s%sobject size for ",
1187 : 12 : (object_size_type & OST_MINIMUM) ? "minimum" : "maximum",
1188 : 12 : (object_size_type & OST_DYNAMIC) ? "dynamic " : "",
1189 : 12 : (object_size_type & OST_SUBOBJECT) ? "sub" : "");
1190 : 12 : print_generic_expr (dump_file, ptr, dump_flags);
1191 : 12 : fprintf (dump_file, ":\n");
1192 : : }
1193 : :
1194 : 9502 : osi.visited = BITMAP_ALLOC (NULL);
1195 : 9502 : osi.reexamine = BITMAP_ALLOC (NULL);
1196 : :
1197 : 9502 : if (!(object_size_type & OST_DYNAMIC))
1198 : : {
1199 : 7375 : osi.depths = NULL;
1200 : 7375 : osi.stack = NULL;
1201 : 7375 : osi.tos = NULL;
1202 : : }
1203 : :
1204 : : /* First pass: walk UD chains, compute object sizes that can be computed.
1205 : : osi.reexamine bitmap at the end will contain versions of SSA_NAMES
1206 : : that need to be reexamined. For both static and dynamic size
1207 : : computation, reexamination is for propagation across dependency loops.
1208 : : The dynamic case has the additional use case where the computed
1209 : : expression needs to be gimplified. */
1210 : 9502 : osi.pass = 0;
1211 : 9502 : osi.changed = false;
1212 : 9502 : collect_object_sizes_for (&osi, ptr);
1213 : :
1214 : 9502 : if (object_size_type & OST_DYNAMIC)
1215 : : {
1216 : 2127 : osi.pass = 1;
1217 : 2127 : gimplify_size_expressions (&osi);
1218 : 2127 : bitmap_clear (osi.reexamine);
1219 : : }
1220 : :
1221 : : /* Second pass: keep recomputing object sizes of variables
1222 : : that need reexamination, until no object sizes are
1223 : : increased or all object sizes are computed. */
1224 : 9502 : if (! bitmap_empty_p (osi.reexamine))
1225 : : {
1226 : 271 : bitmap reexamine = BITMAP_ALLOC (NULL);
1227 : :
1228 : : /* If looking for minimum instead of maximum object size,
1229 : : detect cases where a pointer is increased in a loop.
1230 : : Although even without this detection pass 2 would eventually
1231 : : terminate, it could take a long time. If a pointer is
1232 : : increasing this way, we need to assume 0 object size.
1233 : : E.g. p = &buf[0]; while (cond) p = p + 4; */
1234 : 271 : if (object_size_type & OST_MINIMUM)
1235 : : {
1236 : 38 : osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
1237 : 38 : osi.stack = XNEWVEC (unsigned int, num_ssa_names);
1238 : 19 : osi.tos = osi.stack;
1239 : 19 : osi.pass = 1;
1240 : : /* collect_object_sizes_for is changing
1241 : : osi.reexamine bitmap, so iterate over a copy. */
1242 : 19 : bitmap_copy (reexamine, osi.reexamine);
1243 : 57 : EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
1244 : 38 : if (bitmap_bit_p (osi.reexamine, i))
1245 : 38 : check_for_plus_in_loops (&osi, ssa_name (i));
1246 : :
1247 : 19 : free (osi.depths);
1248 : 19 : osi.depths = NULL;
1249 : 19 : free (osi.stack);
1250 : 19 : osi.stack = NULL;
1251 : 19 : osi.tos = NULL;
1252 : : }
1253 : :
1254 : 285 : do
1255 : : {
1256 : 285 : osi.pass = 2;
1257 : 285 : osi.changed = false;
1258 : : /* collect_object_sizes_for is changing
1259 : : osi.reexamine bitmap, so iterate over a copy. */
1260 : 285 : bitmap_copy (reexamine, osi.reexamine);
1261 : 864 : EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
1262 : 579 : if (bitmap_bit_p (osi.reexamine, i))
1263 : : {
1264 : 579 : collect_object_sizes_for (&osi, ssa_name (i));
1265 : 579 : if (dump_file && (dump_flags & TDF_DETAILS))
1266 : : {
1267 : 0 : fprintf (dump_file, "Reexamining ");
1268 : 0 : print_generic_expr (dump_file, ssa_name (i),
1269 : : dump_flags);
1270 : 0 : fprintf (dump_file, "\n");
1271 : : }
1272 : : }
1273 : : }
1274 : 285 : while (osi.changed);
1275 : :
1276 : 271 : BITMAP_FREE (reexamine);
1277 : : }
1278 : 10031 : EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
1279 : 529 : bitmap_set_bit (computed[object_size_type], i);
1280 : :
1281 : : /* Debugging dumps. */
1282 : 9502 : if (dump_file)
1283 : : {
1284 : 66 : EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
1285 : 54 : if (!object_sizes_unknown_p (object_size_type, i))
1286 : : {
1287 : 54 : print_generic_expr (dump_file, ssa_name (i),
1288 : : dump_flags);
1289 : 108 : fprintf (dump_file,
1290 : : ": %s %s%sobject size ",
1291 : 54 : ((object_size_type & OST_MINIMUM) ? "minimum"
1292 : : : "maximum"),
1293 : : (object_size_type & OST_DYNAMIC) ? "dynamic " : "",
1294 : 54 : (object_size_type & OST_SUBOBJECT) ? "sub" : "");
1295 : 54 : print_generic_expr (dump_file, object_sizes_get (&osi, i),
1296 : : dump_flags);
1297 : 54 : fprintf (dump_file, "\n");
1298 : : }
1299 : : }
1300 : :
1301 : 9502 : BITMAP_FREE (osi.reexamine);
1302 : 9502 : BITMAP_FREE (osi.visited);
1303 : : }
1304 : :
1305 : 15437 : *psize = object_sizes_get (&osi, SSA_NAME_VERSION (ptr));
1306 : 15437 : return !size_unknown_p (*psize, object_size_type);
1307 : : }
1308 : :
1309 : : /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */
1310 : :
1311 : : static void
1312 : 8473 : expr_object_size (struct object_size_info *osi, tree ptr, tree value)
1313 : : {
1314 : 8473 : int object_size_type = osi->object_size_type;
1315 : 8473 : unsigned int varno = SSA_NAME_VERSION (ptr);
1316 : 8473 : tree bytes, wholesize;
1317 : :
1318 : 8473 : gcc_assert (!object_sizes_unknown_p (object_size_type, varno));
1319 : 8473 : gcc_assert (osi->pass == 0);
1320 : :
1321 : 8473 : if (TREE_CODE (value) == WITH_SIZE_EXPR)
1322 : 0 : value = TREE_OPERAND (value, 0);
1323 : :
1324 : : /* Pointer variables should have been handled by merge_object_sizes. */
1325 : 8473 : gcc_assert (TREE_CODE (value) != SSA_NAME
1326 : : || !POINTER_TYPE_P (TREE_TYPE (value)));
1327 : :
1328 : 8473 : if (TREE_CODE (value) == ADDR_EXPR)
1329 : 7052 : addr_object_size (osi, value, object_size_type, &bytes, &wholesize);
1330 : : else
1331 : 1421 : bytes = wholesize = size_unknown (object_size_type);
1332 : :
1333 : 8473 : object_sizes_set (osi, varno, bytes, wholesize);
1334 : 8473 : }
1335 : :
1336 : :
1337 : : /* Compute object_sizes for PTR, defined to the result of a call. */
1338 : :
1339 : : static void
1340 : 1968 : call_object_size (struct object_size_info *osi, tree ptr, gcall *call)
1341 : : {
1342 : 1968 : int object_size_type = osi->object_size_type;
1343 : 1968 : unsigned int varno = SSA_NAME_VERSION (ptr);
1344 : 1968 : tree bytes = NULL_TREE;
1345 : :
1346 : 1968 : gcc_assert (is_gimple_call (call));
1347 : :
1348 : 1968 : gcc_assert (!object_sizes_unknown_p (object_size_type, varno));
1349 : 1968 : gcc_assert (osi->pass == 0);
1350 : :
1351 : 1968 : bool is_strdup = gimple_call_builtin_p (call, BUILT_IN_STRDUP);
1352 : 1968 : bool is_strndup = gimple_call_builtin_p (call, BUILT_IN_STRNDUP);
1353 : 1968 : if (is_strdup || is_strndup)
1354 : 160 : bytes = strdup_object_size (call, object_size_type, is_strndup);
1355 : : else
1356 : 1808 : bytes = alloc_object_size (call, object_size_type);
1357 : :
1358 : 1968 : if (!size_valid_p (bytes, object_size_type))
1359 : 369 : bytes = size_unknown (object_size_type);
1360 : :
1361 : 1968 : object_sizes_set (osi, varno, bytes, bytes);
1362 : 1968 : }
1363 : :
1364 : :
1365 : : /* Compute object_sizes for PTR, defined to an unknown value. */
1366 : :
1367 : : static void
1368 : 0 : unknown_object_size (struct object_size_info *osi, tree ptr)
1369 : : {
1370 : 0 : int object_size_type = osi->object_size_type;
1371 : 0 : unsigned int varno = SSA_NAME_VERSION (ptr);
1372 : :
1373 : 0 : gcc_checking_assert (!object_sizes_unknown_p (object_size_type, varno));
1374 : 0 : gcc_checking_assert (osi->pass == 0);
1375 : 0 : tree bytes = size_unknown (object_size_type);
1376 : :
1377 : 0 : object_sizes_set (osi, varno, bytes, bytes);
1378 : 0 : }
1379 : :
1380 : :
1381 : : /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
1382 : : the object size might need reexamination later. */
1383 : :
1384 : : static bool
1385 : 1880 : merge_object_sizes (struct object_size_info *osi, tree dest, tree orig)
1386 : : {
1387 : 1880 : int object_size_type = osi->object_size_type;
1388 : 1880 : unsigned int varno = SSA_NAME_VERSION (dest);
1389 : 1880 : tree orig_bytes, wholesize;
1390 : :
1391 : 1880 : if (object_sizes_unknown_p (object_size_type, varno))
1392 : : return false;
1393 : :
1394 : 1880 : if (osi->pass == 0)
1395 : 1274 : collect_object_sizes_for (osi, orig);
1396 : :
1397 : 1880 : orig_bytes = object_sizes_get (osi, SSA_NAME_VERSION (orig));
1398 : 1880 : wholesize = object_sizes_get (osi, SSA_NAME_VERSION (orig), true);
1399 : :
1400 : 1880 : if (object_sizes_set (osi, varno, orig_bytes, wholesize))
1401 : 967 : osi->changed = true;
1402 : :
1403 : 1880 : return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
1404 : : }
1405 : :
1406 : :
1407 : : /* Compute object_sizes for VAR, defined to the result of an assignment
1408 : : with operator POINTER_PLUS_EXPR. Return true if the object size might
1409 : : need reexamination later. */
1410 : :
1411 : : static bool
1412 : 917 : plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt)
1413 : : {
1414 : 917 : int object_size_type = osi->object_size_type;
1415 : 917 : unsigned int varno = SSA_NAME_VERSION (var);
1416 : 917 : tree bytes, wholesize;
1417 : 917 : tree op0, op1;
1418 : 917 : bool reexamine = false;
1419 : :
1420 : 917 : if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1421 : : {
1422 : 917 : op0 = gimple_assign_rhs1 (stmt);
1423 : 917 : op1 = gimple_assign_rhs2 (stmt);
1424 : : }
1425 : 0 : else if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
1426 : : {
1427 : 0 : tree rhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
1428 : 0 : gcc_assert (TREE_CODE (rhs) == MEM_REF);
1429 : 0 : op0 = TREE_OPERAND (rhs, 0);
1430 : 0 : op1 = TREE_OPERAND (rhs, 1);
1431 : : }
1432 : : else
1433 : 0 : gcc_unreachable ();
1434 : :
1435 : 917 : if (object_sizes_unknown_p (object_size_type, varno))
1436 : : return false;
1437 : :
1438 : : /* Handle PTR + OFFSET here. */
1439 : 917 : if (size_valid_p (op1, object_size_type)
1440 : 723 : && (TREE_CODE (op0) == SSA_NAME || TREE_CODE (op0) == ADDR_EXPR))
1441 : : {
1442 : 718 : if (TREE_CODE (op0) == SSA_NAME)
1443 : : {
1444 : 691 : if (osi->pass == 0)
1445 : 645 : collect_object_sizes_for (osi, op0);
1446 : :
1447 : 691 : bytes = object_sizes_get (osi, SSA_NAME_VERSION (op0));
1448 : 691 : wholesize = object_sizes_get (osi, SSA_NAME_VERSION (op0), true);
1449 : 691 : reexamine = bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (op0));
1450 : : }
1451 : : else
1452 : : {
1453 : : /* op0 will be ADDR_EXPR here. We should never come here during
1454 : : reexamination. */
1455 : 27 : gcc_checking_assert (osi->pass == 0);
1456 : 27 : addr_object_size (osi, op0, object_size_type, &bytes, &wholesize);
1457 : : }
1458 : :
1459 : : /* size_for_offset doesn't make sense for -1 size, but it does for size 0
1460 : : since the wholesize could be non-zero and a negative offset could give
1461 : : a non-zero size. */
1462 : 718 : if (size_unknown_p (bytes, 0))
1463 : : ;
1464 : 475 : else if ((object_size_type & OST_DYNAMIC)
1465 : 475 : || compare_tree_int (op1, offset_limit) <= 0)
1466 : 437 : bytes = size_for_offset (bytes, op1, wholesize);
1467 : : /* In the static case, with a negative offset, the best estimate for
1468 : : minimum size is size_unknown but for maximum size, the wholesize is a
1469 : : better estimate than size_unknown. */
1470 : 38 : else if (object_size_type & OST_MINIMUM)
1471 : 13 : bytes = size_unknown (object_size_type);
1472 : : else
1473 : 25 : bytes = wholesize;
1474 : : }
1475 : : else
1476 : 199 : bytes = wholesize = size_unknown (object_size_type);
1477 : :
1478 : 917 : if (!size_valid_p (bytes, object_size_type)
1479 : 917 : || !size_valid_p (wholesize, object_size_type))
1480 : 0 : bytes = wholesize = size_unknown (object_size_type);
1481 : :
1482 : 917 : if (object_sizes_set (osi, varno, bytes, wholesize))
1483 : 871 : osi->changed = true;
1484 : : return reexamine;
1485 : : }
1486 : :
1487 : : /* Compute the dynamic object size for VAR. Return the result in SIZE and
1488 : : WHOLESIZE. */
1489 : :
1490 : : static void
1491 : 303 : dynamic_object_size (struct object_size_info *osi, tree var,
1492 : : tree *size, tree *wholesize)
1493 : : {
1494 : 303 : int object_size_type = osi->object_size_type;
1495 : :
1496 : 303 : if (TREE_CODE (var) == SSA_NAME)
1497 : : {
1498 : 200 : unsigned varno = SSA_NAME_VERSION (var);
1499 : :
1500 : 200 : collect_object_sizes_for (osi, var);
1501 : 200 : *size = object_sizes_get (osi, varno);
1502 : 200 : *wholesize = object_sizes_get (osi, varno, true);
1503 : : }
1504 : 103 : else if (TREE_CODE (var) == ADDR_EXPR)
1505 : 102 : addr_object_size (osi, var, object_size_type, size, wholesize);
1506 : : else
1507 : 1 : *size = *wholesize = size_unknown (object_size_type);
1508 : 303 : }
1509 : :
1510 : : /* Compute object_sizes for VAR, defined at STMT, which is
1511 : : a COND_EXPR. Return true if the object size might need reexamination
1512 : : later. */
1513 : :
1514 : : static bool
1515 : 0 : cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt)
1516 : : {
1517 : 0 : tree then_, else_;
1518 : 0 : int object_size_type = osi->object_size_type;
1519 : 0 : unsigned int varno = SSA_NAME_VERSION (var);
1520 : 0 : bool reexamine = false;
1521 : :
1522 : 0 : gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR);
1523 : :
1524 : 0 : if (object_sizes_unknown_p (object_size_type, varno))
1525 : : return false;
1526 : :
1527 : 0 : then_ = gimple_assign_rhs2 (stmt);
1528 : 0 : else_ = gimple_assign_rhs3 (stmt);
1529 : :
1530 : 0 : if (object_size_type & OST_DYNAMIC)
1531 : : {
1532 : 0 : tree then_size, then_wholesize, else_size, else_wholesize;
1533 : :
1534 : 0 : dynamic_object_size (osi, then_, &then_size, &then_wholesize);
1535 : 0 : if (!size_unknown_p (then_size, object_size_type))
1536 : 0 : dynamic_object_size (osi, else_, &else_size, &else_wholesize);
1537 : :
1538 : 0 : tree cond_size, cond_wholesize;
1539 : 0 : if (size_unknown_p (then_size, object_size_type)
1540 : 0 : || size_unknown_p (else_size, object_size_type))
1541 : 0 : cond_size = cond_wholesize = size_unknown (object_size_type);
1542 : : else
1543 : : {
1544 : 0 : cond_size = fold_build3 (COND_EXPR, sizetype,
1545 : : gimple_assign_rhs1 (stmt),
1546 : : then_size, else_size);
1547 : 0 : cond_wholesize = fold_build3 (COND_EXPR, sizetype,
1548 : : gimple_assign_rhs1 (stmt),
1549 : : then_wholesize, else_wholesize);
1550 : : }
1551 : :
1552 : 0 : object_sizes_set (osi, varno, cond_size, cond_wholesize);
1553 : :
1554 : 0 : return false;
1555 : : }
1556 : :
1557 : 0 : if (TREE_CODE (then_) == SSA_NAME)
1558 : 0 : reexamine |= merge_object_sizes (osi, var, then_);
1559 : : else
1560 : 0 : expr_object_size (osi, var, then_);
1561 : :
1562 : 0 : if (object_sizes_unknown_p (object_size_type, varno))
1563 : : return reexamine;
1564 : :
1565 : 0 : if (TREE_CODE (else_) == SSA_NAME)
1566 : 0 : reexamine |= merge_object_sizes (osi, var, else_);
1567 : : else
1568 : 0 : expr_object_size (osi, var, else_);
1569 : :
1570 : : return reexamine;
1571 : : }
1572 : :
1573 : : /* Find size of an object passed as a parameter to the function. */
1574 : :
1575 : : static void
1576 : 1544 : parm_object_size (struct object_size_info *osi, tree var)
1577 : : {
1578 : 1544 : int object_size_type = osi->object_size_type;
1579 : 1544 : tree parm = SSA_NAME_VAR (var);
1580 : :
1581 : 1544 : if (!(object_size_type & OST_DYNAMIC) || !POINTER_TYPE_P (TREE_TYPE (parm)))
1582 : : {
1583 : 1092 : expr_object_size (osi, var, parm);
1584 : 1092 : return;
1585 : : }
1586 : :
1587 : : /* Look for access attribute. */
1588 : 452 : rdwr_map rdwr_idx;
1589 : :
1590 : 452 : tree fndecl = cfun->decl;
1591 : 452 : const attr_access *access = get_parm_access (rdwr_idx, parm, fndecl);
1592 : 452 : tree typesize = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (parm)));
1593 : 452 : tree sz = NULL_TREE;
1594 : :
1595 : : /* If we have an access attribute with a usable size argument... */
1596 : 18 : if (access && access->sizarg != UINT_MAX
1597 : : /* ... and either PARM is void * or has a type that is complete and has a
1598 : : constant size... */
1599 : 468 : && ((typesize && poly_int_tree_p (typesize))
1600 : 4 : || (!typesize && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (parm))))))
1601 : : {
1602 : 11 : tree fnargs = DECL_ARGUMENTS (fndecl);
1603 : 11 : tree arg = NULL_TREE;
1604 : 11 : unsigned argpos = 0;
1605 : :
1606 : : /* ... then walk through the parameters to pick the size parameter and
1607 : : safely scale it by the type size if needed.
1608 : :
1609 : : TODO: we could also compute the size of VLAs where the size is
1610 : : given by a function parameter. */
1611 : 18 : for (arg = fnargs; arg; arg = TREE_CHAIN (arg), ++argpos)
1612 : 18 : if (argpos == access->sizarg)
1613 : : {
1614 : 11 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (arg)));
1615 : 11 : sz = get_or_create_ssa_default_def (cfun, arg);
1616 : 11 : if (sz != NULL_TREE)
1617 : : {
1618 : 11 : sz = fold_convert (sizetype, sz);
1619 : 11 : if (typesize)
1620 : 8 : sz = size_binop (MULT_EXPR, sz, typesize);
1621 : : }
1622 : : break;
1623 : : }
1624 : : }
1625 : 11 : if (!sz)
1626 : 441 : sz = size_unknown (object_size_type);
1627 : :
1628 : 452 : object_sizes_set (osi, SSA_NAME_VERSION (var), sz, sz);
1629 : 452 : }
1630 : :
1631 : : /* Compute an object size expression for VAR, which is the result of a PHI
1632 : : node. */
1633 : :
1634 : : static void
1635 : 154 : phi_dynamic_object_size (struct object_size_info *osi, tree var)
1636 : : {
1637 : 154 : int object_size_type = osi->object_size_type;
1638 : 154 : unsigned int varno = SSA_NAME_VERSION (var);
1639 : 154 : gimple *stmt = SSA_NAME_DEF_STMT (var);
1640 : 154 : unsigned i, num_args = gimple_phi_num_args (stmt);
1641 : 154 : bool wholesize_needed = false;
1642 : :
1643 : : /* The extra space is for the PHI result at the end, which object_sizes_set
1644 : : sets for us. */
1645 : 154 : tree sizes = make_tree_vec (num_args + 1);
1646 : 154 : tree wholesizes = make_tree_vec (num_args + 1);
1647 : :
1648 : : /* Bail out if the size of any of the PHI arguments cannot be
1649 : : determined. */
1650 : 424 : for (i = 0; i < num_args; i++)
1651 : : {
1652 : 308 : edge e = gimple_phi_arg_edge (as_a <gphi *> (stmt), i);
1653 : 308 : if (e->flags & EDGE_COMPLEX)
1654 : : break;
1655 : :
1656 : 303 : tree rhs = gimple_phi_arg_def (stmt, i);
1657 : 303 : tree size, wholesize;
1658 : :
1659 : 303 : dynamic_object_size (osi, rhs, &size, &wholesize);
1660 : :
1661 : 303 : if (size_unknown_p (size, object_size_type))
1662 : : break;
1663 : :
1664 : 270 : if (size != wholesize)
1665 : 215 : wholesize_needed = true;
1666 : :
1667 : 270 : TREE_VEC_ELT (sizes, i) = size;
1668 : 270 : TREE_VEC_ELT (wholesizes, i) = wholesize;
1669 : : }
1670 : :
1671 : 154 : if (i < num_args)
1672 : : {
1673 : 38 : ggc_free (sizes);
1674 : 38 : ggc_free (wholesizes);
1675 : 38 : sizes = wholesizes = size_unknown (object_size_type);
1676 : : }
1677 : :
1678 : : /* Point to the same TREE_VEC so that we can avoid emitting two PHI
1679 : : nodes. */
1680 : 116 : else if (!wholesize_needed)
1681 : : {
1682 : 13 : ggc_free (wholesizes);
1683 : 13 : wholesizes = sizes;
1684 : : }
1685 : :
1686 : 154 : object_sizes_set (osi, varno, sizes, wholesizes);
1687 : 154 : }
1688 : :
1689 : : /* Compute object sizes for VAR.
1690 : : For ADDR_EXPR an object size is the number of remaining bytes
1691 : : to the end of the object (where what is considered an object depends on
1692 : : OSI->object_size_type).
1693 : : For allocation GIMPLE_CALL like malloc or calloc object size is the size
1694 : : of the allocation.
1695 : : For POINTER_PLUS_EXPR where second operand is a constant integer,
1696 : : object size is object size of the first operand minus the constant.
1697 : : If the constant is bigger than the number of remaining bytes until the
1698 : : end of the object, object size is 0, but if it is instead a pointer
1699 : : subtraction, object size is size_unknown (object_size_type).
1700 : : To differentiate addition from subtraction, ADDR_EXPR returns
1701 : : size_unknown (object_size_type) for all objects bigger than half of the
1702 : : address space, and constants less than half of the address space are
1703 : : considered addition, while bigger constants subtraction.
1704 : : For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
1705 : : object size is object size of that argument.
1706 : : Otherwise, object size is the maximum of object sizes of variables
1707 : : that it might be set to. */
1708 : :
1709 : : static void
1710 : 13682 : collect_object_sizes_for (struct object_size_info *osi, tree var)
1711 : : {
1712 : 13682 : int object_size_type = osi->object_size_type;
1713 : 13682 : unsigned int varno = SSA_NAME_VERSION (var);
1714 : 13682 : gimple *stmt;
1715 : 13682 : bool reexamine;
1716 : :
1717 : 13682 : if (bitmap_bit_p (computed[object_size_type], varno))
1718 : : return;
1719 : :
1720 : 12450 : if (osi->pass == 0)
1721 : : {
1722 : 11871 : if (bitmap_set_bit (osi->visited, varno))
1723 : : {
1724 : : /* Initialize to 0 for maximum size and M1U for minimum size so that
1725 : : it gets immediately overridden. */
1726 : 11516 : object_sizes_initialize (osi, varno,
1727 : : size_initval (object_size_type),
1728 : : size_initval (object_size_type));
1729 : : }
1730 : : else
1731 : : {
1732 : : /* Found a dependency loop. Mark the variable for later
1733 : : re-examination. */
1734 : 355 : if (object_size_type & OST_DYNAMIC)
1735 : 70 : object_sizes_set_temp (osi, varno);
1736 : :
1737 : 355 : bitmap_set_bit (osi->reexamine, varno);
1738 : 355 : if (dump_file && (dump_flags & TDF_DETAILS))
1739 : : {
1740 : 0 : fprintf (dump_file, "Found a dependency loop at ");
1741 : 0 : print_generic_expr (dump_file, var, dump_flags);
1742 : 0 : fprintf (dump_file, "\n");
1743 : : }
1744 : 355 : return;
1745 : : }
1746 : : }
1747 : :
1748 : 12095 : if (dump_file && (dump_flags & TDF_DETAILS))
1749 : : {
1750 : 6 : fprintf (dump_file, "Visiting use-def links for ");
1751 : 6 : print_generic_expr (dump_file, var, dump_flags);
1752 : 6 : fprintf (dump_file, "\n");
1753 : : }
1754 : :
1755 : 12095 : stmt = SSA_NAME_DEF_STMT (var);
1756 : 12095 : reexamine = false;
1757 : :
1758 : 12095 : switch (gimple_code (stmt))
1759 : : {
1760 : 6800 : case GIMPLE_ASSIGN:
1761 : 6800 : {
1762 : 6800 : tree rhs = gimple_assign_rhs1 (stmt);
1763 : 6800 : if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
1764 : 6800 : || (gimple_assign_rhs_code (stmt) == ADDR_EXPR
1765 : 5328 : && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF))
1766 : 917 : reexamine = plus_stmt_object_size (osi, var, stmt);
1767 : 5883 : else if (gimple_assign_rhs_code (stmt) == COND_EXPR)
1768 : 0 : reexamine = cond_expr_object_size (osi, var, stmt);
1769 : 5883 : else if (gimple_assign_single_p (stmt)
1770 : 5883 : || gimple_assign_unary_nop_p (stmt))
1771 : : {
1772 : 5883 : if (TREE_CODE (rhs) == SSA_NAME
1773 : 5883 : && POINTER_TYPE_P (TREE_TYPE (rhs)))
1774 : 227 : reexamine = merge_object_sizes (osi, var, rhs);
1775 : : else
1776 : 5656 : expr_object_size (osi, var, rhs);
1777 : : }
1778 : : else
1779 : 0 : unknown_object_size (osi, var);
1780 : : break;
1781 : : }
1782 : :
1783 : 2043 : case GIMPLE_CALL:
1784 : 2043 : {
1785 : 2043 : gcall *call_stmt = as_a <gcall *> (stmt);
1786 : 2043 : tree arg = pass_through_call (call_stmt);
1787 : 2043 : if (arg)
1788 : : {
1789 : 75 : if (TREE_CODE (arg) == SSA_NAME
1790 : 75 : && POINTER_TYPE_P (TREE_TYPE (arg)))
1791 : 58 : reexamine = merge_object_sizes (osi, var, arg);
1792 : : else
1793 : 17 : expr_object_size (osi, var, arg);
1794 : : }
1795 : : else
1796 : 1968 : call_object_size (osi, var, call_stmt);
1797 : : break;
1798 : : }
1799 : :
1800 : 0 : case GIMPLE_ASM:
1801 : : /* Pointers defined by __asm__ statements can point anywhere. */
1802 : 0 : unknown_object_size (osi, var);
1803 : 0 : break;
1804 : :
1805 : 1544 : case GIMPLE_NOP:
1806 : 1544 : if (SSA_NAME_VAR (var)
1807 : 1544 : && TREE_CODE (SSA_NAME_VAR (var)) == PARM_DECL)
1808 : 1544 : parm_object_size (osi, var);
1809 : : else
1810 : : /* Uninitialized SSA names point nowhere. */
1811 : 0 : unknown_object_size (osi, var);
1812 : : break;
1813 : :
1814 : 1708 : case GIMPLE_PHI:
1815 : 1708 : {
1816 : 1708 : unsigned i;
1817 : :
1818 : 1708 : if (object_size_type & OST_DYNAMIC)
1819 : : {
1820 : 154 : phi_dynamic_object_size (osi, var);
1821 : 154 : break;
1822 : : }
1823 : :
1824 : 6007 : for (i = 0; i < gimple_phi_num_args (stmt); i++)
1825 : : {
1826 : 4512 : tree rhs = gimple_phi_arg (stmt, i)->def;
1827 : :
1828 : 4512 : if (object_sizes_unknown_p (object_size_type, varno))
1829 : : break;
1830 : :
1831 : 4453 : if (TREE_CODE (rhs) == SSA_NAME)
1832 : 1595 : reexamine |= merge_object_sizes (osi, var, rhs);
1833 : 2858 : else if (osi->pass == 0)
1834 : 1708 : expr_object_size (osi, var, rhs);
1835 : : }
1836 : : break;
1837 : : }
1838 : :
1839 : 0 : default:
1840 : 0 : gcc_unreachable ();
1841 : : }
1842 : :
1843 : : /* Dynamic sizes use placeholder temps to return an answer, so it is always
1844 : : safe to set COMPUTED for them. */
1845 : 12095 : if ((object_size_type & OST_DYNAMIC)
1846 : 12095 : || !reexamine || object_sizes_unknown_p (object_size_type, varno))
1847 : : {
1848 : 10967 : bitmap_set_bit (computed[object_size_type], varno);
1849 : 10967 : if (!(object_size_type & OST_DYNAMIC))
1850 : 8281 : bitmap_clear_bit (osi->reexamine, varno);
1851 : 2686 : else if (reexamine)
1852 : 74 : bitmap_set_bit (osi->reexamine, varno);
1853 : : }
1854 : : else
1855 : : {
1856 : 1128 : bitmap_set_bit (osi->reexamine, varno);
1857 : 1128 : if (dump_file && (dump_flags & TDF_DETAILS))
1858 : : {
1859 : 0 : fprintf (dump_file, "Need to reexamine ");
1860 : 0 : print_generic_expr (dump_file, var, dump_flags);
1861 : 0 : fprintf (dump_file, "\n");
1862 : : }
1863 : : }
1864 : : }
1865 : :
1866 : :
1867 : : /* Helper function for check_for_plus_in_loops. Called recursively
1868 : : to detect loops. */
1869 : :
1870 : : static void
1871 : 20 : check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
1872 : : unsigned int depth)
1873 : : {
1874 : 20 : gimple *stmt = SSA_NAME_DEF_STMT (var);
1875 : 20 : unsigned int varno = SSA_NAME_VERSION (var);
1876 : :
1877 : 20 : if (osi->depths[varno])
1878 : : {
1879 : 10 : if (osi->depths[varno] != depth)
1880 : : {
1881 : 10 : unsigned int *sp;
1882 : :
1883 : : /* Found a loop involving pointer addition. */
1884 : 20 : for (sp = osi->tos; sp > osi->stack; )
1885 : : {
1886 : 20 : --sp;
1887 : 20 : bitmap_clear_bit (osi->reexamine, *sp);
1888 : 20 : bitmap_set_bit (computed[osi->object_size_type], *sp);
1889 : 20 : object_sizes_set (osi, *sp, size_zero_node,
1890 : : object_sizes_get (osi, *sp, true));
1891 : 20 : if (*sp == varno)
1892 : : break;
1893 : : }
1894 : : }
1895 : 10 : return;
1896 : : }
1897 : 10 : else if (! bitmap_bit_p (osi->reexamine, varno))
1898 : : return;
1899 : :
1900 : 10 : osi->depths[varno] = depth;
1901 : 10 : *osi->tos++ = varno;
1902 : :
1903 : 10 : switch (gimple_code (stmt))
1904 : : {
1905 : :
1906 : 10 : case GIMPLE_ASSIGN:
1907 : 10 : {
1908 : 10 : if ((gimple_assign_single_p (stmt)
1909 : 10 : || gimple_assign_unary_nop_p (stmt))
1910 : 10 : && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
1911 : : {
1912 : 0 : tree rhs = gimple_assign_rhs1 (stmt);
1913 : :
1914 : 0 : check_for_plus_in_loops_1 (osi, rhs, depth);
1915 : : }
1916 : 10 : else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1917 : : {
1918 : 10 : tree basevar = gimple_assign_rhs1 (stmt);
1919 : 10 : tree cst = gimple_assign_rhs2 (stmt);
1920 : :
1921 : 10 : gcc_assert (TREE_CODE (cst) == INTEGER_CST);
1922 : :
1923 : 20 : check_for_plus_in_loops_1 (osi, basevar,
1924 : 10 : depth + !integer_zerop (cst));
1925 : : }
1926 : : else
1927 : 0 : gcc_unreachable ();
1928 : : break;
1929 : : }
1930 : :
1931 : 0 : case GIMPLE_CALL:
1932 : 0 : {
1933 : 0 : gcall *call_stmt = as_a <gcall *> (stmt);
1934 : 0 : tree arg = pass_through_call (call_stmt);
1935 : 0 : if (arg)
1936 : : {
1937 : 0 : if (TREE_CODE (arg) == SSA_NAME)
1938 : 0 : check_for_plus_in_loops_1 (osi, arg, depth);
1939 : : else
1940 : 0 : gcc_unreachable ();
1941 : : }
1942 : : break;
1943 : : }
1944 : :
1945 : : case GIMPLE_PHI:
1946 : : {
1947 : : unsigned i;
1948 : :
1949 : 0 : for (i = 0; i < gimple_phi_num_args (stmt); i++)
1950 : : {
1951 : 0 : tree rhs = gimple_phi_arg (stmt, i)->def;
1952 : :
1953 : 0 : if (TREE_CODE (rhs) == SSA_NAME)
1954 : 0 : check_for_plus_in_loops_1 (osi, rhs, depth);
1955 : : }
1956 : : break;
1957 : : }
1958 : :
1959 : 0 : default:
1960 : 0 : gcc_unreachable ();
1961 : : }
1962 : :
1963 : 10 : osi->depths[varno] = 0;
1964 : 10 : osi->tos--;
1965 : : }
1966 : :
1967 : :
1968 : : /* Check if some pointer we are computing object size of is being increased
1969 : : within a loop. If yes, assume all the SSA variables participating in
1970 : : that loop have minimum object sizes 0. */
1971 : :
1972 : : static void
1973 : 38 : check_for_plus_in_loops (struct object_size_info *osi, tree var)
1974 : : {
1975 : 38 : gimple *stmt = SSA_NAME_DEF_STMT (var);
1976 : :
1977 : : /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
1978 : : and looked for a POINTER_PLUS_EXPR in the pass-through
1979 : : argument, if any. In GIMPLE, however, such an expression
1980 : : is not a valid call operand. */
1981 : :
1982 : 38 : if (is_gimple_assign (stmt)
1983 : 38 : && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1984 : : {
1985 : 10 : tree basevar = gimple_assign_rhs1 (stmt);
1986 : 10 : tree cst = gimple_assign_rhs2 (stmt);
1987 : :
1988 : 10 : gcc_assert (TREE_CODE (cst) == INTEGER_CST);
1989 : :
1990 : : /* Skip non-positive offsets. */
1991 : 10 : if (integer_zerop (cst) || compare_tree_int (cst, offset_limit) > 0)
1992 : 0 : return;
1993 : :
1994 : 10 : osi->depths[SSA_NAME_VERSION (basevar)] = 1;
1995 : 10 : *osi->tos++ = SSA_NAME_VERSION (basevar);
1996 : 10 : check_for_plus_in_loops_1 (osi, var, 2);
1997 : 10 : osi->depths[SSA_NAME_VERSION (basevar)] = 0;
1998 : 10 : osi->tos--;
1999 : : }
2000 : : }
2001 : :
2002 : :
2003 : : /* Initialize data structures for the object size computation. */
2004 : :
2005 : : void
2006 : 18753 : init_object_sizes (void)
2007 : : {
2008 : 18753 : int object_size_type;
2009 : :
2010 : 18753 : if (computed[0])
2011 : : return;
2012 : :
2013 : 22653 : for (object_size_type = 0; object_size_type < OST_END; object_size_type++)
2014 : : {
2015 : 20136 : object_sizes_grow (object_size_type);
2016 : 20136 : computed[object_size_type] = BITMAP_ALLOC (NULL);
2017 : : }
2018 : :
2019 : 2517 : init_offset_limit ();
2020 : : }
2021 : :
2022 : :
2023 : : /* Destroy data structures after the object size computation. */
2024 : :
2025 : : void
2026 : 3213403 : fini_object_sizes (void)
2027 : : {
2028 : 3213403 : int object_size_type;
2029 : :
2030 : 28920627 : for (object_size_type = 0; object_size_type < OST_END; object_size_type++)
2031 : : {
2032 : 25707224 : object_sizes_release (object_size_type);
2033 : 25707224 : BITMAP_FREE (computed[object_size_type]);
2034 : : }
2035 : 3213403 : }
2036 : :
2037 : : /* Dummy valueize function. */
2038 : :
2039 : : static tree
2040 : 17869 : do_valueize (tree t)
2041 : : {
2042 : 17869 : return t;
2043 : : }
2044 : :
2045 : : /* Process a __builtin_object_size or __builtin_dynamic_object_size call in
2046 : : CALL early for subobjects before any object information is lost due to
2047 : : optimization. Insert a MIN or MAX expression of the result and
2048 : : __builtin_object_size at I so that it may be processed in the second pass.
2049 : : __builtin_dynamic_object_size is treated like __builtin_object_size here
2050 : : since we're only looking for constant bounds. */
2051 : :
2052 : : static void
2053 : 11969 : early_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call)
2054 : : {
2055 : 11969 : tree ost = gimple_call_arg (call, 1);
2056 : 11969 : tree lhs = gimple_call_lhs (call);
2057 : 11969 : gcc_assert (lhs != NULL_TREE);
2058 : :
2059 : 11969 : if (!tree_fits_uhwi_p (ost))
2060 : 9840 : return;
2061 : :
2062 : 11969 : unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
2063 : 11969 : tree ptr = gimple_call_arg (call, 0);
2064 : :
2065 : 11969 : if (object_size_type != 1 && object_size_type != 3)
2066 : : return;
2067 : :
2068 : 3870 : if (TREE_CODE (ptr) != ADDR_EXPR && TREE_CODE (ptr) != SSA_NAME)
2069 : : return;
2070 : :
2071 : 3870 : tree type = TREE_TYPE (lhs);
2072 : 3870 : tree bytes;
2073 : 3870 : if (!compute_builtin_object_size (ptr, object_size_type, &bytes)
2074 : 3870 : || !int_fits_type_p (bytes, type))
2075 : : return;
2076 : :
2077 : 2129 : tree tem = make_ssa_name (type);
2078 : 2129 : gimple_call_set_lhs (call, tem);
2079 : 2129 : enum tree_code code = object_size_type & OST_MINIMUM ? MAX_EXPR : MIN_EXPR;
2080 : 2129 : tree cst = fold_convert (type, bytes);
2081 : 2129 : gimple *g = gimple_build_assign (lhs, code, tem, cst);
2082 : 2129 : gsi_insert_after (i, g, GSI_NEW_STMT);
2083 : 2129 : update_stmt (call);
2084 : : }
2085 : :
2086 : : /* Attempt to fold one __builtin_dynamic_object_size call in CALL into an
2087 : : expression and insert it at I. Return true if it succeeds. */
2088 : :
2089 : : static bool
2090 : 3435 : dynamic_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call)
2091 : : {
2092 : 3435 : gcc_assert (gimple_call_num_args (call) == 2);
2093 : :
2094 : 3435 : tree args[2];
2095 : 3435 : args[0] = gimple_call_arg (call, 0);
2096 : 3435 : args[1] = gimple_call_arg (call, 1);
2097 : :
2098 : 3435 : location_t loc = EXPR_LOC_OR_LOC (args[0], input_location);
2099 : 3435 : tree result_type = gimple_call_return_type (as_a <gcall *> (call));
2100 : 3435 : tree result = fold_builtin_call_array (loc, result_type,
2101 : : gimple_call_fn (call), 2, args);
2102 : :
2103 : 3435 : if (!result)
2104 : : return false;
2105 : :
2106 : : /* fold_builtin_call_array may wrap the result inside a
2107 : : NOP_EXPR. */
2108 : 2312 : STRIP_NOPS (result);
2109 : 2312 : gimplify_and_update_call_from_tree (i, result);
2110 : :
2111 : 2312 : if (dump_file && (dump_flags & TDF_DETAILS))
2112 : : {
2113 : 0 : fprintf (dump_file, "Simplified (dynamic)\n ");
2114 : 0 : print_gimple_stmt (dump_file, call, 0, dump_flags);
2115 : 0 : fprintf (dump_file, " to ");
2116 : 0 : print_generic_expr (dump_file, result);
2117 : 0 : fprintf (dump_file, "\n");
2118 : : }
2119 : : return true;
2120 : : }
2121 : :
2122 : : static unsigned int
2123 : 3213403 : object_sizes_execute (function *fun, bool early)
2124 : : {
2125 : 3213403 : todo = 0;
2126 : :
2127 : 3213403 : basic_block bb;
2128 : 26602732 : FOR_EACH_BB_FN (bb, fun)
2129 : : {
2130 : 23389329 : gimple_stmt_iterator i;
2131 : 197406489 : for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
2132 : : {
2133 : 150627831 : tree result;
2134 : 150627831 : bool dynamic = false;
2135 : :
2136 : 150627831 : gimple *call = gsi_stmt (i);
2137 : 150627831 : if (gimple_call_builtin_p (call, BUILT_IN_DYNAMIC_OBJECT_SIZE))
2138 : : dynamic = true;
2139 : 150619994 : else if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE))
2140 : 150609078 : continue;
2141 : :
2142 : 18753 : tree lhs = gimple_call_lhs (call);
2143 : 18753 : if (!lhs)
2144 : 0 : continue;
2145 : :
2146 : 18753 : init_object_sizes ();
2147 : :
2148 : : /* If early, only attempt to fold
2149 : : __builtin_object_size (x, 1) and __builtin_object_size (x, 3),
2150 : : and rather than folding the builtin to the constant if any,
2151 : : create a MIN_EXPR or MAX_EXPR of the __builtin_object_size
2152 : : call result and the computed constant. Do the same for
2153 : : __builtin_dynamic_object_size too. */
2154 : 18753 : if (early)
2155 : : {
2156 : 11969 : early_object_sizes_execute_one (&i, call);
2157 : 11969 : continue;
2158 : : }
2159 : :
2160 : 6784 : if (dynamic)
2161 : : {
2162 : 3435 : if (dynamic_object_sizes_execute_one (&i, call))
2163 : 2312 : continue;
2164 : : else
2165 : : {
2166 : : /* If we could not find a suitable size expression, lower to
2167 : : __builtin_object_size so that we may at least get a
2168 : : constant lower or higher estimate. */
2169 : 1123 : tree bosfn = builtin_decl_implicit (BUILT_IN_OBJECT_SIZE);
2170 : 1123 : gimple_call_set_fndecl (call, bosfn);
2171 : 1123 : update_stmt (call);
2172 : :
2173 : 1123 : if (dump_file && (dump_flags & TDF_DETAILS))
2174 : : {
2175 : 0 : print_generic_expr (dump_file, gimple_call_arg (call, 0),
2176 : : dump_flags);
2177 : 0 : fprintf (dump_file,
2178 : : ": Retrying as __builtin_object_size\n");
2179 : : }
2180 : : }
2181 : : }
2182 : :
2183 : 4472 : result = gimple_fold_stmt_to_constant (call, do_valueize);
2184 : 4472 : if (!result)
2185 : : {
2186 : 2242 : tree ost = gimple_call_arg (call, 1);
2187 : :
2188 : 2242 : if (tree_fits_uhwi_p (ost))
2189 : : {
2190 : 2242 : unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
2191 : :
2192 : 2242 : if (object_size_type & OST_MINIMUM)
2193 : 360 : result = build_zero_cst (size_type_node);
2194 : 1882 : else if (object_size_type < OST_END)
2195 : 1882 : result = fold_convert (size_type_node,
2196 : : integer_minus_one_node);
2197 : : }
2198 : :
2199 : 2242 : if (!result)
2200 : 0 : continue;
2201 : : }
2202 : :
2203 : 4472 : gcc_assert (TREE_CODE (result) == INTEGER_CST);
2204 : :
2205 : 4472 : if (dump_file && (dump_flags & TDF_DETAILS))
2206 : : {
2207 : 0 : fprintf (dump_file, "Simplified\n ");
2208 : 0 : print_gimple_stmt (dump_file, call, 0, dump_flags);
2209 : 0 : fprintf (dump_file, " to ");
2210 : 0 : print_generic_expr (dump_file, result);
2211 : 0 : fprintf (dump_file, "\n");
2212 : : }
2213 : :
2214 : : /* Propagate into all uses and fold those stmts. */
2215 : 4472 : if (!SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
2216 : 4472 : replace_uses_by (lhs, result);
2217 : : else
2218 : 0 : replace_call_with_value (&i, result);
2219 : : }
2220 : : }
2221 : :
2222 : 3213403 : fini_object_sizes ();
2223 : 3213403 : return todo;
2224 : : }
2225 : :
2226 : : /* Simple pass to optimize all __builtin_object_size () builtins. */
2227 : :
2228 : : namespace {
2229 : :
2230 : : const pass_data pass_data_object_sizes =
2231 : : {
2232 : : GIMPLE_PASS, /* type */
2233 : : "objsz", /* name */
2234 : : OPTGROUP_NONE, /* optinfo_flags */
2235 : : TV_NONE, /* tv_id */
2236 : : ( PROP_cfg | PROP_ssa ), /* properties_required */
2237 : : PROP_objsz, /* properties_provided */
2238 : : 0, /* properties_destroyed */
2239 : : 0, /* todo_flags_start */
2240 : : 0, /* todo_flags_finish */
2241 : : };
2242 : :
2243 : : class pass_object_sizes : public gimple_opt_pass
2244 : : {
2245 : : public:
2246 : 563828 : pass_object_sizes (gcc::context *ctxt)
2247 : 1127656 : : gimple_opt_pass (pass_data_object_sizes, ctxt)
2248 : : {}
2249 : :
2250 : : /* opt_pass methods: */
2251 : 281914 : opt_pass * clone () final override { return new pass_object_sizes (m_ctxt); }
2252 : 988045 : unsigned int execute (function *fun) final override
2253 : : {
2254 : 988045 : return object_sizes_execute (fun, false);
2255 : : }
2256 : : }; // class pass_object_sizes
2257 : :
2258 : : } // anon namespace
2259 : :
2260 : : gimple_opt_pass *
2261 : 281914 : make_pass_object_sizes (gcc::context *ctxt)
2262 : : {
2263 : 281914 : return new pass_object_sizes (ctxt);
2264 : : }
2265 : :
2266 : : /* Early version of pass to optimize all __builtin_object_size () builtins. */
2267 : :
2268 : : namespace {
2269 : :
2270 : : const pass_data pass_data_early_object_sizes =
2271 : : {
2272 : : GIMPLE_PASS, /* type */
2273 : : "early_objsz", /* name */
2274 : : OPTGROUP_NONE, /* optinfo_flags */
2275 : : TV_NONE, /* tv_id */
2276 : : ( PROP_cfg | PROP_ssa ), /* properties_required */
2277 : : 0, /* properties_provided */
2278 : : 0, /* properties_destroyed */
2279 : : 0, /* todo_flags_start */
2280 : : 0, /* todo_flags_finish */
2281 : : };
2282 : :
2283 : : class pass_early_object_sizes : public gimple_opt_pass
2284 : : {
2285 : : public:
2286 : 281914 : pass_early_object_sizes (gcc::context *ctxt)
2287 : 563828 : : gimple_opt_pass (pass_data_early_object_sizes, ctxt)
2288 : : {}
2289 : :
2290 : : /* opt_pass methods: */
2291 : 2225358 : unsigned int execute (function *fun) final override
2292 : : {
2293 : 2225358 : return object_sizes_execute (fun, true);
2294 : : }
2295 : : }; // class pass_object_sizes
2296 : :
2297 : : } // anon namespace
2298 : :
2299 : : gimple_opt_pass *
2300 : 281914 : make_pass_early_object_sizes (gcc::context *ctxt)
2301 : : {
2302 : 281914 : return new pass_early_object_sizes (ctxt);
2303 : : }
|