OSDN Git Service

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