1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to
19 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
24 #include "coretypes.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
36 bitmap visited, reexamine;
40 unsigned int *stack, *tos;
43 static unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 };
45 static tree compute_object_offset (tree, tree);
46 static unsigned HOST_WIDE_INT addr_object_size (tree, int);
47 static unsigned HOST_WIDE_INT alloc_object_size (tree, int);
48 static tree pass_through_call (tree);
49 static void collect_object_sizes_for (struct object_size_info *, tree);
50 static void expr_object_size (struct object_size_info *, tree, tree);
51 static bool merge_object_sizes (struct object_size_info *, tree, tree,
52 unsigned HOST_WIDE_INT);
53 static bool plus_expr_object_size (struct object_size_info *, tree, tree);
54 static bool cond_expr_object_size (struct object_size_info *, tree, tree);
55 static unsigned int compute_object_sizes (void);
56 static void init_offset_limit (void);
57 static void check_for_plus_in_loops (struct object_size_info *, tree);
58 static void check_for_plus_in_loops_1 (struct object_size_info *, tree,
61 /* object_sizes[0] is upper bound for number of bytes till the end of
63 object_sizes[1] is upper bound for number of bytes till the end of
64 the subobject (innermost array or field with address taken).
65 object_sizes[2] is lower bound for number of bytes till the end of
66 the object and object_sizes[3] lower bound for subobject. */
67 static unsigned HOST_WIDE_INT *object_sizes[4];
69 /* Bitmaps what object sizes have been computed already. */
70 static bitmap computed[4];
72 /* Maximum value of offset we consider to be addition. */
73 static unsigned HOST_WIDE_INT offset_limit;
76 /* Initialize OFFSET_LIMIT variable. */
78 init_offset_limit (void)
80 if (host_integerp (TYPE_MAX_VALUE (sizetype), 1))
81 offset_limit = tree_low_cst (TYPE_MAX_VALUE (sizetype), 1);
88 /* Compute offset of EXPR within VAR. Return error_mark_node
92 compute_object_offset (tree expr, tree var)
94 enum tree_code code = PLUS_EXPR;
98 return size_zero_node;
100 switch (TREE_CODE (expr))
103 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
104 if (base == error_mark_node)
107 t = TREE_OPERAND (expr, 1);
108 off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
109 size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
116 case VIEW_CONVERT_EXPR:
117 case NON_LVALUE_EXPR:
118 return compute_object_offset (TREE_OPERAND (expr, 0), var);
121 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
122 if (base == error_mark_node)
125 off = TYPE_SIZE_UNIT (TREE_TYPE (expr));
129 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
130 if (base == error_mark_node)
133 t = TREE_OPERAND (expr, 1);
134 if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
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);
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 (tree ptr, int object_size_type)
160 gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
162 pt_var = TREE_OPERAND (ptr, 0);
163 if (REFERENCE_CLASS_P (pt_var))
164 pt_var = get_base_address (pt_var);
167 && (SSA_VAR_P (pt_var) || TREE_CODE (pt_var) == STRING_CST)
168 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
169 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
170 && (unsigned HOST_WIDE_INT)
171 tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1) < offset_limit)
175 if (pt_var != TREE_OPERAND (ptr, 0))
179 if (object_size_type & 1)
181 var = TREE_OPERAND (ptr, 0);
184 && TREE_CODE (var) != BIT_FIELD_REF
185 && TREE_CODE (var) != COMPONENT_REF
186 && TREE_CODE (var) != ARRAY_REF
187 && TREE_CODE (var) != ARRAY_RANGE_REF
188 && TREE_CODE (var) != REALPART_EXPR
189 && TREE_CODE (var) != IMAGPART_EXPR)
190 var = TREE_OPERAND (var, 0);
191 if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
192 var = TREE_OPERAND (var, 0);
193 if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
194 || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
195 || tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)),
196 TYPE_SIZE_UNIT (TREE_TYPE (var))))
202 bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
203 if (bytes != error_mark_node)
205 if (TREE_CODE (bytes) == INTEGER_CST
206 && tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes))
207 bytes = size_zero_node;
209 bytes = size_binop (MINUS_EXPR,
210 TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes);
214 bytes = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
216 if (host_integerp (bytes, 1))
217 return tree_low_cst (bytes, 1);
220 return unknown[object_size_type];
224 /* Compute __builtin_object_size for CALL, which is a CALL_EXPR.
225 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
226 argument from __builtin_object_size. If unknown, return
227 unknown[object_size_type]. */
229 static unsigned HOST_WIDE_INT
230 alloc_object_size (tree call, int object_size_type)
232 tree callee, bytes = NULL_TREE;
234 int arg1 = -1, arg2 = -1;
236 gcc_assert (TREE_CODE (call) == CALL_EXPR);
238 callee = get_callee_fndecl (call);
240 return unknown[object_size_type];
242 alloc_size = lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee)));
243 if (alloc_size && TREE_VALUE (alloc_size))
245 tree p = TREE_VALUE (alloc_size);
247 arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1;
249 arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
252 if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
253 switch (DECL_FUNCTION_CODE (callee))
255 case BUILT_IN_CALLOC:
258 case BUILT_IN_MALLOC:
259 case BUILT_IN_ALLOCA:
265 if (arg1 < 0 || arg1 >= call_expr_nargs (call)
266 || TREE_CODE (CALL_EXPR_ARG (call, arg1)) != INTEGER_CST
268 && (arg2 >= call_expr_nargs (call)
269 || TREE_CODE (CALL_EXPR_ARG (call, arg2)) != INTEGER_CST)))
270 return unknown[object_size_type];
273 bytes = size_binop (MULT_EXPR,
274 fold_convert (sizetype, CALL_EXPR_ARG (call, arg1)),
275 fold_convert (sizetype, CALL_EXPR_ARG (call, arg2)));
277 bytes = fold_convert (sizetype, CALL_EXPR_ARG (call, arg1));
279 if (bytes && host_integerp (bytes, 1))
280 return tree_low_cst (bytes, 1);
282 return unknown[object_size_type];
286 /* If object size is propagated from one of function's arguments directly
287 to its return value, return that argument for CALL_EXPR CALL.
288 Otherwise return NULL. */
291 pass_through_call (tree call)
293 tree callee = get_callee_fndecl (call);
296 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
297 switch (DECL_FUNCTION_CODE (callee))
299 case BUILT_IN_MEMCPY:
300 case BUILT_IN_MEMMOVE:
301 case BUILT_IN_MEMSET:
302 case BUILT_IN_STRCPY:
303 case BUILT_IN_STRNCPY:
304 case BUILT_IN_STRCAT:
305 case BUILT_IN_STRNCAT:
306 case BUILT_IN_MEMCPY_CHK:
307 case BUILT_IN_MEMMOVE_CHK:
308 case BUILT_IN_MEMSET_CHK:
309 case BUILT_IN_STRCPY_CHK:
310 case BUILT_IN_STRNCPY_CHK:
311 case BUILT_IN_STRCAT_CHK:
312 case BUILT_IN_STRNCAT_CHK:
313 if (call_expr_nargs (call) >= 1)
314 return CALL_EXPR_ARG (call, 0);
324 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
325 second argument from __builtin_object_size. */
327 unsigned HOST_WIDE_INT
328 compute_builtin_object_size (tree ptr, int object_size_type)
330 gcc_assert (object_size_type >= 0 && object_size_type <= 3);
333 init_offset_limit ();
335 if (TREE_CODE (ptr) == ADDR_EXPR)
336 return addr_object_size (ptr, object_size_type);
337 else if (TREE_CODE (ptr) == CALL_EXPR)
339 tree arg = pass_through_call (ptr);
342 return compute_builtin_object_size (arg, object_size_type);
344 return alloc_object_size (ptr, object_size_type);
346 else if (TREE_CODE (ptr) == SSA_NAME
347 && POINTER_TYPE_P (TREE_TYPE (ptr))
348 && object_sizes[object_size_type] != NULL)
350 if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
352 struct object_size_info osi;
358 fprintf (dump_file, "Computing %s %sobject size for ",
359 (object_size_type & 2) ? "minimum" : "maximum",
360 (object_size_type & 1) ? "sub" : "");
361 print_generic_expr (dump_file, ptr, dump_flags);
362 fprintf (dump_file, ":\n");
365 osi.visited = BITMAP_ALLOC (NULL);
366 osi.reexamine = BITMAP_ALLOC (NULL);
367 osi.object_size_type = object_size_type;
372 /* First pass: walk UD chains, compute object sizes that
373 can be computed. osi.reexamine bitmap at the end will
374 contain what variables were found in dependency cycles
375 and therefore need to be reexamined. */
378 collect_object_sizes_for (&osi, ptr);
380 /* Second pass: keep recomputing object sizes of variables
381 that need reexamination, until no object sizes are
382 increased or all object sizes are computed. */
383 if (! bitmap_empty_p (osi.reexamine))
385 bitmap reexamine = BITMAP_ALLOC (NULL);
387 /* If looking for minimum instead of maximum object size,
388 detect cases where a pointer is increased in a loop.
389 Although even without this detection pass 2 would eventually
390 terminate, it could take a long time. If a pointer is
391 increasing this way, we need to assume 0 object size.
392 E.g. p = &buf[0]; while (cond) p = p + 4; */
393 if (object_size_type & 2)
395 osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
396 osi.stack = XNEWVEC (unsigned int, num_ssa_names);
399 /* collect_object_sizes_for is changing
400 osi.reexamine bitmap, so iterate over a copy. */
401 bitmap_copy (reexamine, osi.reexamine);
402 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
403 if (bitmap_bit_p (osi.reexamine, i))
404 check_for_plus_in_loops (&osi, ssa_name (i));
417 /* collect_object_sizes_for is changing
418 osi.reexamine bitmap, so iterate over a copy. */
419 bitmap_copy (reexamine, osi.reexamine);
420 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
421 if (bitmap_bit_p (osi.reexamine, i))
423 collect_object_sizes_for (&osi, ssa_name (i));
424 if (dump_file && (dump_flags & TDF_DETAILS))
426 fprintf (dump_file, "Reexamining ");
427 print_generic_expr (dump_file, ssa_name (i),
429 fprintf (dump_file, "\n");
435 BITMAP_FREE (reexamine);
437 EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
438 bitmap_set_bit (computed[object_size_type], i);
440 /* Debugging dumps. */
443 EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
444 if (object_sizes[object_size_type][i]
445 != unknown[object_size_type])
447 print_generic_expr (dump_file, ssa_name (i),
450 ": %s %sobject size "
451 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
452 (object_size_type & 2) ? "minimum" : "maximum",
453 (object_size_type & 1) ? "sub" : "",
454 object_sizes[object_size_type][i]);
458 BITMAP_FREE (osi.reexamine);
459 BITMAP_FREE (osi.visited);
462 return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
465 return unknown[object_size_type];
469 /* Compute object_sizes for PTR, defined to VALUE, which is not
473 expr_object_size (struct object_size_info *osi, tree ptr, tree value)
475 int object_size_type = osi->object_size_type;
476 unsigned int varno = SSA_NAME_VERSION (ptr);
477 unsigned HOST_WIDE_INT bytes;
479 gcc_assert (object_sizes[object_size_type][varno]
480 != unknown[object_size_type]);
481 gcc_assert (osi->pass == 0);
483 if (TREE_CODE (value) == WITH_SIZE_EXPR)
484 value = TREE_OPERAND (value, 0);
486 /* Pointer variables should have been handled by merge_object_sizes. */
487 gcc_assert (TREE_CODE (value) != SSA_NAME
488 || !POINTER_TYPE_P (TREE_TYPE (value)));
490 if (TREE_CODE (value) == ADDR_EXPR)
491 bytes = addr_object_size (value, object_size_type);
492 else if (TREE_CODE (value) == CALL_EXPR)
493 bytes = alloc_object_size (value, object_size_type);
495 bytes = unknown[object_size_type];
497 if ((object_size_type & 2) == 0)
499 if (object_sizes[object_size_type][varno] < bytes)
500 object_sizes[object_size_type][varno] = bytes;
504 if (object_sizes[object_size_type][varno] > bytes)
505 object_sizes[object_size_type][varno] = bytes;
510 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
511 the object size might need reexamination later. */
514 merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
515 unsigned HOST_WIDE_INT offset)
517 int object_size_type = osi->object_size_type;
518 unsigned int varno = SSA_NAME_VERSION (dest);
519 unsigned HOST_WIDE_INT orig_bytes;
521 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
523 if (offset >= offset_limit)
525 object_sizes[object_size_type][varno] = unknown[object_size_type];
530 collect_object_sizes_for (osi, orig);
532 orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
533 if (orig_bytes != unknown[object_size_type])
534 orig_bytes = (offset > orig_bytes)
535 ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset;
537 if ((object_size_type & 2) == 0)
539 if (object_sizes[object_size_type][varno] < orig_bytes)
541 object_sizes[object_size_type][varno] = orig_bytes;
547 if (object_sizes[object_size_type][varno] > orig_bytes)
549 object_sizes[object_size_type][varno] = orig_bytes;
553 return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
557 /* Compute object_sizes for PTR, defined to VALUE, which is
558 a PLUS_EXPR. Return true if the object size might need reexamination
562 plus_expr_object_size (struct object_size_info *osi, tree var, tree value)
564 tree op0 = TREE_OPERAND (value, 0);
565 tree op1 = TREE_OPERAND (value, 1);
566 bool ptr1_p = POINTER_TYPE_P (TREE_TYPE (op0))
567 && TREE_CODE (op0) != INTEGER_CST;
568 bool ptr2_p = POINTER_TYPE_P (TREE_TYPE (op1))
569 && TREE_CODE (op1) != INTEGER_CST;
570 int object_size_type = osi->object_size_type;
571 unsigned int varno = SSA_NAME_VERSION (var);
572 unsigned HOST_WIDE_INT bytes;
574 gcc_assert (TREE_CODE (value) == PLUS_EXPR);
576 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
579 /* Swap operands if needed. */
580 if (ptr2_p && !ptr1_p)
589 /* Handle PTR + OFFSET here. */
592 && TREE_CODE (op1) == INTEGER_CST
593 && (TREE_CODE (op0) == SSA_NAME
594 || TREE_CODE (op0) == ADDR_EXPR))
596 if (! host_integerp (op1, 1))
597 bytes = unknown[object_size_type];
598 else if (TREE_CODE (op0) == SSA_NAME)
599 return merge_object_sizes (osi, var, op0, tree_low_cst (op1, 1));
602 unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
604 bytes = compute_builtin_object_size (op0, object_size_type);
605 if (bytes == unknown[object_size_type])
607 else if (off > offset_limit)
608 bytes = unknown[object_size_type];
609 else if (off > bytes)
616 bytes = unknown[object_size_type];
618 if ((object_size_type & 2) == 0)
620 if (object_sizes[object_size_type][varno] < bytes)
621 object_sizes[object_size_type][varno] = bytes;
625 if (object_sizes[object_size_type][varno] > bytes)
626 object_sizes[object_size_type][varno] = bytes;
632 /* Compute object_sizes for PTR, defined to VALUE, which is
633 a COND_EXPR. Return true if the object size might need reexamination
637 cond_expr_object_size (struct object_size_info *osi, tree var, tree value)
640 int object_size_type = osi->object_size_type;
641 unsigned int varno = SSA_NAME_VERSION (var);
642 bool reexamine = false;
644 gcc_assert (TREE_CODE (value) == COND_EXPR);
646 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
649 then_ = COND_EXPR_THEN (value);
650 else_ = COND_EXPR_ELSE (value);
652 if (TREE_CODE (then_) == SSA_NAME)
653 reexamine |= merge_object_sizes (osi, var, then_, 0);
655 expr_object_size (osi, var, then_);
657 if (TREE_CODE (else_) == SSA_NAME)
658 reexamine |= merge_object_sizes (osi, var, else_, 0);
660 expr_object_size (osi, var, else_);
666 /* Compute object sizes for VAR.
667 For ADDR_EXPR an object size is the number of remaining bytes
668 to the end of the object (where what is considered an object depends on
669 OSI->object_size_type).
670 For allocation CALL_EXPR like malloc or calloc object size is the size
672 For pointer PLUS_EXPR where second operand is a constant integer,
673 object size is object size of the first operand minus the constant.
674 If the constant is bigger than the number of remaining bytes until the
675 end of the object, object size is 0, but if it is instead a pointer
676 subtraction, object size is unknown[object_size_type].
677 To differentiate addition from subtraction, ADDR_EXPR returns
678 unknown[object_size_type] for all objects bigger than half of the address
679 space, and constants less than half of the address space are considered
680 addition, while bigger constants subtraction.
681 For a memcpy like CALL_EXPR that always returns one of its arguments, the
682 object size is object size of that argument.
683 Otherwise, object size is the maximum of object sizes of variables
684 that it might be set to. */
687 collect_object_sizes_for (struct object_size_info *osi, tree var)
689 int object_size_type = osi->object_size_type;
690 unsigned int varno = SSA_NAME_VERSION (var);
694 if (bitmap_bit_p (computed[object_size_type], varno))
699 if (! bitmap_bit_p (osi->visited, varno))
701 bitmap_set_bit (osi->visited, varno);
702 object_sizes[object_size_type][varno]
703 = (object_size_type & 2) ? -1 : 0;
707 /* Found a dependency loop. Mark the variable for later
709 bitmap_set_bit (osi->reexamine, varno);
710 if (dump_file && (dump_flags & TDF_DETAILS))
712 fprintf (dump_file, "Found a dependency loop at ");
713 print_generic_expr (dump_file, var, dump_flags);
714 fprintf (dump_file, "\n");
720 if (dump_file && (dump_flags & TDF_DETAILS))
722 fprintf (dump_file, "Visiting use-def links for ");
723 print_generic_expr (dump_file, var, dump_flags);
724 fprintf (dump_file, "\n");
727 stmt = SSA_NAME_DEF_STMT (var);
730 switch (TREE_CODE (stmt))
733 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
734 stmt = TREE_OPERAND (stmt, 0);
737 case GIMPLE_MODIFY_STMT:
739 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
742 if (TREE_CODE (rhs) == CALL_EXPR)
744 arg = pass_through_call (rhs);
749 if (TREE_CODE (rhs) == SSA_NAME
750 && POINTER_TYPE_P (TREE_TYPE (rhs)))
751 reexamine = merge_object_sizes (osi, var, rhs, 0);
753 else if (TREE_CODE (rhs) == PLUS_EXPR)
754 reexamine = plus_expr_object_size (osi, var, rhs);
756 else if (TREE_CODE (rhs) == COND_EXPR)
757 reexamine = cond_expr_object_size (osi, var, rhs);
760 expr_object_size (osi, var, rhs);
765 /* Pointers defined by __asm__ statements can point anywhere. */
766 object_sizes[object_size_type][varno] = unknown[object_size_type];
771 tree decl = SSA_NAME_VAR (var);
773 gcc_assert (IS_EMPTY_STMT (stmt));
775 if (TREE_CODE (decl) != PARM_DECL && DECL_INITIAL (decl))
776 expr_object_size (osi, var, DECL_INITIAL (decl));
778 expr_object_size (osi, var, decl);
786 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
788 tree rhs = PHI_ARG_DEF (stmt, i);
790 if (object_sizes[object_size_type][varno]
791 == unknown[object_size_type])
794 if (TREE_CODE (rhs) == SSA_NAME)
795 reexamine |= merge_object_sizes (osi, var, rhs, 0);
796 else if (osi->pass == 0)
797 expr_object_size (osi, var, rhs);
806 || object_sizes[object_size_type][varno] == unknown[object_size_type])
808 bitmap_set_bit (computed[object_size_type], varno);
809 bitmap_clear_bit (osi->reexamine, varno);
813 bitmap_set_bit (osi->reexamine, varno);
814 if (dump_file && (dump_flags & TDF_DETAILS))
816 fprintf (dump_file, "Need to reexamine ");
817 print_generic_expr (dump_file, var, dump_flags);
818 fprintf (dump_file, "\n");
824 /* Helper function for check_for_plus_in_loops. Called recursively
828 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
831 tree stmt = SSA_NAME_DEF_STMT (var);
832 unsigned int varno = SSA_NAME_VERSION (var);
834 if (osi->depths[varno])
836 if (osi->depths[varno] != depth)
840 /* Found a loop involving pointer addition. */
841 for (sp = osi->tos; sp > osi->stack; )
844 bitmap_clear_bit (osi->reexamine, *sp);
845 bitmap_set_bit (computed[osi->object_size_type], *sp);
846 object_sizes[osi->object_size_type][*sp] = 0;
853 else if (! bitmap_bit_p (osi->reexamine, varno))
856 osi->depths[varno] = depth;
859 switch (TREE_CODE (stmt))
862 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
863 stmt = TREE_OPERAND (stmt, 0);
866 case GIMPLE_MODIFY_STMT:
868 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
871 if (TREE_CODE (rhs) == CALL_EXPR)
873 arg = pass_through_call (rhs);
878 if (TREE_CODE (rhs) == SSA_NAME)
879 check_for_plus_in_loops_1 (osi, rhs, depth);
880 else if (TREE_CODE (rhs) == PLUS_EXPR)
882 tree op0 = TREE_OPERAND (rhs, 0);
883 tree op1 = TREE_OPERAND (rhs, 1);
886 if (TREE_CODE (op0) == SSA_NAME)
895 gcc_assert (TREE_CODE (basevar) == SSA_NAME);
897 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
899 check_for_plus_in_loops_1 (osi, basevar,
900 depth + !integer_zerop (cst));
910 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
912 tree rhs = PHI_ARG_DEF (stmt, i);
914 if (TREE_CODE (rhs) == SSA_NAME)
915 check_for_plus_in_loops_1 (osi, rhs, depth);
923 osi->depths[varno] = 0;
928 /* Check if some pointer we are computing object size of is being increased
929 within a loop. If yes, assume all the SSA variables participating in
930 that loop have minimum object sizes 0. */
933 check_for_plus_in_loops (struct object_size_info *osi, tree var)
935 tree stmt = SSA_NAME_DEF_STMT (var);
937 switch (TREE_CODE (stmt))
940 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
941 stmt = TREE_OPERAND (stmt, 0);
944 case GIMPLE_MODIFY_STMT:
946 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
949 if (TREE_CODE (rhs) == CALL_EXPR)
951 arg = pass_through_call (rhs);
956 if (TREE_CODE (rhs) == PLUS_EXPR)
958 tree op0 = TREE_OPERAND (rhs, 0);
959 tree op1 = TREE_OPERAND (rhs, 1);
962 if (TREE_CODE (op0) == SSA_NAME)
971 gcc_assert (TREE_CODE (basevar) == SSA_NAME);
973 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
975 if (integer_zerop (cst))
978 osi->depths[SSA_NAME_VERSION (basevar)] = 1;
979 *osi->tos++ = SSA_NAME_VERSION (basevar);
980 check_for_plus_in_loops_1 (osi, var, 2);
981 osi->depths[SSA_NAME_VERSION (basevar)] = 0;
992 /* Initialize data structures for the object size computation. */
995 init_object_sizes (void)
997 int object_size_type;
1002 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1004 object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names);
1005 computed[object_size_type] = BITMAP_ALLOC (NULL);
1008 init_offset_limit ();
1012 /* Destroy data structures after the object size computation. */
1015 fini_object_sizes (void)
1017 int object_size_type;
1019 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1021 free (object_sizes[object_size_type]);
1022 BITMAP_FREE (computed[object_size_type]);
1023 object_sizes[object_size_type] = NULL;
1028 /* Simple pass to optimize all __builtin_object_size () builtins. */
1031 compute_object_sizes (void)
1036 block_stmt_iterator i;
1037 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
1039 tree *stmtp = bsi_stmt_ptr (i);
1040 tree call = get_rhs (*stmtp);
1041 tree callee, result;
1043 if (!call || TREE_CODE (call) != CALL_EXPR)
1046 callee = get_callee_fndecl (call);
1048 || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
1049 || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE)
1052 init_object_sizes ();
1053 result = fold_call_expr (call, false);
1056 if (call_expr_nargs (call) == 2
1057 && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (call, 0))))
1059 tree ost = CALL_EXPR_ARG (call, 1);
1061 if (host_integerp (ost, 1))
1063 unsigned HOST_WIDE_INT object_size_type
1064 = tree_low_cst (ost, 1);
1066 if (object_size_type < 2)
1067 result = fold_convert (size_type_node,
1068 integer_minus_one_node);
1069 else if (object_size_type < 4)
1070 result = size_zero_node;
1078 if (dump_file && (dump_flags & TDF_DETAILS))
1080 fprintf (dump_file, "Simplified\n ");
1081 print_generic_stmt (dump_file, *stmtp, dump_flags);
1084 if (!set_rhs (stmtp, result))
1086 update_stmt (*stmtp);
1088 if (dump_file && (dump_flags & TDF_DETAILS))
1090 fprintf (dump_file, "to\n ");
1091 print_generic_stmt (dump_file, *stmtp, dump_flags);
1092 fprintf (dump_file, "\n");
1097 fini_object_sizes ();
1101 struct tree_opt_pass pass_object_sizes =
1105 compute_object_sizes, /* execute */
1108 0, /* static_pass_number */
1110 PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */
1111 0, /* properties_provided */
1112 0, /* properties_destroyed */
1113 0, /* todo_flags_start */
1114 TODO_dump_func | TODO_verify_ssa, /* todo_flags_finish */