OSDN Git Service

PR tree-optimization/50596
[pf3gnuchains/gcc-fork.git] / gcc / tree-object-size.c
1 /* __builtin_object_size (ptr, object_size_type) computation
2    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
3    Free Software Foundation, Inc.
4    Contributed by Jakub Jelinek <jakub@redhat.com>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "diagnostic-core.h"
28 #include "tree-pretty-print.h"
29 #include "gimple-pretty-print.h"
30 #include "tree-flow.h"
31 #include "tree-pass.h"
32 #include "tree-ssa-propagate.h"
33
34 struct object_size_info
35 {
36   int object_size_type;
37   bitmap visited, reexamine;
38   int pass;
39   bool changed;
40   unsigned int *depths;
41   unsigned int *stack, *tos;
42 };
43
44 static unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 };
45
46 static tree compute_object_offset (const_tree, const_tree);
47 static unsigned HOST_WIDE_INT addr_object_size (struct object_size_info *,
48                                                 const_tree, int);
49 static unsigned HOST_WIDE_INT alloc_object_size (const_gimple, int);
50 static tree pass_through_call (const_gimple);
51 static void collect_object_sizes_for (struct object_size_info *, tree);
52 static void expr_object_size (struct object_size_info *, tree, tree);
53 static bool merge_object_sizes (struct object_size_info *, tree, tree,
54                                 unsigned HOST_WIDE_INT);
55 static bool plus_stmt_object_size (struct object_size_info *, tree, gimple);
56 static bool cond_expr_object_size (struct object_size_info *, tree, gimple);
57 static unsigned int compute_object_sizes (void);
58 static void init_offset_limit (void);
59 static void check_for_plus_in_loops (struct object_size_info *, tree);
60 static void check_for_plus_in_loops_1 (struct object_size_info *, tree,
61                                        unsigned int);
62
63 /* object_sizes[0] is upper bound for number of bytes till the end of
64    the object.
65    object_sizes[1] is upper bound for number of bytes till the end of
66    the subobject (innermost array or field with address taken).
67    object_sizes[2] is lower bound for number of bytes till the end of
68    the object and object_sizes[3] lower bound for subobject.  */
69 static unsigned HOST_WIDE_INT *object_sizes[4];
70
71 /* Bitmaps what object sizes have been computed already.  */
72 static bitmap computed[4];
73
74 /* Maximum value of offset we consider to be addition.  */
75 static unsigned HOST_WIDE_INT offset_limit;
76
77
78 /* Initialize OFFSET_LIMIT variable.  */
79 static void
80 init_offset_limit (void)
81 {
82   if (host_integerp (TYPE_MAX_VALUE (sizetype), 1))
83     offset_limit = tree_low_cst (TYPE_MAX_VALUE (sizetype), 1);
84   else
85     offset_limit = -1;
86   offset_limit /= 2;
87 }
88
89
90 /* Compute offset of EXPR within VAR.  Return error_mark_node
91    if unknown.  */
92
93 static tree
94 compute_object_offset (const_tree expr, const_tree var)
95 {
96   enum tree_code code = PLUS_EXPR;
97   tree base, off, t;
98
99   if (expr == var)
100     return size_zero_node;
101
102   switch (TREE_CODE (expr))
103     {
104     case COMPONENT_REF:
105       base = compute_object_offset (TREE_OPERAND (expr, 0), var);
106       if (base == error_mark_node)
107         return base;
108
109       t = TREE_OPERAND (expr, 1);
110       off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
111                         size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
112                                   / BITS_PER_UNIT));
113       break;
114
115     case REALPART_EXPR:
116     CASE_CONVERT:
117     case VIEW_CONVERT_EXPR:
118     case NON_LVALUE_EXPR:
119       return compute_object_offset (TREE_OPERAND (expr, 0), var);
120
121     case IMAGPART_EXPR:
122       base = compute_object_offset (TREE_OPERAND (expr, 0), var);
123       if (base == error_mark_node)
124         return base;
125
126       off = TYPE_SIZE_UNIT (TREE_TYPE (expr));
127       break;
128
129     case ARRAY_REF:
130       base = compute_object_offset (TREE_OPERAND (expr, 0), var);
131       if (base == error_mark_node)
132         return base;
133
134       t = TREE_OPERAND (expr, 1);
135       if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
136         {
137           code = MINUS_EXPR;
138           t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
139         }
140       t = fold_convert (sizetype, t);
141       off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
142       break;
143
144     case MEM_REF:
145       gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR);
146       return double_int_to_tree (sizetype, mem_ref_offset (expr));
147
148     default:
149       return error_mark_node;
150     }
151
152   return size_binop (code, base, off);
153 }
154
155
156 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
157    OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
158    If unknown, return unknown[object_size_type].  */
159
160 static unsigned HOST_WIDE_INT
161 addr_object_size (struct object_size_info *osi, const_tree ptr,
162                   int object_size_type)
163 {
164   tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
165
166   gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
167
168   pt_var = TREE_OPERAND (ptr, 0);
169   while (handled_component_p (pt_var))
170     pt_var = TREE_OPERAND (pt_var, 0);
171
172   if (pt_var
173       && TREE_CODE (pt_var) == MEM_REF)
174     {
175       unsigned HOST_WIDE_INT sz;
176
177       if (!osi || (object_size_type & 1) != 0
178           || TREE_CODE (pt_var) != SSA_NAME)
179         {
180           sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
181                                             object_size_type & ~1);
182         }
183       else
184         {
185           tree var = TREE_OPERAND (pt_var, 0);
186           if (osi->pass == 0)
187             collect_object_sizes_for (osi, var);
188           if (bitmap_bit_p (computed[object_size_type],
189                             SSA_NAME_VERSION (var)))
190             sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)];
191           else
192             sz = unknown[object_size_type];
193         }
194       if (sz != unknown[object_size_type])
195         {
196           double_int dsz = double_int_sub (uhwi_to_double_int (sz),
197                                            mem_ref_offset (pt_var));
198           if (double_int_negative_p (dsz))
199             sz = 0;
200           else if (double_int_fits_in_uhwi_p (dsz))
201             sz = double_int_to_uhwi (dsz);
202           else
203             sz = unknown[object_size_type];
204         }
205
206       if (sz != unknown[object_size_type] && sz < offset_limit)
207         pt_var_size = size_int (sz);
208     }
209   else if (pt_var
210            && DECL_P (pt_var)
211            && host_integerp (DECL_SIZE_UNIT (pt_var), 1)
212            && (unsigned HOST_WIDE_INT)
213                 tree_low_cst (DECL_SIZE_UNIT (pt_var), 1) < offset_limit)
214     pt_var_size = DECL_SIZE_UNIT (pt_var);
215   else if (pt_var
216            && TREE_CODE (pt_var) == STRING_CST
217            && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
218            && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
219            && (unsigned HOST_WIDE_INT)
220               tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
221               < offset_limit)
222     pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
223   else
224     return unknown[object_size_type];
225
226   if (pt_var != TREE_OPERAND (ptr, 0))
227     {
228       tree var;
229
230       if (object_size_type & 1)
231         {
232           var = TREE_OPERAND (ptr, 0);
233
234           while (var != pt_var
235                  && TREE_CODE (var) != BIT_FIELD_REF
236                  && TREE_CODE (var) != COMPONENT_REF
237                  && TREE_CODE (var) != ARRAY_REF
238                  && TREE_CODE (var) != ARRAY_RANGE_REF
239                  && TREE_CODE (var) != REALPART_EXPR
240                  && TREE_CODE (var) != IMAGPART_EXPR)
241             var = TREE_OPERAND (var, 0);
242           if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
243             var = TREE_OPERAND (var, 0);
244           if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
245               || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
246               || (pt_var_size
247                   && tree_int_cst_lt (pt_var_size,
248                                       TYPE_SIZE_UNIT (TREE_TYPE (var)))))
249             var = pt_var;
250           else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF)
251             {
252               tree v = var;
253               /* For &X->fld, compute object size only if fld isn't the last
254                  field, as struct { int i; char c[1]; } is often used instead
255                  of flexible array member.  */
256               while (v && v != pt_var)
257                 switch (TREE_CODE (v))
258                   {
259                   case ARRAY_REF:
260                     if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))
261                         && TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST)
262                       {
263                         tree domain
264                           = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0)));
265                         if (domain
266                             && TYPE_MAX_VALUE (domain)
267                             && TREE_CODE (TYPE_MAX_VALUE (domain))
268                                == INTEGER_CST
269                             && tree_int_cst_lt (TREE_OPERAND (v, 1),
270                                                 TYPE_MAX_VALUE (domain)))
271                           {
272                             v = NULL_TREE;
273                             break;
274                           }
275                       }
276                     v = TREE_OPERAND (v, 0);
277                     break;
278                   case REALPART_EXPR:
279                   case IMAGPART_EXPR:
280                     v = NULL_TREE;
281                     break;
282                   case COMPONENT_REF:
283                     if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
284                       {
285                         v = NULL_TREE;
286                         break;
287                       }
288                     while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
289                       if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
290                           != UNION_TYPE
291                           && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
292                           != QUAL_UNION_TYPE)
293                         break;
294                       else
295                         v = TREE_OPERAND (v, 0);
296                     if (TREE_CODE (v) == COMPONENT_REF
297                         && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
298                            == RECORD_TYPE)
299                       {
300                         tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1));
301                         for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain))
302                           if (TREE_CODE (fld_chain) == FIELD_DECL)
303                             break;
304
305                         if (fld_chain)
306                           {
307                             v = NULL_TREE;
308                             break;
309                           }
310                         v = TREE_OPERAND (v, 0);
311                       }
312                     while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
313                       if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
314                           != UNION_TYPE
315                           && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
316                           != QUAL_UNION_TYPE)
317                         break;
318                       else
319                         v = TREE_OPERAND (v, 0);
320                     if (v != pt_var)
321                       v = NULL_TREE;
322                     else
323                       v = pt_var;
324                     break;
325                   default:
326                     v = pt_var;
327                     break;
328                   }
329               if (v == pt_var)
330                 var = pt_var;
331             }
332         }
333       else
334         var = pt_var;
335
336       if (var != pt_var)
337         var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
338       else if (!pt_var_size)
339         return unknown[object_size_type];
340       else
341         var_size = pt_var_size;
342       bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
343       if (bytes != error_mark_node)
344         {
345           if (TREE_CODE (bytes) == INTEGER_CST
346               && tree_int_cst_lt (var_size, bytes))
347             bytes = size_zero_node;
348           else
349             bytes = size_binop (MINUS_EXPR, var_size, bytes);
350         }
351       if (var != pt_var
352           && pt_var_size
353           && TREE_CODE (pt_var) == MEM_REF
354           && bytes != error_mark_node)
355         {
356           tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var);
357           if (bytes2 != error_mark_node)
358             {
359               if (TREE_CODE (bytes2) == INTEGER_CST
360                   && tree_int_cst_lt (pt_var_size, bytes2))
361                 bytes2 = size_zero_node;
362               else
363                 bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
364               bytes = size_binop (MIN_EXPR, bytes, bytes2);
365             }
366         }
367     }
368   else if (!pt_var_size)
369     return unknown[object_size_type];
370   else
371     bytes = pt_var_size;
372
373   if (host_integerp (bytes, 1))
374     return tree_low_cst (bytes, 1);
375
376   return unknown[object_size_type];
377 }
378
379
380 /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
381    Handles various allocation calls.  OBJECT_SIZE_TYPE is the second
382    argument from __builtin_object_size.  If unknown, return
383    unknown[object_size_type].  */
384
385 static unsigned HOST_WIDE_INT
386 alloc_object_size (const_gimple call, int object_size_type)
387 {
388   tree callee, bytes = NULL_TREE;
389   tree alloc_size;
390   int arg1 = -1, arg2 = -1;
391
392   gcc_assert (is_gimple_call (call));
393
394   callee = gimple_call_fndecl (call);
395   if (!callee)
396     return unknown[object_size_type];
397
398   alloc_size = lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee)));
399   if (alloc_size && TREE_VALUE (alloc_size))
400     {
401       tree p = TREE_VALUE (alloc_size);
402
403       arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1;
404       if (TREE_CHAIN (p))
405         arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
406     }
407
408   if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
409     switch (DECL_FUNCTION_CODE (callee))
410       {
411       case BUILT_IN_CALLOC:
412         arg2 = 1;
413         /* fall through */
414       case BUILT_IN_MALLOC:
415       case BUILT_IN_ALLOCA:
416       case BUILT_IN_ALLOCA_WITH_ALIGN:
417         arg1 = 0;
418       default:
419         break;
420       }
421
422   if (arg1 < 0 || arg1 >= (int)gimple_call_num_args (call)
423       || TREE_CODE (gimple_call_arg (call, arg1)) != INTEGER_CST
424       || (arg2 >= 0
425           && (arg2 >= (int)gimple_call_num_args (call)
426               || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST)))
427     return unknown[object_size_type];
428
429   if (arg2 >= 0)
430     bytes = size_binop (MULT_EXPR,
431         fold_convert (sizetype, gimple_call_arg (call, arg1)),
432         fold_convert (sizetype, gimple_call_arg (call, arg2)));
433   else if (arg1 >= 0)
434     bytes = fold_convert (sizetype, gimple_call_arg (call, arg1));
435
436   if (bytes && host_integerp (bytes, 1))
437     return tree_low_cst (bytes, 1);
438
439   return unknown[object_size_type];
440 }
441
442
443 /* If object size is propagated from one of function's arguments directly
444    to its return value, return that argument for GIMPLE_CALL statement CALL.
445    Otherwise return NULL.  */
446
447 static tree
448 pass_through_call (const_gimple call)
449 {
450   tree callee = gimple_call_fndecl (call);
451
452   if (callee
453       && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
454     switch (DECL_FUNCTION_CODE (callee))
455       {
456       case BUILT_IN_MEMCPY:
457       case BUILT_IN_MEMMOVE:
458       case BUILT_IN_MEMSET:
459       case BUILT_IN_STRCPY:
460       case BUILT_IN_STRNCPY:
461       case BUILT_IN_STRCAT:
462       case BUILT_IN_STRNCAT:
463       case BUILT_IN_MEMCPY_CHK:
464       case BUILT_IN_MEMMOVE_CHK:
465       case BUILT_IN_MEMSET_CHK:
466       case BUILT_IN_STRCPY_CHK:
467       case BUILT_IN_STRNCPY_CHK:
468       case BUILT_IN_STRCAT_CHK:
469       case BUILT_IN_STRNCAT_CHK:
470       case BUILT_IN_ASSUME_ALIGNED:
471         if (gimple_call_num_args (call) >= 1)
472           return gimple_call_arg (call, 0);
473         break;
474       default:
475         break;
476       }
477
478   return NULL_TREE;
479 }
480
481
482 /* Compute __builtin_object_size value for PTR.  OBJECT_SIZE_TYPE is the
483    second argument from __builtin_object_size.  */
484
485 unsigned HOST_WIDE_INT
486 compute_builtin_object_size (tree ptr, int object_size_type)
487 {
488   gcc_assert (object_size_type >= 0 && object_size_type <= 3);
489
490   if (! offset_limit)
491     init_offset_limit ();
492
493   if (TREE_CODE (ptr) == ADDR_EXPR)
494     return addr_object_size (NULL, ptr, object_size_type);
495
496   if (TREE_CODE (ptr) == SSA_NAME
497       && POINTER_TYPE_P (TREE_TYPE (ptr))
498       && object_sizes[object_size_type] != NULL)
499     {
500       if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
501         {
502           struct object_size_info osi;
503           bitmap_iterator bi;
504           unsigned int i;
505
506           if (dump_file)
507             {
508               fprintf (dump_file, "Computing %s %sobject size for ",
509                        (object_size_type & 2) ? "minimum" : "maximum",
510                        (object_size_type & 1) ? "sub" : "");
511               print_generic_expr (dump_file, ptr, dump_flags);
512               fprintf (dump_file, ":\n");
513             }
514
515           osi.visited = BITMAP_ALLOC (NULL);
516           osi.reexamine = BITMAP_ALLOC (NULL);
517           osi.object_size_type = object_size_type;
518           osi.depths = NULL;
519           osi.stack = NULL;
520           osi.tos = NULL;
521
522           /* First pass: walk UD chains, compute object sizes that
523              can be computed.  osi.reexamine bitmap at the end will
524              contain what variables were found in dependency cycles
525              and therefore need to be reexamined.  */
526           osi.pass = 0;
527           osi.changed = false;
528           collect_object_sizes_for (&osi, ptr);
529
530           /* Second pass: keep recomputing object sizes of variables
531              that need reexamination, until no object sizes are
532              increased or all object sizes are computed.  */
533           if (! bitmap_empty_p (osi.reexamine))
534             {
535               bitmap reexamine = BITMAP_ALLOC (NULL);
536
537               /* If looking for minimum instead of maximum object size,
538                  detect cases where a pointer is increased in a loop.
539                  Although even without this detection pass 2 would eventually
540                  terminate, it could take a long time.  If a pointer is
541                  increasing this way, we need to assume 0 object size.
542                  E.g. p = &buf[0]; while (cond) p = p + 4;  */
543               if (object_size_type & 2)
544                 {
545                   osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
546                   osi.stack = XNEWVEC (unsigned int, num_ssa_names);
547                   osi.tos = osi.stack;
548                   osi.pass = 1;
549                   /* collect_object_sizes_for is changing
550                      osi.reexamine bitmap, so iterate over a copy.  */
551                   bitmap_copy (reexamine, osi.reexamine);
552                   EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
553                     if (bitmap_bit_p (osi.reexamine, i))
554                       check_for_plus_in_loops (&osi, ssa_name (i));
555
556                   free (osi.depths);
557                   osi.depths = NULL;
558                   free (osi.stack);
559                   osi.stack = NULL;
560                   osi.tos = NULL;
561                 }
562
563               do
564                 {
565                   osi.pass = 2;
566                   osi.changed = false;
567                   /* collect_object_sizes_for is changing
568                      osi.reexamine bitmap, so iterate over a copy.  */
569                   bitmap_copy (reexamine, osi.reexamine);
570                   EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
571                     if (bitmap_bit_p (osi.reexamine, i))
572                       {
573                         collect_object_sizes_for (&osi, ssa_name (i));
574                         if (dump_file && (dump_flags & TDF_DETAILS))
575                           {
576                             fprintf (dump_file, "Reexamining ");
577                             print_generic_expr (dump_file, ssa_name (i),
578                                                 dump_flags);
579                             fprintf (dump_file, "\n");
580                           }
581                       }
582                 }
583               while (osi.changed);
584
585               BITMAP_FREE (reexamine);
586             }
587           EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
588             bitmap_set_bit (computed[object_size_type], i);
589
590           /* Debugging dumps.  */
591           if (dump_file)
592             {
593               EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
594                 if (object_sizes[object_size_type][i]
595                     != unknown[object_size_type])
596                   {
597                     print_generic_expr (dump_file, ssa_name (i),
598                                         dump_flags);
599                     fprintf (dump_file,
600                              ": %s %sobject size "
601                              HOST_WIDE_INT_PRINT_UNSIGNED "\n",
602                              (object_size_type & 2) ? "minimum" : "maximum",
603                              (object_size_type & 1) ? "sub" : "",
604                              object_sizes[object_size_type][i]);
605                   }
606             }
607
608           BITMAP_FREE (osi.reexamine);
609           BITMAP_FREE (osi.visited);
610         }
611
612       return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
613     }
614
615   return unknown[object_size_type];
616 }
617
618 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME.  */
619
620 static void
621 expr_object_size (struct object_size_info *osi, tree ptr, tree value)
622 {
623   int object_size_type = osi->object_size_type;
624   unsigned int varno = SSA_NAME_VERSION (ptr);
625   unsigned HOST_WIDE_INT bytes;
626
627   gcc_assert (object_sizes[object_size_type][varno]
628               != unknown[object_size_type]);
629   gcc_assert (osi->pass == 0);
630
631   if (TREE_CODE (value) == WITH_SIZE_EXPR)
632     value = TREE_OPERAND (value, 0);
633
634   /* Pointer variables should have been handled by merge_object_sizes.  */
635   gcc_assert (TREE_CODE (value) != SSA_NAME
636               || !POINTER_TYPE_P (TREE_TYPE (value)));
637
638   if (TREE_CODE (value) == ADDR_EXPR)
639     bytes = addr_object_size (osi, value, object_size_type);
640   else
641     bytes = unknown[object_size_type];
642
643   if ((object_size_type & 2) == 0)
644     {
645       if (object_sizes[object_size_type][varno] < bytes)
646         object_sizes[object_size_type][varno] = bytes;
647     }
648   else
649     {
650       if (object_sizes[object_size_type][varno] > bytes)
651         object_sizes[object_size_type][varno] = bytes;
652     }
653 }
654
655
656 /* Compute object_sizes for PTR, defined to the result of a call.  */
657
658 static void
659 call_object_size (struct object_size_info *osi, tree ptr, gimple call)
660 {
661   int object_size_type = osi->object_size_type;
662   unsigned int varno = SSA_NAME_VERSION (ptr);
663   unsigned HOST_WIDE_INT bytes;
664
665   gcc_assert (is_gimple_call (call));
666
667   gcc_assert (object_sizes[object_size_type][varno]
668               != unknown[object_size_type]);
669   gcc_assert (osi->pass == 0);
670
671   bytes = alloc_object_size (call, object_size_type);
672
673   if ((object_size_type & 2) == 0)
674     {
675       if (object_sizes[object_size_type][varno] < bytes)
676         object_sizes[object_size_type][varno] = bytes;
677     }
678   else
679     {
680       if (object_sizes[object_size_type][varno] > bytes)
681         object_sizes[object_size_type][varno] = bytes;
682     }
683 }
684
685
686 /* Compute object_sizes for PTR, defined to an unknown value.  */
687
688 static void
689 unknown_object_size (struct object_size_info *osi, tree ptr)
690 {
691   int object_size_type = osi->object_size_type;
692   unsigned int varno = SSA_NAME_VERSION (ptr);
693   unsigned HOST_WIDE_INT bytes;
694
695   gcc_assert (object_sizes[object_size_type][varno]
696               != unknown[object_size_type]);
697   gcc_assert (osi->pass == 0);
698
699   bytes = unknown[object_size_type];
700
701   if ((object_size_type & 2) == 0)
702     {
703       if (object_sizes[object_size_type][varno] < bytes)
704         object_sizes[object_size_type][varno] = bytes;
705     }
706   else
707     {
708       if (object_sizes[object_size_type][varno] > bytes)
709         object_sizes[object_size_type][varno] = bytes;
710     }
711 }
712
713
714 /* Merge object sizes of ORIG + OFFSET into DEST.  Return true if
715    the object size might need reexamination later.  */
716
717 static bool
718 merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
719                     unsigned HOST_WIDE_INT offset)
720 {
721   int object_size_type = osi->object_size_type;
722   unsigned int varno = SSA_NAME_VERSION (dest);
723   unsigned HOST_WIDE_INT orig_bytes;
724
725   if (object_sizes[object_size_type][varno] == unknown[object_size_type])
726     return false;
727   if (offset >= offset_limit)
728     {
729       object_sizes[object_size_type][varno] = unknown[object_size_type];
730       return false;
731     }
732
733   if (osi->pass == 0)
734     collect_object_sizes_for (osi, orig);
735
736   orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
737   if (orig_bytes != unknown[object_size_type])
738     orig_bytes = (offset > orig_bytes)
739                  ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset;
740
741   if ((object_size_type & 2) == 0)
742     {
743       if (object_sizes[object_size_type][varno] < orig_bytes)
744         {
745           object_sizes[object_size_type][varno] = orig_bytes;
746           osi->changed = true;
747         }
748     }
749   else
750     {
751       if (object_sizes[object_size_type][varno] > orig_bytes)
752         {
753           object_sizes[object_size_type][varno] = orig_bytes;
754           osi->changed = true;
755         }
756     }
757   return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
758 }
759
760
761 /* Compute object_sizes for VAR, defined to the result of an assignment
762    with operator POINTER_PLUS_EXPR.  Return true if the object size might
763    need reexamination  later.  */
764
765 static bool
766 plus_stmt_object_size (struct object_size_info *osi, tree var, gimple stmt)
767 {
768   int object_size_type = osi->object_size_type;
769   unsigned int varno = SSA_NAME_VERSION (var);
770   unsigned HOST_WIDE_INT bytes;
771   tree op0, op1;
772
773   if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
774     {
775       op0 = gimple_assign_rhs1 (stmt);
776       op1 = gimple_assign_rhs2 (stmt);
777     }
778   else if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
779     {
780       tree rhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
781       gcc_assert (TREE_CODE (rhs) == MEM_REF);
782       op0 = TREE_OPERAND (rhs, 0);
783       op1 = TREE_OPERAND (rhs, 1);
784     }
785   else
786     gcc_unreachable ();
787
788   if (object_sizes[object_size_type][varno] == unknown[object_size_type])
789     return false;
790
791   /* Handle PTR + OFFSET here.  */
792   if (TREE_CODE (op1) == INTEGER_CST
793       && (TREE_CODE (op0) == SSA_NAME
794           || TREE_CODE (op0) == ADDR_EXPR))
795     {
796       if (! host_integerp (op1, 1))
797         bytes = unknown[object_size_type];
798       else if (TREE_CODE (op0) == SSA_NAME)
799         return merge_object_sizes (osi, var, op0, tree_low_cst (op1, 1));
800       else
801         {
802           unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
803
804           /* op0 will be ADDR_EXPR here.  */
805           bytes = addr_object_size (osi, op0, object_size_type);
806           if (bytes == unknown[object_size_type])
807             ;
808           else if (off > offset_limit)
809             bytes = unknown[object_size_type];
810           else if (off > bytes)
811             bytes = 0;
812           else
813             bytes -= off;
814         }
815     }
816   else
817     bytes = unknown[object_size_type];
818
819   if ((object_size_type & 2) == 0)
820     {
821       if (object_sizes[object_size_type][varno] < bytes)
822         object_sizes[object_size_type][varno] = bytes;
823     }
824   else
825     {
826       if (object_sizes[object_size_type][varno] > bytes)
827         object_sizes[object_size_type][varno] = bytes;
828     }
829   return false;
830 }
831
832
833 /* Compute object_sizes for VAR, defined at STMT, which is
834    a COND_EXPR.  Return true if the object size might need reexamination
835    later.  */
836
837 static bool
838 cond_expr_object_size (struct object_size_info *osi, tree var, gimple stmt)
839 {
840   tree then_, else_;
841   int object_size_type = osi->object_size_type;
842   unsigned int varno = SSA_NAME_VERSION (var);
843   bool reexamine = false;
844
845   gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR);
846
847   if (object_sizes[object_size_type][varno] == unknown[object_size_type])
848     return false;
849
850   then_ = gimple_assign_rhs2 (stmt);
851   else_ = gimple_assign_rhs3 (stmt);
852
853   if (TREE_CODE (then_) == SSA_NAME)
854     reexamine |= merge_object_sizes (osi, var, then_, 0);
855   else
856     expr_object_size (osi, var, then_);
857
858   if (TREE_CODE (else_) == SSA_NAME)
859     reexamine |= merge_object_sizes (osi, var, else_, 0);
860   else
861     expr_object_size (osi, var, else_);
862
863   return reexamine;
864 }
865
866 /* Compute object sizes for VAR.
867    For ADDR_EXPR an object size is the number of remaining bytes
868    to the end of the object (where what is considered an object depends on
869    OSI->object_size_type).
870    For allocation GIMPLE_CALL like malloc or calloc object size is the size
871    of the allocation.
872    For POINTER_PLUS_EXPR where second operand is a constant integer,
873    object size is object size of the first operand minus the constant.
874    If the constant is bigger than the number of remaining bytes until the
875    end of the object, object size is 0, but if it is instead a pointer
876    subtraction, object size is unknown[object_size_type].
877    To differentiate addition from subtraction, ADDR_EXPR returns
878    unknown[object_size_type] for all objects bigger than half of the address
879    space, and constants less than half of the address space are considered
880    addition, while bigger constants subtraction.
881    For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
882    object size is object size of that argument.
883    Otherwise, object size is the maximum of object sizes of variables
884    that it might be set to.  */
885
886 static void
887 collect_object_sizes_for (struct object_size_info *osi, tree var)
888 {
889   int object_size_type = osi->object_size_type;
890   unsigned int varno = SSA_NAME_VERSION (var);
891   gimple stmt;
892   bool reexamine;
893
894   if (bitmap_bit_p (computed[object_size_type], varno))
895     return;
896
897   if (osi->pass == 0)
898     {
899       if (bitmap_set_bit (osi->visited, varno))
900         {
901           object_sizes[object_size_type][varno]
902             = (object_size_type & 2) ? -1 : 0;
903         }
904       else
905         {
906           /* Found a dependency loop.  Mark the variable for later
907              re-examination.  */
908           bitmap_set_bit (osi->reexamine, varno);
909           if (dump_file && (dump_flags & TDF_DETAILS))
910             {
911               fprintf (dump_file, "Found a dependency loop at ");
912               print_generic_expr (dump_file, var, dump_flags);
913               fprintf (dump_file, "\n");
914             }
915           return;
916         }
917     }
918
919   if (dump_file && (dump_flags & TDF_DETAILS))
920     {
921       fprintf (dump_file, "Visiting use-def links for ");
922       print_generic_expr (dump_file, var, dump_flags);
923       fprintf (dump_file, "\n");
924     }
925
926   stmt = SSA_NAME_DEF_STMT (var);
927   reexamine = false;
928
929   switch (gimple_code (stmt))
930     {
931     case GIMPLE_ASSIGN:
932       {
933         tree rhs = gimple_assign_rhs1 (stmt);
934         if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
935             || (gimple_assign_rhs_code (stmt) == ADDR_EXPR
936                 && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF))
937           reexamine = plus_stmt_object_size (osi, var, stmt);
938         else if (gimple_assign_rhs_code (stmt) == COND_EXPR)
939           reexamine = cond_expr_object_size (osi, var, stmt);
940         else if (gimple_assign_single_p (stmt)
941                  || gimple_assign_unary_nop_p (stmt))
942           {
943             if (TREE_CODE (rhs) == SSA_NAME
944                 && POINTER_TYPE_P (TREE_TYPE (rhs)))
945               reexamine = merge_object_sizes (osi, var, rhs, 0);
946             else
947               expr_object_size (osi, var, rhs);
948           }
949         else
950           unknown_object_size (osi, var);
951         break;
952       }
953
954     case GIMPLE_CALL:
955       {
956         tree arg = pass_through_call (stmt);
957         if (arg)
958           {
959             if (TREE_CODE (arg) == SSA_NAME
960                 && POINTER_TYPE_P (TREE_TYPE (arg)))
961               reexamine = merge_object_sizes (osi, var, arg, 0);
962             else
963               expr_object_size (osi, var, arg);
964           }
965         else
966           call_object_size (osi, var, stmt);
967         break;
968       }
969
970     case GIMPLE_ASM:
971       /* Pointers defined by __asm__ statements can point anywhere.  */
972       object_sizes[object_size_type][varno] = unknown[object_size_type];
973       break;
974
975     case GIMPLE_NOP:
976       {
977         tree decl = SSA_NAME_VAR (var);
978
979         if (TREE_CODE (decl) != PARM_DECL && DECL_INITIAL (decl))
980           expr_object_size (osi, var, DECL_INITIAL (decl));
981         else
982           expr_object_size (osi, var, decl);
983       }
984       break;
985
986     case GIMPLE_PHI:
987       {
988         unsigned i;
989
990         for (i = 0; i < gimple_phi_num_args (stmt); i++)
991           {
992             tree rhs = gimple_phi_arg (stmt, i)->def;
993
994             if (object_sizes[object_size_type][varno]
995                 == unknown[object_size_type])
996               break;
997
998             if (TREE_CODE (rhs) == SSA_NAME)
999               reexamine |= merge_object_sizes (osi, var, rhs, 0);
1000             else if (osi->pass == 0)
1001               expr_object_size (osi, var, rhs);
1002           }
1003         break;
1004       }
1005
1006     default:
1007       gcc_unreachable ();
1008     }
1009
1010   if (! reexamine
1011       || object_sizes[object_size_type][varno] == unknown[object_size_type])
1012     {
1013       bitmap_set_bit (computed[object_size_type], varno);
1014       bitmap_clear_bit (osi->reexamine, varno);
1015     }
1016   else
1017     {
1018       bitmap_set_bit (osi->reexamine, varno);
1019       if (dump_file && (dump_flags & TDF_DETAILS))
1020         {
1021           fprintf (dump_file, "Need to reexamine ");
1022           print_generic_expr (dump_file, var, dump_flags);
1023           fprintf (dump_file, "\n");
1024         }
1025     }
1026 }
1027
1028
1029 /* Helper function for check_for_plus_in_loops.  Called recursively
1030    to detect loops.  */
1031
1032 static void
1033 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
1034                            unsigned int depth)
1035 {
1036   gimple stmt = SSA_NAME_DEF_STMT (var);
1037   unsigned int varno = SSA_NAME_VERSION (var);
1038
1039   if (osi->depths[varno])
1040     {
1041       if (osi->depths[varno] != depth)
1042         {
1043           unsigned int *sp;
1044
1045           /* Found a loop involving pointer addition.  */
1046           for (sp = osi->tos; sp > osi->stack; )
1047             {
1048               --sp;
1049               bitmap_clear_bit (osi->reexamine, *sp);
1050               bitmap_set_bit (computed[osi->object_size_type], *sp);
1051               object_sizes[osi->object_size_type][*sp] = 0;
1052               if (*sp == varno)
1053                 break;
1054             }
1055         }
1056       return;
1057     }
1058   else if (! bitmap_bit_p (osi->reexamine, varno))
1059     return;
1060
1061   osi->depths[varno] = depth;
1062   *osi->tos++ = varno;
1063
1064   switch (gimple_code (stmt))
1065     {
1066
1067     case GIMPLE_ASSIGN:
1068       {
1069         if ((gimple_assign_single_p (stmt)
1070              || gimple_assign_unary_nop_p (stmt))
1071             && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
1072           {
1073             tree rhs = gimple_assign_rhs1 (stmt);
1074
1075             check_for_plus_in_loops_1 (osi, rhs, depth);
1076           }
1077         else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1078           {
1079             tree basevar = gimple_assign_rhs1 (stmt);
1080             tree cst = gimple_assign_rhs2 (stmt);
1081
1082             gcc_assert (TREE_CODE (cst) == INTEGER_CST);
1083
1084             check_for_plus_in_loops_1 (osi, basevar,
1085                                        depth + !integer_zerop (cst));
1086           }
1087         else
1088           gcc_unreachable ();
1089         break;
1090       }
1091
1092     case GIMPLE_CALL:
1093       {
1094         tree arg = pass_through_call (stmt);
1095         if (arg)
1096           {
1097             if (TREE_CODE (arg) == SSA_NAME)
1098               check_for_plus_in_loops_1 (osi, arg, depth);
1099             else
1100               gcc_unreachable ();
1101           }
1102         break;
1103       }
1104
1105     case GIMPLE_PHI:
1106       {
1107         unsigned i;
1108
1109         for (i = 0; i < gimple_phi_num_args (stmt); i++)
1110           {
1111             tree rhs = gimple_phi_arg (stmt, i)->def;
1112
1113             if (TREE_CODE (rhs) == SSA_NAME)
1114               check_for_plus_in_loops_1 (osi, rhs, depth);
1115           }
1116         break;
1117       }
1118
1119     default:
1120       gcc_unreachable ();
1121     }
1122
1123   osi->depths[varno] = 0;
1124   osi->tos--;
1125 }
1126
1127
1128 /* Check if some pointer we are computing object size of is being increased
1129    within a loop.  If yes, assume all the SSA variables participating in
1130    that loop have minimum object sizes 0.  */
1131
1132 static void
1133 check_for_plus_in_loops (struct object_size_info *osi, tree var)
1134 {
1135   gimple stmt = SSA_NAME_DEF_STMT (var);
1136
1137   /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
1138      and looked for a POINTER_PLUS_EXPR in the pass-through
1139      argument, if any.  In GIMPLE, however, such an expression
1140      is not a valid call operand.  */
1141
1142   if (is_gimple_assign (stmt)
1143       && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1144     {
1145       tree basevar = gimple_assign_rhs1 (stmt);
1146       tree cst = gimple_assign_rhs2 (stmt);
1147
1148       gcc_assert (TREE_CODE (cst) == INTEGER_CST);
1149
1150       if (integer_zerop (cst))
1151         return;
1152
1153       osi->depths[SSA_NAME_VERSION (basevar)] = 1;
1154       *osi->tos++ = SSA_NAME_VERSION (basevar);
1155       check_for_plus_in_loops_1 (osi, var, 2);
1156       osi->depths[SSA_NAME_VERSION (basevar)] = 0;
1157       osi->tos--;
1158     }
1159 }
1160
1161
1162 /* Initialize data structures for the object size computation.  */
1163
1164 void
1165 init_object_sizes (void)
1166 {
1167   int object_size_type;
1168
1169   if (object_sizes[0])
1170     return;
1171
1172   for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1173     {
1174       object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names);
1175       computed[object_size_type] = BITMAP_ALLOC (NULL);
1176     }
1177
1178   init_offset_limit ();
1179 }
1180
1181
1182 /* Destroy data structures after the object size computation.  */
1183
1184 void
1185 fini_object_sizes (void)
1186 {
1187   int object_size_type;
1188
1189   for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1190     {
1191       free (object_sizes[object_size_type]);
1192       BITMAP_FREE (computed[object_size_type]);
1193       object_sizes[object_size_type] = NULL;
1194     }
1195 }
1196
1197
1198 /* Simple pass to optimize all __builtin_object_size () builtins.  */
1199
1200 static unsigned int
1201 compute_object_sizes (void)
1202 {
1203   basic_block bb;
1204   FOR_EACH_BB (bb)
1205     {
1206       gimple_stmt_iterator i;
1207       for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
1208         {
1209           tree callee, result;
1210           gimple call = gsi_stmt (i);
1211
1212           if (gimple_code (call) != GIMPLE_CALL)
1213             continue;
1214
1215           callee = gimple_call_fndecl (call);
1216           if (!callee
1217               || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
1218               || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE)
1219             continue;
1220
1221           init_object_sizes ();
1222           result = fold_call_stmt (call, false);
1223           if (!result)
1224             {
1225               if (gimple_call_num_args (call) == 2
1226                   && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, 0))))
1227                 {
1228                   tree ost = gimple_call_arg (call, 1);
1229
1230                   if (host_integerp (ost, 1))
1231                     {
1232                       unsigned HOST_WIDE_INT object_size_type
1233                         = tree_low_cst (ost, 1);
1234
1235                       if (object_size_type < 2)
1236                         result = fold_convert (size_type_node,
1237                                                integer_minus_one_node);
1238                       else if (object_size_type < 4)
1239                         result = build_zero_cst (size_type_node);
1240                     }
1241                 }
1242
1243               if (!result)
1244                 continue;
1245             }
1246
1247           if (dump_file && (dump_flags & TDF_DETAILS))
1248             {
1249               fprintf (dump_file, "Simplified\n  ");
1250               print_gimple_stmt (dump_file, call, 0, dump_flags);
1251             }
1252
1253           if (!update_call_from_tree (&i, result))
1254             gcc_unreachable ();
1255
1256           if (dump_file && (dump_flags & TDF_DETAILS))
1257             {
1258               fprintf (dump_file, "to\n  ");
1259               print_gimple_stmt (dump_file, gsi_stmt (i), 0, dump_flags);
1260               fprintf (dump_file, "\n");
1261             }
1262         }
1263     }
1264
1265   fini_object_sizes ();
1266   return 0;
1267 }
1268
1269 struct gimple_opt_pass pass_object_sizes =
1270 {
1271  {
1272   GIMPLE_PASS,
1273   "objsz",                              /* name */
1274   NULL,                                 /* gate */
1275   compute_object_sizes,                 /* execute */
1276   NULL,                                 /* sub */
1277   NULL,                                 /* next */
1278   0,                                    /* static_pass_number */
1279   TV_NONE,                              /* tv_id */
1280   PROP_cfg | PROP_ssa,                  /* properties_required */
1281   0,                                    /* properties_provided */
1282   0,                                    /* properties_destroyed */
1283   0,                                    /* todo_flags_start */
1284   TODO_verify_ssa                       /* todo_flags_finish */
1285  }
1286 };