OSDN Git Service

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