* Makefile.in ($(out_object_file)): Depend upon $(DF_H).
[official-gcc.git] / gcc / tree-object-size.c
blob5c64b989d5ec43ede3112c0d484992498b2a5e15
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>
6 This file is part of GCC.
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.
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.
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/>. */
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"
33 struct object_size_info
35 int object_size_type;
36 bitmap visited, reexamine;
37 int pass;
38 bool changed;
39 unsigned int *depths;
40 unsigned int *stack, *tos;
43 static unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 };
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);
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];
70 /* Bitmaps what object sizes have been computed already. */
71 static bitmap computed[4];
73 /* Maximum value of offset we consider to be addition. */
74 static unsigned HOST_WIDE_INT offset_limit;
77 /* Initialize OFFSET_LIMIT variable. */
78 static void
79 init_offset_limit (void)
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;
89 /* Compute offset of EXPR within VAR. Return error_mark_node
90 if unknown. */
92 static tree
93 compute_object_offset (const_tree expr, const_tree var)
95 enum tree_code code = PLUS_EXPR;
96 tree base, off, t;
98 if (expr == var)
99 return size_zero_node;
101 switch (TREE_CODE (expr))
103 case COMPONENT_REF:
104 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
105 if (base == error_mark_node)
106 return base;
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;
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);
120 case IMAGPART_EXPR:
121 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
122 if (base == error_mark_node)
123 return base;
125 off = TYPE_SIZE_UNIT (TREE_TYPE (expr));
126 break;
128 case ARRAY_REF:
129 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
130 if (base == error_mark_node)
131 return base;
133 t = TREE_OPERAND (expr, 1);
134 if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
136 code = MINUS_EXPR;
137 t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
139 t = fold_convert (sizetype, t);
140 off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
141 break;
143 default:
144 return error_mark_node;
147 return size_binop (code, base, off);
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]. */
155 static unsigned HOST_WIDE_INT
156 addr_object_size (struct object_size_info *osi, const_tree ptr,
157 int object_size_type)
159 tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
161 gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
163 pt_var = TREE_OPERAND (ptr, 0);
164 if (REFERENCE_CLASS_P (pt_var))
165 pt_var = get_base_address (pt_var);
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))))
172 unsigned HOST_WIDE_INT sz;
174 if (!osi)
175 sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
176 object_size_type);
177 else
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];
189 if (sz != unknown[object_size_type] && sz < offset_limit)
190 pt_var_size = size_int (sz);
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];
203 if (pt_var != TREE_OPERAND (ptr, 0))
205 tree var;
207 if (object_size_type & 1)
209 var = TREE_OPERAND (ptr, 0);
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)
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))
236 case ARRAY_REF:
237 if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))
238 && TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST)
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)))
249 v = NULL_TREE;
250 break;
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)
262 v = NULL_TREE;
263 break;
265 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
266 == RECORD_TYPE)
268 tree fld_chain = TREE_CHAIN (TREE_OPERAND (v, 1));
269 for (; fld_chain; fld_chain = TREE_CHAIN (fld_chain))
270 if (TREE_CODE (fld_chain) == FIELD_DECL)
271 break;
273 if (fld_chain)
275 v = NULL_TREE;
276 break;
280 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
281 == RECORD_TYPE)
282 v = TREE_OPERAND (v, 0);
283 while (v && v != pt_var && TREE_CODE (v) == COMPONENT_REF)
284 if (TREE_CODE (TREE_TYPE (v)) != UNION_TYPE
285 && TREE_CODE (TREE_TYPE (v)) != QUAL_UNION_TYPE)
286 break;
287 else
288 v = TREE_OPERAND (v, 0);
289 if (v && v != pt_var)
290 v = NULL_TREE;
291 else
292 v = pt_var;
293 break;
294 default:
295 v = pt_var;
296 break;
298 if (v == pt_var)
299 var = pt_var;
302 else
303 var = pt_var;
305 if (var != pt_var)
306 var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
307 else if (!pt_var_size)
308 return unknown[object_size_type];
309 else
310 var_size = pt_var_size;
311 bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
312 if (bytes != error_mark_node)
314 if (TREE_CODE (bytes) == INTEGER_CST
315 && tree_int_cst_lt (var_size, bytes))
316 bytes = size_zero_node;
317 else
318 bytes = size_binop (MINUS_EXPR, var_size, bytes);
320 if (var != pt_var
321 && pt_var_size
322 && TREE_CODE (pt_var) == INDIRECT_REF
323 && bytes != error_mark_node)
325 tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var);
326 if (bytes2 != error_mark_node)
328 if (TREE_CODE (bytes2) == INTEGER_CST
329 && tree_int_cst_lt (pt_var_size, bytes2))
330 bytes2 = size_zero_node;
331 else
332 bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
333 bytes = size_binop (MIN_EXPR, bytes, bytes2);
337 else if (!pt_var_size)
338 return unknown[object_size_type];
339 else
340 bytes = pt_var_size;
342 if (host_integerp (bytes, 1))
343 return tree_low_cst (bytes, 1);
345 return unknown[object_size_type];
349 /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
350 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
351 argument from __builtin_object_size. If unknown, return
352 unknown[object_size_type]. */
354 static unsigned HOST_WIDE_INT
355 alloc_object_size (const_gimple call, int object_size_type)
357 tree callee, bytes = NULL_TREE;
358 tree alloc_size;
359 int arg1 = -1, arg2 = -1;
361 gcc_assert (is_gimple_call (call));
363 callee = gimple_call_fndecl (call);
364 if (!callee)
365 return unknown[object_size_type];
367 alloc_size = lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee)));
368 if (alloc_size && TREE_VALUE (alloc_size))
370 tree p = TREE_VALUE (alloc_size);
372 arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1;
373 if (TREE_CHAIN (p))
374 arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
377 if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
378 switch (DECL_FUNCTION_CODE (callee))
380 case BUILT_IN_CALLOC:
381 arg2 = 1;
382 /* fall through */
383 case BUILT_IN_MALLOC:
384 case BUILT_IN_ALLOCA:
385 arg1 = 0;
386 default:
387 break;
390 if (arg1 < 0 || arg1 >= (int)gimple_call_num_args (call)
391 || TREE_CODE (gimple_call_arg (call, arg1)) != INTEGER_CST
392 || (arg2 >= 0
393 && (arg2 >= (int)gimple_call_num_args (call)
394 || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST)))
395 return unknown[object_size_type];
397 if (arg2 >= 0)
398 bytes = size_binop (MULT_EXPR,
399 fold_convert (sizetype, gimple_call_arg (call, arg1)),
400 fold_convert (sizetype, gimple_call_arg (call, arg2)));
401 else if (arg1 >= 0)
402 bytes = fold_convert (sizetype, gimple_call_arg (call, arg1));
404 if (bytes && host_integerp (bytes, 1))
405 return tree_low_cst (bytes, 1);
407 return unknown[object_size_type];
411 /* If object size is propagated from one of function's arguments directly
412 to its return value, return that argument for GIMPLE_CALL statement CALL.
413 Otherwise return NULL. */
415 static tree
416 pass_through_call (const_gimple call)
418 tree callee = gimple_call_fndecl (call);
420 if (callee
421 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
422 switch (DECL_FUNCTION_CODE (callee))
424 case BUILT_IN_MEMCPY:
425 case BUILT_IN_MEMMOVE:
426 case BUILT_IN_MEMSET:
427 case BUILT_IN_STRCPY:
428 case BUILT_IN_STRNCPY:
429 case BUILT_IN_STRCAT:
430 case BUILT_IN_STRNCAT:
431 case BUILT_IN_MEMCPY_CHK:
432 case BUILT_IN_MEMMOVE_CHK:
433 case BUILT_IN_MEMSET_CHK:
434 case BUILT_IN_STRCPY_CHK:
435 case BUILT_IN_STRNCPY_CHK:
436 case BUILT_IN_STRCAT_CHK:
437 case BUILT_IN_STRNCAT_CHK:
438 if (gimple_call_num_args (call) >= 1)
439 return gimple_call_arg (call, 0);
440 break;
441 default:
442 break;
445 return NULL_TREE;
449 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
450 second argument from __builtin_object_size. */
452 unsigned HOST_WIDE_INT
453 compute_builtin_object_size (tree ptr, int object_size_type)
455 gcc_assert (object_size_type >= 0 && object_size_type <= 3);
457 if (! offset_limit)
458 init_offset_limit ();
460 if (TREE_CODE (ptr) == ADDR_EXPR)
461 return addr_object_size (NULL, ptr, object_size_type);
463 if (TREE_CODE (ptr) == SSA_NAME
464 && POINTER_TYPE_P (TREE_TYPE (ptr))
465 && object_sizes[object_size_type] != NULL)
467 if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
469 struct object_size_info osi;
470 bitmap_iterator bi;
471 unsigned int i;
473 if (dump_file)
475 fprintf (dump_file, "Computing %s %sobject size for ",
476 (object_size_type & 2) ? "minimum" : "maximum",
477 (object_size_type & 1) ? "sub" : "");
478 print_generic_expr (dump_file, ptr, dump_flags);
479 fprintf (dump_file, ":\n");
482 osi.visited = BITMAP_ALLOC (NULL);
483 osi.reexamine = BITMAP_ALLOC (NULL);
484 osi.object_size_type = object_size_type;
485 osi.depths = NULL;
486 osi.stack = NULL;
487 osi.tos = NULL;
489 /* First pass: walk UD chains, compute object sizes that
490 can be computed. osi.reexamine bitmap at the end will
491 contain what variables were found in dependency cycles
492 and therefore need to be reexamined. */
493 osi.pass = 0;
494 osi.changed = false;
495 collect_object_sizes_for (&osi, ptr);
497 /* Second pass: keep recomputing object sizes of variables
498 that need reexamination, until no object sizes are
499 increased or all object sizes are computed. */
500 if (! bitmap_empty_p (osi.reexamine))
502 bitmap reexamine = BITMAP_ALLOC (NULL);
504 /* If looking for minimum instead of maximum object size,
505 detect cases where a pointer is increased in a loop.
506 Although even without this detection pass 2 would eventually
507 terminate, it could take a long time. If a pointer is
508 increasing this way, we need to assume 0 object size.
509 E.g. p = &buf[0]; while (cond) p = p + 4; */
510 if (object_size_type & 2)
512 osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
513 osi.stack = XNEWVEC (unsigned int, num_ssa_names);
514 osi.tos = osi.stack;
515 osi.pass = 1;
516 /* collect_object_sizes_for is changing
517 osi.reexamine bitmap, so iterate over a copy. */
518 bitmap_copy (reexamine, osi.reexamine);
519 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
520 if (bitmap_bit_p (osi.reexamine, i))
521 check_for_plus_in_loops (&osi, ssa_name (i));
523 free (osi.depths);
524 osi.depths = NULL;
525 free (osi.stack);
526 osi.stack = NULL;
527 osi.tos = NULL;
532 osi.pass = 2;
533 osi.changed = false;
534 /* collect_object_sizes_for is changing
535 osi.reexamine bitmap, so iterate over a copy. */
536 bitmap_copy (reexamine, osi.reexamine);
537 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
538 if (bitmap_bit_p (osi.reexamine, i))
540 collect_object_sizes_for (&osi, ssa_name (i));
541 if (dump_file && (dump_flags & TDF_DETAILS))
543 fprintf (dump_file, "Reexamining ");
544 print_generic_expr (dump_file, ssa_name (i),
545 dump_flags);
546 fprintf (dump_file, "\n");
550 while (osi.changed);
552 BITMAP_FREE (reexamine);
554 EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
555 bitmap_set_bit (computed[object_size_type], i);
557 /* Debugging dumps. */
558 if (dump_file)
560 EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
561 if (object_sizes[object_size_type][i]
562 != unknown[object_size_type])
564 print_generic_expr (dump_file, ssa_name (i),
565 dump_flags);
566 fprintf (dump_file,
567 ": %s %sobject size "
568 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
569 (object_size_type & 2) ? "minimum" : "maximum",
570 (object_size_type & 1) ? "sub" : "",
571 object_sizes[object_size_type][i]);
575 BITMAP_FREE (osi.reexamine);
576 BITMAP_FREE (osi.visited);
579 return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
582 return unknown[object_size_type];
585 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */
587 static void
588 expr_object_size (struct object_size_info *osi, tree ptr, tree value)
590 int object_size_type = osi->object_size_type;
591 unsigned int varno = SSA_NAME_VERSION (ptr);
592 unsigned HOST_WIDE_INT bytes;
594 gcc_assert (object_sizes[object_size_type][varno]
595 != unknown[object_size_type]);
596 gcc_assert (osi->pass == 0);
598 if (TREE_CODE (value) == WITH_SIZE_EXPR)
599 value = TREE_OPERAND (value, 0);
601 /* Pointer variables should have been handled by merge_object_sizes. */
602 gcc_assert (TREE_CODE (value) != SSA_NAME
603 || !POINTER_TYPE_P (TREE_TYPE (value)));
605 if (TREE_CODE (value) == ADDR_EXPR)
606 bytes = addr_object_size (osi, value, object_size_type);
607 else
608 bytes = unknown[object_size_type];
610 if ((object_size_type & 2) == 0)
612 if (object_sizes[object_size_type][varno] < bytes)
613 object_sizes[object_size_type][varno] = bytes;
615 else
617 if (object_sizes[object_size_type][varno] > bytes)
618 object_sizes[object_size_type][varno] = bytes;
623 /* Compute object_sizes for PTR, defined to the result of a call. */
625 static void
626 call_object_size (struct object_size_info *osi, tree ptr, gimple call)
628 int object_size_type = osi->object_size_type;
629 unsigned int varno = SSA_NAME_VERSION (ptr);
630 unsigned HOST_WIDE_INT bytes;
632 gcc_assert (is_gimple_call (call));
634 gcc_assert (object_sizes[object_size_type][varno]
635 != unknown[object_size_type]);
636 gcc_assert (osi->pass == 0);
638 bytes = alloc_object_size (call, object_size_type);
640 if ((object_size_type & 2) == 0)
642 if (object_sizes[object_size_type][varno] < bytes)
643 object_sizes[object_size_type][varno] = bytes;
645 else
647 if (object_sizes[object_size_type][varno] > bytes)
648 object_sizes[object_size_type][varno] = bytes;
653 /* Compute object_sizes for PTR, defined to an unknown value. */
655 static void
656 unknown_object_size (struct object_size_info *osi, tree ptr)
658 int object_size_type = osi->object_size_type;
659 unsigned int varno = SSA_NAME_VERSION (ptr);
660 unsigned HOST_WIDE_INT bytes;
662 gcc_assert (object_sizes[object_size_type][varno]
663 != unknown[object_size_type]);
664 gcc_assert (osi->pass == 0);
666 bytes = unknown[object_size_type];
668 if ((object_size_type & 2) == 0)
670 if (object_sizes[object_size_type][varno] < bytes)
671 object_sizes[object_size_type][varno] = bytes;
673 else
675 if (object_sizes[object_size_type][varno] > bytes)
676 object_sizes[object_size_type][varno] = bytes;
681 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
682 the object size might need reexamination later. */
684 static bool
685 merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
686 unsigned HOST_WIDE_INT offset)
688 int object_size_type = osi->object_size_type;
689 unsigned int varno = SSA_NAME_VERSION (dest);
690 unsigned HOST_WIDE_INT orig_bytes;
692 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
693 return false;
694 if (offset >= offset_limit)
696 object_sizes[object_size_type][varno] = unknown[object_size_type];
697 return false;
700 if (osi->pass == 0)
701 collect_object_sizes_for (osi, orig);
703 orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
704 if (orig_bytes != unknown[object_size_type])
705 orig_bytes = (offset > orig_bytes)
706 ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset;
708 if ((object_size_type & 2) == 0)
710 if (object_sizes[object_size_type][varno] < orig_bytes)
712 object_sizes[object_size_type][varno] = orig_bytes;
713 osi->changed = true;
716 else
718 if (object_sizes[object_size_type][varno] > orig_bytes)
720 object_sizes[object_size_type][varno] = orig_bytes;
721 osi->changed = true;
724 return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
728 /* Compute object_sizes for VAR, defined to the result of an assignment
729 with operator POINTER_PLUS_EXPR. Return true if the object size might
730 need reexamination later. */
732 static bool
733 plus_stmt_object_size (struct object_size_info *osi, tree var, gimple stmt)
735 int object_size_type = osi->object_size_type;
736 unsigned int varno = SSA_NAME_VERSION (var);
737 unsigned HOST_WIDE_INT bytes;
738 tree op0, op1;
740 gcc_assert (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR);
742 op0 = gimple_assign_rhs1 (stmt);
743 op1 = gimple_assign_rhs2 (stmt);
745 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
746 return false;
748 /* Handle PTR + OFFSET here. */
749 if (TREE_CODE (op1) == INTEGER_CST
750 && (TREE_CODE (op0) == SSA_NAME
751 || TREE_CODE (op0) == ADDR_EXPR))
753 if (! host_integerp (op1, 1))
754 bytes = unknown[object_size_type];
755 else if (TREE_CODE (op0) == SSA_NAME)
756 return merge_object_sizes (osi, var, op0, tree_low_cst (op1, 1));
757 else
759 unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
761 /* op0 will be ADDR_EXPR here. */
762 bytes = addr_object_size (osi, op0, object_size_type);
763 if (bytes == unknown[object_size_type])
765 else if (off > offset_limit)
766 bytes = unknown[object_size_type];
767 else if (off > bytes)
768 bytes = 0;
769 else
770 bytes -= off;
773 else
774 bytes = unknown[object_size_type];
776 if ((object_size_type & 2) == 0)
778 if (object_sizes[object_size_type][varno] < bytes)
779 object_sizes[object_size_type][varno] = bytes;
781 else
783 if (object_sizes[object_size_type][varno] > bytes)
784 object_sizes[object_size_type][varno] = bytes;
786 return false;
790 /* Compute object_sizes for VAR, defined to VALUE, which is
791 a COND_EXPR. Return true if the object size might need reexamination
792 later. */
794 static bool
795 cond_expr_object_size (struct object_size_info *osi, tree var, tree value)
797 tree then_, else_;
798 int object_size_type = osi->object_size_type;
799 unsigned int varno = SSA_NAME_VERSION (var);
800 bool reexamine = false;
802 gcc_assert (TREE_CODE (value) == COND_EXPR);
804 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
805 return false;
807 then_ = COND_EXPR_THEN (value);
808 else_ = COND_EXPR_ELSE (value);
810 if (TREE_CODE (then_) == SSA_NAME)
811 reexamine |= merge_object_sizes (osi, var, then_, 0);
812 else
813 expr_object_size (osi, var, then_);
815 if (TREE_CODE (else_) == SSA_NAME)
816 reexamine |= merge_object_sizes (osi, var, else_, 0);
817 else
818 expr_object_size (osi, var, else_);
820 return reexamine;
823 /* Compute object sizes for VAR.
824 For ADDR_EXPR an object size is the number of remaining bytes
825 to the end of the object (where what is considered an object depends on
826 OSI->object_size_type).
827 For allocation GIMPLE_CALL like malloc or calloc object size is the size
828 of the allocation.
829 For POINTER_PLUS_EXPR where second operand is a constant integer,
830 object size is object size of the first operand minus the constant.
831 If the constant is bigger than the number of remaining bytes until the
832 end of the object, object size is 0, but if it is instead a pointer
833 subtraction, object size is unknown[object_size_type].
834 To differentiate addition from subtraction, ADDR_EXPR returns
835 unknown[object_size_type] for all objects bigger than half of the address
836 space, and constants less than half of the address space are considered
837 addition, while bigger constants subtraction.
838 For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
839 object size is object size of that argument.
840 Otherwise, object size is the maximum of object sizes of variables
841 that it might be set to. */
843 static void
844 collect_object_sizes_for (struct object_size_info *osi, tree var)
846 int object_size_type = osi->object_size_type;
847 unsigned int varno = SSA_NAME_VERSION (var);
848 gimple stmt;
849 bool reexamine;
851 if (bitmap_bit_p (computed[object_size_type], varno))
852 return;
854 if (osi->pass == 0)
856 if (! bitmap_bit_p (osi->visited, varno))
858 bitmap_set_bit (osi->visited, varno);
859 object_sizes[object_size_type][varno]
860 = (object_size_type & 2) ? -1 : 0;
862 else
864 /* Found a dependency loop. Mark the variable for later
865 re-examination. */
866 bitmap_set_bit (osi->reexamine, varno);
867 if (dump_file && (dump_flags & TDF_DETAILS))
869 fprintf (dump_file, "Found a dependency loop at ");
870 print_generic_expr (dump_file, var, dump_flags);
871 fprintf (dump_file, "\n");
873 return;
877 if (dump_file && (dump_flags & TDF_DETAILS))
879 fprintf (dump_file, "Visiting use-def links for ");
880 print_generic_expr (dump_file, var, dump_flags);
881 fprintf (dump_file, "\n");
884 stmt = SSA_NAME_DEF_STMT (var);
885 reexamine = false;
887 switch (gimple_code (stmt))
889 case GIMPLE_ASSIGN:
891 if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
892 reexamine = plus_stmt_object_size (osi, var, stmt);
893 else if (gimple_assign_single_p (stmt)
894 || gimple_assign_unary_nop_p (stmt))
896 tree rhs = gimple_assign_rhs1 (stmt);
898 if (TREE_CODE (rhs) == SSA_NAME
899 && POINTER_TYPE_P (TREE_TYPE (rhs)))
900 reexamine = merge_object_sizes (osi, var, rhs, 0);
901 else if (TREE_CODE (rhs) == COND_EXPR)
902 reexamine = cond_expr_object_size (osi, var, rhs);
903 else
904 expr_object_size (osi, var, rhs);
906 else
907 unknown_object_size (osi, var);
908 break;
911 case GIMPLE_CALL:
913 tree arg = pass_through_call (stmt);
914 if (arg)
916 if (TREE_CODE (arg) == SSA_NAME
917 && POINTER_TYPE_P (TREE_TYPE (arg)))
918 reexamine = merge_object_sizes (osi, var, arg, 0);
919 else if (TREE_CODE (arg) == COND_EXPR)
920 reexamine = cond_expr_object_size (osi, var, arg);
921 else
922 expr_object_size (osi, var, arg);
924 else
925 call_object_size (osi, var, stmt);
926 break;
929 case GIMPLE_ASM:
930 /* Pointers defined by __asm__ statements can point anywhere. */
931 object_sizes[object_size_type][varno] = unknown[object_size_type];
932 break;
934 case GIMPLE_NOP:
936 tree decl = SSA_NAME_VAR (var);
938 if (TREE_CODE (decl) != PARM_DECL && DECL_INITIAL (decl))
939 expr_object_size (osi, var, DECL_INITIAL (decl));
940 else
941 expr_object_size (osi, var, decl);
943 break;
945 case GIMPLE_PHI:
947 unsigned i;
949 for (i = 0; i < gimple_phi_num_args (stmt); i++)
951 tree rhs = gimple_phi_arg (stmt, i)->def;
953 if (object_sizes[object_size_type][varno]
954 == unknown[object_size_type])
955 break;
957 if (TREE_CODE (rhs) == SSA_NAME)
958 reexamine |= merge_object_sizes (osi, var, rhs, 0);
959 else if (osi->pass == 0)
960 expr_object_size (osi, var, rhs);
962 break;
965 default:
966 gcc_unreachable ();
969 if (! reexamine
970 || object_sizes[object_size_type][varno] == unknown[object_size_type])
972 bitmap_set_bit (computed[object_size_type], varno);
973 bitmap_clear_bit (osi->reexamine, varno);
975 else
977 bitmap_set_bit (osi->reexamine, varno);
978 if (dump_file && (dump_flags & TDF_DETAILS))
980 fprintf (dump_file, "Need to reexamine ");
981 print_generic_expr (dump_file, var, dump_flags);
982 fprintf (dump_file, "\n");
988 /* Helper function for check_for_plus_in_loops. Called recursively
989 to detect loops. */
991 static void
992 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
993 unsigned int depth)
995 gimple stmt = SSA_NAME_DEF_STMT (var);
996 unsigned int varno = SSA_NAME_VERSION (var);
998 if (osi->depths[varno])
1000 if (osi->depths[varno] != depth)
1002 unsigned int *sp;
1004 /* Found a loop involving pointer addition. */
1005 for (sp = osi->tos; sp > osi->stack; )
1007 --sp;
1008 bitmap_clear_bit (osi->reexamine, *sp);
1009 bitmap_set_bit (computed[osi->object_size_type], *sp);
1010 object_sizes[osi->object_size_type][*sp] = 0;
1011 if (*sp == varno)
1012 break;
1015 return;
1017 else if (! bitmap_bit_p (osi->reexamine, varno))
1018 return;
1020 osi->depths[varno] = depth;
1021 *osi->tos++ = varno;
1023 switch (gimple_code (stmt))
1026 case GIMPLE_ASSIGN:
1028 if ((gimple_assign_single_p (stmt)
1029 || gimple_assign_unary_nop_p (stmt))
1030 && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
1032 tree rhs = gimple_assign_rhs1 (stmt);
1034 check_for_plus_in_loops_1 (osi, rhs, depth);
1036 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1038 tree basevar = gimple_assign_rhs1 (stmt);
1039 tree cst = gimple_assign_rhs2 (stmt);
1041 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
1043 check_for_plus_in_loops_1 (osi, basevar,
1044 depth + !integer_zerop (cst));
1046 else
1047 gcc_unreachable ();
1048 break;
1051 case GIMPLE_CALL:
1053 tree arg = pass_through_call (stmt);
1054 if (arg)
1056 if (TREE_CODE (arg) == SSA_NAME)
1057 check_for_plus_in_loops_1 (osi, arg, depth);
1058 else
1059 gcc_unreachable ();
1061 break;
1064 case GIMPLE_PHI:
1066 unsigned i;
1068 for (i = 0; i < gimple_phi_num_args (stmt); i++)
1070 tree rhs = gimple_phi_arg (stmt, i)->def;
1072 if (TREE_CODE (rhs) == SSA_NAME)
1073 check_for_plus_in_loops_1 (osi, rhs, depth);
1075 break;
1078 default:
1079 gcc_unreachable ();
1082 osi->depths[varno] = 0;
1083 osi->tos--;
1087 /* Check if some pointer we are computing object size of is being increased
1088 within a loop. If yes, assume all the SSA variables participating in
1089 that loop have minimum object sizes 0. */
1091 static void
1092 check_for_plus_in_loops (struct object_size_info *osi, tree var)
1094 gimple stmt = SSA_NAME_DEF_STMT (var);
1096 /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
1097 and looked for a POINTER_PLUS_EXPR in the pass-through
1098 argument, if any. In GIMPLE, however, such an expression
1099 is not a valid call operand. */
1101 if (is_gimple_assign (stmt)
1102 && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1104 tree basevar = gimple_assign_rhs1 (stmt);
1105 tree cst = gimple_assign_rhs2 (stmt);
1107 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
1109 if (integer_zerop (cst))
1110 return;
1112 osi->depths[SSA_NAME_VERSION (basevar)] = 1;
1113 *osi->tos++ = SSA_NAME_VERSION (basevar);
1114 check_for_plus_in_loops_1 (osi, var, 2);
1115 osi->depths[SSA_NAME_VERSION (basevar)] = 0;
1116 osi->tos--;
1121 /* Initialize data structures for the object size computation. */
1123 void
1124 init_object_sizes (void)
1126 int object_size_type;
1128 if (object_sizes[0])
1129 return;
1131 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1133 object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names);
1134 computed[object_size_type] = BITMAP_ALLOC (NULL);
1137 init_offset_limit ();
1141 /* Destroy data structures after the object size computation. */
1143 void
1144 fini_object_sizes (void)
1146 int object_size_type;
1148 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1150 free (object_sizes[object_size_type]);
1151 BITMAP_FREE (computed[object_size_type]);
1152 object_sizes[object_size_type] = NULL;
1157 /* Simple pass to optimize all __builtin_object_size () builtins. */
1159 static unsigned int
1160 compute_object_sizes (void)
1162 basic_block bb;
1163 FOR_EACH_BB (bb)
1165 gimple_stmt_iterator i;
1166 for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
1168 tree callee, result;
1169 gimple call = gsi_stmt (i);
1171 if (gimple_code (call) != GIMPLE_CALL)
1172 continue;
1174 callee = gimple_call_fndecl (call);
1175 if (!callee
1176 || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
1177 || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE)
1178 continue;
1180 init_object_sizes ();
1181 result = fold_call_stmt (call, false);
1182 if (!result)
1184 if (gimple_call_num_args (call) == 2
1185 && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, 0))))
1187 tree ost = gimple_call_arg (call, 1);
1189 if (host_integerp (ost, 1))
1191 unsigned HOST_WIDE_INT object_size_type
1192 = tree_low_cst (ost, 1);
1194 if (object_size_type < 2)
1195 result = fold_convert (size_type_node,
1196 integer_minus_one_node);
1197 else if (object_size_type < 4)
1198 result = size_zero_node;
1202 if (!result)
1203 continue;
1206 if (dump_file && (dump_flags & TDF_DETAILS))
1208 fprintf (dump_file, "Simplified\n ");
1209 print_gimple_stmt (dump_file, call, 0, dump_flags);
1212 if (!update_call_from_tree (&i, result))
1213 gcc_unreachable ();
1215 /* NOTE: In the pre-tuples code, we called update_stmt here. This is
1216 now handled by gsi_replace, called from update_call_from_tree. */
1218 if (dump_file && (dump_flags & TDF_DETAILS))
1220 fprintf (dump_file, "to\n ");
1221 print_gimple_stmt (dump_file, call, 0, dump_flags);
1222 fprintf (dump_file, "\n");
1227 fini_object_sizes ();
1228 return 0;
1231 struct gimple_opt_pass pass_object_sizes =
1234 GIMPLE_PASS,
1235 "objsz", /* name */
1236 NULL, /* gate */
1237 compute_object_sizes, /* execute */
1238 NULL, /* sub */
1239 NULL, /* next */
1240 0, /* static_pass_number */
1241 TV_NONE, /* tv_id */
1242 PROP_cfg | PROP_ssa, /* properties_required */
1243 0, /* properties_provided */
1244 0, /* properties_destroyed */
1245 0, /* todo_flags_start */
1246 TODO_dump_func | TODO_verify_ssa /* todo_flags_finish */