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