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