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"
27 #include "diagnostic.h"
28 #include "tree-flow.h"
29 #include "tree-pass.h"
30 #include "tree-ssa-propagate.h"
32 struct object_size_info
35 bitmap visited
, reexamine
;
39 unsigned int *stack
, *tos
;
42 static unsigned HOST_WIDE_INT unknown
[4] = { -1, -1, 0, 0 };
44 static tree
compute_object_offset (tree
, tree
);
45 static unsigned HOST_WIDE_INT
addr_object_size (tree
, int);
46 static unsigned HOST_WIDE_INT
alloc_object_size (tree
, int);
47 static tree
pass_through_call (tree
);
48 static void collect_object_sizes_for (struct object_size_info
*, tree
);
49 static void expr_object_size (struct object_size_info
*, tree
, tree
);
50 static bool merge_object_sizes (struct object_size_info
*, tree
, tree
,
51 unsigned HOST_WIDE_INT
);
52 static bool plus_expr_object_size (struct object_size_info
*, tree
, tree
);
53 static bool cond_expr_object_size (struct object_size_info
*, tree
, tree
);
54 static unsigned int compute_object_sizes (void);
55 static void init_offset_limit (void);
56 static void check_for_plus_in_loops (struct object_size_info
*, tree
);
57 static void check_for_plus_in_loops_1 (struct object_size_info
*, tree
,
60 /* object_sizes[0] is upper bound for number of bytes till the end of
62 object_sizes[1] is upper bound for number of bytes till the end of
63 the subobject (innermost array or field with address taken).
64 object_sizes[2] is lower bound for number of bytes till the end of
65 the object and object_sizes[3] lower bound for subobject. */
66 static unsigned HOST_WIDE_INT
*object_sizes
[4];
68 /* Bitmaps what object sizes have been computed already. */
69 static bitmap computed
[4];
71 /* Maximum value of offset we consider to be addition. */
72 static unsigned HOST_WIDE_INT offset_limit
;
75 /* Initialize OFFSET_LIMIT variable. */
77 init_offset_limit (void)
79 if (host_integerp (TYPE_MAX_VALUE (sizetype
), 1))
80 offset_limit
= tree_low_cst (TYPE_MAX_VALUE (sizetype
), 1);
87 /* Compute offset of EXPR within VAR. Return error_mark_node
91 compute_object_offset (tree expr
, tree var
)
93 enum tree_code code
= PLUS_EXPR
;
97 return size_zero_node
;
99 switch (TREE_CODE (expr
))
102 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
103 if (base
== error_mark_node
)
106 t
= TREE_OPERAND (expr
, 1);
107 off
= size_binop (PLUS_EXPR
, DECL_FIELD_OFFSET (t
),
108 size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t
), 1)
115 case VIEW_CONVERT_EXPR
:
116 case NON_LVALUE_EXPR
:
117 return compute_object_offset (TREE_OPERAND (expr
, 0), var
);
120 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
121 if (base
== error_mark_node
)
124 off
= TYPE_SIZE_UNIT (TREE_TYPE (expr
));
128 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
129 if (base
== error_mark_node
)
132 t
= TREE_OPERAND (expr
, 1);
133 if (TREE_CODE (t
) == INTEGER_CST
&& tree_int_cst_sgn (t
) < 0)
136 t
= fold_build1 (NEGATE_EXPR
, TREE_TYPE (t
), t
);
138 t
= fold_convert (sizetype
, t
);
139 off
= size_binop (MULT_EXPR
, TYPE_SIZE_UNIT (TREE_TYPE (expr
)), t
);
143 return error_mark_node
;
146 return size_binop (code
, base
, off
);
150 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
151 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
152 If unknown, return unknown[object_size_type]. */
154 static unsigned HOST_WIDE_INT
155 addr_object_size (tree ptr
, int object_size_type
)
159 gcc_assert (TREE_CODE (ptr
) == ADDR_EXPR
);
161 pt_var
= TREE_OPERAND (ptr
, 0);
162 if (REFERENCE_CLASS_P (pt_var
))
163 pt_var
= get_base_address (pt_var
);
166 && (SSA_VAR_P (pt_var
) || TREE_CODE (pt_var
) == STRING_CST
)
167 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var
))
168 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)), 1)
169 && (unsigned HOST_WIDE_INT
)
170 tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)), 1) < offset_limit
)
174 if (pt_var
!= TREE_OPERAND (ptr
, 0))
178 if (object_size_type
& 1)
180 var
= TREE_OPERAND (ptr
, 0);
183 && TREE_CODE (var
) != BIT_FIELD_REF
184 && TREE_CODE (var
) != COMPONENT_REF
185 && TREE_CODE (var
) != ARRAY_REF
186 && TREE_CODE (var
) != ARRAY_RANGE_REF
187 && TREE_CODE (var
) != REALPART_EXPR
188 && TREE_CODE (var
) != IMAGPART_EXPR
)
189 var
= TREE_OPERAND (var
, 0);
190 if (var
!= pt_var
&& TREE_CODE (var
) == ARRAY_REF
)
191 var
= TREE_OPERAND (var
, 0);
192 if (! TYPE_SIZE_UNIT (TREE_TYPE (var
))
193 || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var
)), 1)
194 || tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)),
195 TYPE_SIZE_UNIT (TREE_TYPE (var
))))
201 bytes
= compute_object_offset (TREE_OPERAND (ptr
, 0), var
);
202 if (bytes
!= error_mark_node
)
204 if (TREE_CODE (bytes
) == INTEGER_CST
205 && tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (var
)), bytes
))
206 bytes
= size_zero_node
;
208 bytes
= size_binop (MINUS_EXPR
,
209 TYPE_SIZE_UNIT (TREE_TYPE (var
)), bytes
);
213 bytes
= TYPE_SIZE_UNIT (TREE_TYPE (pt_var
));
215 if (host_integerp (bytes
, 1))
216 return tree_low_cst (bytes
, 1);
219 return unknown
[object_size_type
];
223 /* Compute __builtin_object_size for CALL, which is a CALL_EXPR.
224 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
225 argument from __builtin_object_size. If unknown, return
226 unknown[object_size_type]. */
228 static unsigned HOST_WIDE_INT
229 alloc_object_size (tree call
, int object_size_type
)
231 tree callee
, arglist
, a
, bytes
= NULL_TREE
;
232 unsigned int arg_mask
= 0;
234 gcc_assert (TREE_CODE (call
) == CALL_EXPR
);
236 callee
= get_callee_fndecl (call
);
237 arglist
= TREE_OPERAND (call
, 1);
239 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
240 switch (DECL_FUNCTION_CODE (callee
))
242 case BUILT_IN_MALLOC
:
243 case BUILT_IN_ALLOCA
:
247 case BUILT_IN_REALLOC:
251 case BUILT_IN_CALLOC
:
258 for (a
= arglist
; arg_mask
&& a
; arg_mask
>>= 1, a
= TREE_CHAIN (a
))
261 tree arg
= TREE_VALUE (a
);
263 if (TREE_CODE (arg
) != INTEGER_CST
)
267 bytes
= fold_convert (sizetype
, arg
);
269 bytes
= size_binop (MULT_EXPR
, bytes
,
270 fold_convert (sizetype
, arg
));
273 if (! arg_mask
&& bytes
&& host_integerp (bytes
, 1))
274 return tree_low_cst (bytes
, 1);
276 return unknown
[object_size_type
];
280 /* If object size is propagated from one of function's arguments directly
281 to its return value, return that argument for CALL_EXPR CALL.
282 Otherwise return NULL. */
285 pass_through_call (tree call
)
287 tree callee
= get_callee_fndecl (call
);
288 tree arglist
= TREE_OPERAND (call
, 1);
291 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
292 switch (DECL_FUNCTION_CODE (callee
))
294 case BUILT_IN_MEMCPY
:
295 case BUILT_IN_MEMMOVE
:
296 case BUILT_IN_MEMSET
:
297 case BUILT_IN_STRCPY
:
298 case BUILT_IN_STRNCPY
:
299 case BUILT_IN_STRCAT
:
300 case BUILT_IN_STRNCAT
:
301 case BUILT_IN_MEMCPY_CHK
:
302 case BUILT_IN_MEMMOVE_CHK
:
303 case BUILT_IN_MEMSET_CHK
:
304 case BUILT_IN_STRCPY_CHK
:
305 case BUILT_IN_STRNCPY_CHK
:
306 case BUILT_IN_STRCAT_CHK
:
307 case BUILT_IN_STRNCAT_CHK
:
309 return TREE_VALUE (arglist
);
319 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
320 second argument from __builtin_object_size. */
322 unsigned HOST_WIDE_INT
323 compute_builtin_object_size (tree ptr
, int object_size_type
)
325 gcc_assert (object_size_type
>= 0 && object_size_type
<= 3);
328 init_offset_limit ();
330 if (TREE_CODE (ptr
) == ADDR_EXPR
)
331 return addr_object_size (ptr
, object_size_type
);
332 else if (TREE_CODE (ptr
) == CALL_EXPR
)
334 tree arg
= pass_through_call (ptr
);
337 return compute_builtin_object_size (arg
, object_size_type
);
339 return alloc_object_size (ptr
, object_size_type
);
341 else if (TREE_CODE (ptr
) == SSA_NAME
342 && POINTER_TYPE_P (TREE_TYPE (ptr
))
343 && object_sizes
[object_size_type
] != NULL
)
345 if (!bitmap_bit_p (computed
[object_size_type
], SSA_NAME_VERSION (ptr
)))
347 struct object_size_info osi
;
353 fprintf (dump_file
, "Computing %s %sobject size for ",
354 (object_size_type
& 2) ? "minimum" : "maximum",
355 (object_size_type
& 1) ? "sub" : "");
356 print_generic_expr (dump_file
, ptr
, dump_flags
);
357 fprintf (dump_file
, ":\n");
360 osi
.visited
= BITMAP_ALLOC (NULL
);
361 osi
.reexamine
= BITMAP_ALLOC (NULL
);
362 osi
.object_size_type
= object_size_type
;
367 /* First pass: walk UD chains, compute object sizes that
368 can be computed. osi.reexamine bitmap at the end will
369 contain what variables were found in dependency cycles
370 and therefore need to be reexamined. */
373 collect_object_sizes_for (&osi
, ptr
);
375 /* Second pass: keep recomputing object sizes of variables
376 that need reexamination, until no object sizes are
377 increased or all object sizes are computed. */
378 if (! bitmap_empty_p (osi
.reexamine
))
380 bitmap reexamine
= BITMAP_ALLOC (NULL
);
382 /* If looking for minimum instead of maximum object size,
383 detect cases where a pointer is increased in a loop.
384 Although even without this detection pass 2 would eventually
385 terminate, it could take a long time. If a pointer is
386 increasing this way, we need to assume 0 object size.
387 E.g. p = &buf[0]; while (cond) p = p + 4; */
388 if (object_size_type
& 2)
390 osi
.depths
= XCNEWVEC (unsigned int, num_ssa_names
);
391 osi
.stack
= XNEWVEC (unsigned int, num_ssa_names
);
394 /* collect_object_sizes_for is changing
395 osi.reexamine bitmap, so iterate over a copy. */
396 bitmap_copy (reexamine
, osi
.reexamine
);
397 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
398 if (bitmap_bit_p (osi
.reexamine
, i
))
399 check_for_plus_in_loops (&osi
, ssa_name (i
));
412 /* collect_object_sizes_for is changing
413 osi.reexamine bitmap, so iterate over a copy. */
414 bitmap_copy (reexamine
, osi
.reexamine
);
415 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
416 if (bitmap_bit_p (osi
.reexamine
, i
))
418 collect_object_sizes_for (&osi
, ssa_name (i
));
419 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
421 fprintf (dump_file
, "Reexamining ");
422 print_generic_expr (dump_file
, ssa_name (i
),
424 fprintf (dump_file
, "\n");
430 BITMAP_FREE (reexamine
);
432 EXECUTE_IF_SET_IN_BITMAP (osi
.reexamine
, 0, i
, bi
)
433 bitmap_set_bit (computed
[object_size_type
], i
);
435 /* Debugging dumps. */
438 EXECUTE_IF_SET_IN_BITMAP (osi
.visited
, 0, i
, bi
)
439 if (object_sizes
[object_size_type
][i
]
440 != unknown
[object_size_type
])
442 print_generic_expr (dump_file
, ssa_name (i
),
445 ": %s %sobject size "
446 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
447 (object_size_type
& 2) ? "minimum" : "maximum",
448 (object_size_type
& 1) ? "sub" : "",
449 object_sizes
[object_size_type
][i
]);
453 BITMAP_FREE (osi
.reexamine
);
454 BITMAP_FREE (osi
.visited
);
457 return object_sizes
[object_size_type
][SSA_NAME_VERSION (ptr
)];
460 return unknown
[object_size_type
];
464 /* Compute object_sizes for PTR, defined to VALUE, which is not
468 expr_object_size (struct object_size_info
*osi
, tree ptr
, tree value
)
470 int object_size_type
= osi
->object_size_type
;
471 unsigned int varno
= SSA_NAME_VERSION (ptr
);
472 unsigned HOST_WIDE_INT bytes
;
474 gcc_assert (object_sizes
[object_size_type
][varno
]
475 != unknown
[object_size_type
]);
476 gcc_assert (osi
->pass
== 0);
478 if (TREE_CODE (value
) == WITH_SIZE_EXPR
)
479 value
= TREE_OPERAND (value
, 0);
481 /* Pointer variables should have been handled by merge_object_sizes. */
482 gcc_assert (TREE_CODE (value
) != SSA_NAME
483 || !POINTER_TYPE_P (TREE_TYPE (value
)));
485 if (TREE_CODE (value
) == ADDR_EXPR
)
486 bytes
= addr_object_size (value
, object_size_type
);
487 else if (TREE_CODE (value
) == CALL_EXPR
)
488 bytes
= alloc_object_size (value
, object_size_type
);
490 bytes
= unknown
[object_size_type
];
492 if ((object_size_type
& 2) == 0)
494 if (object_sizes
[object_size_type
][varno
] < bytes
)
495 object_sizes
[object_size_type
][varno
] = bytes
;
499 if (object_sizes
[object_size_type
][varno
] > bytes
)
500 object_sizes
[object_size_type
][varno
] = bytes
;
505 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
506 the object size might need reexamination later. */
509 merge_object_sizes (struct object_size_info
*osi
, tree dest
, tree orig
,
510 unsigned HOST_WIDE_INT offset
)
512 int object_size_type
= osi
->object_size_type
;
513 unsigned int varno
= SSA_NAME_VERSION (dest
);
514 unsigned HOST_WIDE_INT orig_bytes
;
516 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
518 if (offset
>= offset_limit
)
520 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
525 collect_object_sizes_for (osi
, orig
);
527 orig_bytes
= object_sizes
[object_size_type
][SSA_NAME_VERSION (orig
)];
528 if (orig_bytes
!= unknown
[object_size_type
])
529 orig_bytes
= (offset
> orig_bytes
)
530 ? (unsigned HOST_WIDE_INT
) 0 : orig_bytes
- offset
;
532 if ((object_size_type
& 2) == 0)
534 if (object_sizes
[object_size_type
][varno
] < orig_bytes
)
536 object_sizes
[object_size_type
][varno
] = orig_bytes
;
542 if (object_sizes
[object_size_type
][varno
] > orig_bytes
)
544 object_sizes
[object_size_type
][varno
] = orig_bytes
;
548 return bitmap_bit_p (osi
->reexamine
, SSA_NAME_VERSION (orig
));
552 /* Compute object_sizes for PTR, defined to VALUE, which is
553 a PLUS_EXPR. Return true if the object size might need reexamination
557 plus_expr_object_size (struct object_size_info
*osi
, tree var
, tree value
)
559 tree op0
= TREE_OPERAND (value
, 0);
560 tree op1
= TREE_OPERAND (value
, 1);
561 bool ptr1_p
= POINTER_TYPE_P (TREE_TYPE (op0
))
562 && TREE_CODE (op0
) != INTEGER_CST
;
563 bool ptr2_p
= POINTER_TYPE_P (TREE_TYPE (op1
))
564 && TREE_CODE (op1
) != INTEGER_CST
;
565 int object_size_type
= osi
->object_size_type
;
566 unsigned int varno
= SSA_NAME_VERSION (var
);
567 unsigned HOST_WIDE_INT bytes
;
569 gcc_assert (TREE_CODE (value
) == PLUS_EXPR
);
571 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
574 /* Swap operands if needed. */
575 if (ptr2_p
&& !ptr1_p
)
584 /* Handle PTR + OFFSET here. */
587 && TREE_CODE (op1
) == INTEGER_CST
588 && (TREE_CODE (op0
) == SSA_NAME
589 || TREE_CODE (op0
) == ADDR_EXPR
))
591 if (! host_integerp (op1
, 1))
592 bytes
= unknown
[object_size_type
];
593 else if (TREE_CODE (op0
) == SSA_NAME
)
594 return merge_object_sizes (osi
, var
, op0
, tree_low_cst (op1
, 1));
597 unsigned HOST_WIDE_INT off
= tree_low_cst (op1
, 1);
599 bytes
= compute_builtin_object_size (op0
, object_size_type
);
600 if (off
> offset_limit
)
601 bytes
= unknown
[object_size_type
];
602 else if (off
> bytes
)
609 bytes
= unknown
[object_size_type
];
611 if ((object_size_type
& 2) == 0)
613 if (object_sizes
[object_size_type
][varno
] < bytes
)
614 object_sizes
[object_size_type
][varno
] = bytes
;
618 if (object_sizes
[object_size_type
][varno
] > bytes
)
619 object_sizes
[object_size_type
][varno
] = bytes
;
625 /* Compute object_sizes for PTR, defined to VALUE, which is
626 a COND_EXPR. Return true if the object size might need reexamination
630 cond_expr_object_size (struct object_size_info
*osi
, tree var
, tree value
)
633 int object_size_type
= osi
->object_size_type
;
634 unsigned int varno
= SSA_NAME_VERSION (var
);
635 bool reexamine
= false;
637 gcc_assert (TREE_CODE (value
) == COND_EXPR
);
639 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
642 then_
= COND_EXPR_THEN (value
);
643 else_
= COND_EXPR_ELSE (value
);
645 if (TREE_CODE (then_
) == SSA_NAME
)
646 reexamine
|= merge_object_sizes (osi
, var
, then_
, 0);
648 expr_object_size (osi
, var
, then_
);
650 if (TREE_CODE (else_
) == SSA_NAME
)
651 reexamine
|= merge_object_sizes (osi
, var
, else_
, 0);
653 expr_object_size (osi
, var
, else_
);
659 /* Compute object sizes for VAR.
660 For ADDR_EXPR an object size is the number of remaining bytes
661 to the end of the object (where what is considered an object depends on
662 OSI->object_size_type).
663 For allocation CALL_EXPR like malloc or calloc object size is the size
665 For pointer PLUS_EXPR where second operand is a constant integer,
666 object size is object size of the first operand minus the constant.
667 If the constant is bigger than the number of remaining bytes until the
668 end of the object, object size is 0, but if it is instead a pointer
669 subtraction, object size is unknown[object_size_type].
670 To differentiate addition from subtraction, ADDR_EXPR returns
671 unknown[object_size_type] for all objects bigger than half of the address
672 space, and constants less than half of the address space are considered
673 addition, while bigger constants subtraction.
674 For a memcpy like CALL_EXPR that always returns one of its arguments, the
675 object size is object size of that argument.
676 Otherwise, object size is the maximum of object sizes of variables
677 that it might be set to. */
680 collect_object_sizes_for (struct object_size_info
*osi
, tree var
)
682 int object_size_type
= osi
->object_size_type
;
683 unsigned int varno
= SSA_NAME_VERSION (var
);
687 if (bitmap_bit_p (computed
[object_size_type
], varno
))
692 if (! bitmap_bit_p (osi
->visited
, varno
))
694 bitmap_set_bit (osi
->visited
, varno
);
695 object_sizes
[object_size_type
][varno
]
696 = (object_size_type
& 2) ? -1 : 0;
700 /* Found a dependency loop. Mark the variable for later
702 bitmap_set_bit (osi
->reexamine
, varno
);
703 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
705 fprintf (dump_file
, "Found a dependency loop at ");
706 print_generic_expr (dump_file
, var
, dump_flags
);
707 fprintf (dump_file
, "\n");
713 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
715 fprintf (dump_file
, "Visiting use-def links for ");
716 print_generic_expr (dump_file
, var
, dump_flags
);
717 fprintf (dump_file
, "\n");
720 stmt
= SSA_NAME_DEF_STMT (var
);
723 switch (TREE_CODE (stmt
))
726 gcc_assert (TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
);
727 stmt
= TREE_OPERAND (stmt
, 0);
730 case GIMPLE_MODIFY_STMT
:
732 tree rhs
= GIMPLE_STMT_OPERAND (stmt
, 1), arg
;
735 if (TREE_CODE (rhs
) == CALL_EXPR
)
737 arg
= pass_through_call (rhs
);
742 if (TREE_CODE (rhs
) == SSA_NAME
743 && POINTER_TYPE_P (TREE_TYPE (rhs
)))
744 reexamine
= merge_object_sizes (osi
, var
, rhs
, 0);
746 else if (TREE_CODE (rhs
) == PLUS_EXPR
)
747 reexamine
= plus_expr_object_size (osi
, var
, rhs
);
749 else if (TREE_CODE (rhs
) == COND_EXPR
)
750 reexamine
= cond_expr_object_size (osi
, var
, rhs
);
753 expr_object_size (osi
, var
, rhs
);
758 /* Pointers defined by __asm__ statements can point anywhere. */
759 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
764 tree decl
= SSA_NAME_VAR (var
);
766 gcc_assert (IS_EMPTY_STMT (stmt
));
768 if (TREE_CODE (decl
) != PARM_DECL
&& DECL_INITIAL (decl
))
769 expr_object_size (osi
, var
, DECL_INITIAL (decl
));
771 expr_object_size (osi
, var
, decl
);
779 for (i
= 0; i
< PHI_NUM_ARGS (stmt
); i
++)
781 tree rhs
= PHI_ARG_DEF (stmt
, i
);
783 if (object_sizes
[object_size_type
][varno
]
784 == unknown
[object_size_type
])
787 if (TREE_CODE (rhs
) == SSA_NAME
)
788 reexamine
|= merge_object_sizes (osi
, var
, rhs
, 0);
789 else if (osi
->pass
== 0)
790 expr_object_size (osi
, var
, rhs
);
799 || object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
801 bitmap_set_bit (computed
[object_size_type
], varno
);
802 bitmap_clear_bit (osi
->reexamine
, varno
);
806 bitmap_set_bit (osi
->reexamine
, varno
);
807 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
809 fprintf (dump_file
, "Need to reexamine ");
810 print_generic_expr (dump_file
, var
, dump_flags
);
811 fprintf (dump_file
, "\n");
817 /* Helper function for check_for_plus_in_loops. Called recursively
821 check_for_plus_in_loops_1 (struct object_size_info
*osi
, tree var
,
824 tree stmt
= SSA_NAME_DEF_STMT (var
);
825 unsigned int varno
= SSA_NAME_VERSION (var
);
827 if (osi
->depths
[varno
])
829 if (osi
->depths
[varno
] != depth
)
833 /* Found a loop involving pointer addition. */
834 for (sp
= osi
->tos
; sp
> osi
->stack
; )
837 bitmap_clear_bit (osi
->reexamine
, *sp
);
838 bitmap_set_bit (computed
[osi
->object_size_type
], *sp
);
839 object_sizes
[osi
->object_size_type
][*sp
] = 0;
846 else if (! bitmap_bit_p (osi
->reexamine
, varno
))
849 osi
->depths
[varno
] = depth
;
852 switch (TREE_CODE (stmt
))
855 gcc_assert (TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
);
856 stmt
= TREE_OPERAND (stmt
, 0);
859 case GIMPLE_MODIFY_STMT
:
861 tree rhs
= GIMPLE_STMT_OPERAND (stmt
, 1), arg
;
864 if (TREE_CODE (rhs
) == CALL_EXPR
)
866 arg
= pass_through_call (rhs
);
871 if (TREE_CODE (rhs
) == SSA_NAME
)
872 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
873 else if (TREE_CODE (rhs
) == PLUS_EXPR
)
875 tree op0
= TREE_OPERAND (rhs
, 0);
876 tree op1
= TREE_OPERAND (rhs
, 1);
879 if (TREE_CODE (op0
) == SSA_NAME
)
888 gcc_assert (TREE_CODE (basevar
) == SSA_NAME
);
890 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
892 check_for_plus_in_loops_1 (osi
, basevar
,
893 depth
+ !integer_zerop (cst
));
903 for (i
= 0; i
< PHI_NUM_ARGS (stmt
); i
++)
905 tree rhs
= PHI_ARG_DEF (stmt
, i
);
907 if (TREE_CODE (rhs
) == SSA_NAME
)
908 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
916 osi
->depths
[varno
] = 0;
921 /* Check if some pointer we are computing object size of is being increased
922 within a loop. If yes, assume all the SSA variables participating in
923 that loop have minimum object sizes 0. */
926 check_for_plus_in_loops (struct object_size_info
*osi
, tree var
)
928 tree stmt
= SSA_NAME_DEF_STMT (var
);
930 switch (TREE_CODE (stmt
))
933 gcc_assert (TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
);
934 stmt
= TREE_OPERAND (stmt
, 0);
937 case GIMPLE_MODIFY_STMT
:
939 tree rhs
= GIMPLE_STMT_OPERAND (stmt
, 1), arg
;
942 if (TREE_CODE (rhs
) == CALL_EXPR
)
944 arg
= pass_through_call (rhs
);
949 if (TREE_CODE (rhs
) == PLUS_EXPR
)
951 tree op0
= TREE_OPERAND (rhs
, 0);
952 tree op1
= TREE_OPERAND (rhs
, 1);
955 if (TREE_CODE (op0
) == SSA_NAME
)
964 gcc_assert (TREE_CODE (basevar
) == SSA_NAME
);
966 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
968 if (integer_zerop (cst
))
971 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 1;
972 *osi
->tos
++ = SSA_NAME_VERSION (basevar
);
973 check_for_plus_in_loops_1 (osi
, var
, 2);
974 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 0;
985 /* Initialize data structures for the object size computation. */
988 init_object_sizes (void)
990 int object_size_type
;
995 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
997 object_sizes
[object_size_type
] = XNEWVEC (unsigned HOST_WIDE_INT
, num_ssa_names
);
998 computed
[object_size_type
] = BITMAP_ALLOC (NULL
);
1001 init_offset_limit ();
1005 /* Destroy data structures after the object size computation. */
1008 fini_object_sizes (void)
1010 int object_size_type
;
1012 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
1014 free (object_sizes
[object_size_type
]);
1015 BITMAP_FREE (computed
[object_size_type
]);
1016 object_sizes
[object_size_type
] = NULL
;
1021 /* Simple pass to optimize all __builtin_object_size () builtins. */
1024 compute_object_sizes (void)
1029 block_stmt_iterator i
;
1030 for (i
= bsi_start (bb
); !bsi_end_p (i
); bsi_next (&i
))
1032 tree
*stmtp
= bsi_stmt_ptr (i
);
1033 tree call
= get_rhs (*stmtp
);
1034 tree callee
, result
;
1036 if (!call
|| TREE_CODE (call
) != CALL_EXPR
)
1039 callee
= get_callee_fndecl (call
);
1041 || DECL_BUILT_IN_CLASS (callee
) != BUILT_IN_NORMAL
1042 || DECL_FUNCTION_CODE (callee
) != BUILT_IN_OBJECT_SIZE
)
1045 init_object_sizes ();
1046 result
= fold_builtin (callee
, TREE_OPERAND (call
, 1), false);
1049 tree arglist
= TREE_OPERAND (call
, 1);
1052 && POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist
)))
1053 && TREE_CHAIN (arglist
) != NULL
1054 && TREE_CHAIN (TREE_CHAIN (arglist
)) == NULL
)
1056 tree ost
= TREE_VALUE (TREE_CHAIN (arglist
));
1058 if (host_integerp (ost
, 1))
1060 unsigned HOST_WIDE_INT object_size_type
1061 = tree_low_cst (ost
, 1);
1063 if (object_size_type
< 2)
1064 result
= fold_convert (size_type_node
,
1065 integer_minus_one_node
);
1066 else if (object_size_type
< 4)
1067 result
= size_zero_node
;
1075 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1077 fprintf (dump_file
, "Simplified\n ");
1078 print_generic_stmt (dump_file
, *stmtp
, dump_flags
);
1081 if (!set_rhs (stmtp
, result
))
1083 update_stmt (*stmtp
);
1085 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1087 fprintf (dump_file
, "to\n ");
1088 print_generic_stmt (dump_file
, *stmtp
, dump_flags
);
1089 fprintf (dump_file
, "\n");
1094 fini_object_sizes ();
1098 struct tree_opt_pass pass_object_sizes
=
1102 compute_object_sizes
, /* execute */
1105 0, /* static_pass_number */
1107 PROP_cfg
| PROP_ssa
| PROP_alias
, /* properties_required */
1108 0, /* properties_provided */
1109 0, /* properties_destroyed */
1110 0, /* todo_flags_start */
1111 TODO_dump_func
| TODO_verify_ssa
, /* todo_flags_finish */