1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004, 2005 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 void compute_object_sizes (void);
54 static void init_offset_limit (void);
55 static void check_for_plus_in_loops (struct object_size_info
*, tree
);
56 static void check_for_plus_in_loops_1 (struct object_size_info
*, tree
,
59 /* object_sizes[0] is upper bound for number of bytes till the end of
61 object_sizes[1] is upper bound for number of bytes till the end of
62 the subobject (innermost array or field with address taken).
63 object_sizes[2] is lower bound for number of bytes till the end of
64 the object and object_sizes[3] lower bound for subobject. */
65 static unsigned HOST_WIDE_INT
*object_sizes
[4];
67 /* Bitmaps what object sizes have been computed already. */
68 static bitmap computed
[4];
70 /* Maximum value of offset we consider to be addition. */
71 static unsigned HOST_WIDE_INT offset_limit
;
74 /* Initialize OFFSET_LIMIT variable. */
76 init_offset_limit (void)
78 if (host_integerp (TYPE_MAX_VALUE (sizetype
), 1))
79 offset_limit
= tree_low_cst (TYPE_MAX_VALUE (sizetype
), 1);
86 /* Compute offset of EXPR within VAR. Return error_mark_node
90 compute_object_offset (tree expr
, tree var
)
92 enum tree_code code
= PLUS_EXPR
;
96 return size_zero_node
;
98 switch (TREE_CODE (expr
))
101 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
102 if (base
== error_mark_node
)
105 t
= TREE_OPERAND (expr
, 1);
106 off
= size_binop (PLUS_EXPR
, DECL_FIELD_OFFSET (t
),
107 size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t
), 1)
114 case VIEW_CONVERT_EXPR
:
115 case NON_LVALUE_EXPR
:
116 return compute_object_offset (TREE_OPERAND (expr
, 0), var
);
119 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
120 if (base
== error_mark_node
)
123 off
= TYPE_SIZE_UNIT (TREE_TYPE (expr
));
127 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
128 if (base
== error_mark_node
)
131 t
= TREE_OPERAND (expr
, 1);
132 if (TREE_CODE (t
) == INTEGER_CST
&& tree_int_cst_sgn (t
) < 0)
135 t
= fold_build1 (NEGATE_EXPR
, TREE_TYPE (t
), t
);
137 t
= convert (sizetype
, t
);
138 off
= size_binop (MULT_EXPR
, TYPE_SIZE_UNIT (TREE_TYPE (expr
)), t
);
142 return error_mark_node
;
145 return size_binop (code
, base
, off
);
149 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
150 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
151 If unknown, return unknown[object_size_type]. */
153 static unsigned HOST_WIDE_INT
154 addr_object_size (tree ptr
, int object_size_type
)
158 gcc_assert (TREE_CODE (ptr
) == ADDR_EXPR
);
160 pt_var
= TREE_OPERAND (ptr
, 0);
161 if (REFERENCE_CLASS_P (pt_var
))
162 pt_var
= get_base_address (pt_var
);
165 && (SSA_VAR_P (pt_var
) || TREE_CODE (pt_var
) == STRING_CST
)
166 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var
))
167 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)), 1)
168 && (unsigned HOST_WIDE_INT
)
169 tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)), 1) < offset_limit
)
173 if (pt_var
!= TREE_OPERAND (ptr
, 0))
177 if (object_size_type
& 1)
179 var
= TREE_OPERAND (ptr
, 0);
182 && TREE_CODE (var
) != BIT_FIELD_REF
183 && TREE_CODE (var
) != COMPONENT_REF
184 && TREE_CODE (var
) != ARRAY_REF
185 && TREE_CODE (var
) != ARRAY_RANGE_REF
186 && TREE_CODE (var
) != REALPART_EXPR
187 && TREE_CODE (var
) != IMAGPART_EXPR
)
188 var
= TREE_OPERAND (var
, 0);
189 if (var
!= pt_var
&& TREE_CODE (var
) == ARRAY_REF
)
190 var
= TREE_OPERAND (var
, 0);
191 if (! TYPE_SIZE_UNIT (TREE_TYPE (var
))
192 || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var
)), 1)
193 || tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)),
194 TYPE_SIZE_UNIT (TREE_TYPE (var
))))
200 bytes
= compute_object_offset (TREE_OPERAND (ptr
, 0), var
);
201 if (bytes
!= error_mark_node
)
203 if (TREE_CODE (bytes
) == INTEGER_CST
204 && tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (var
)), bytes
))
205 bytes
= size_zero_node
;
207 bytes
= size_binop (MINUS_EXPR
,
208 TYPE_SIZE_UNIT (TREE_TYPE (var
)), bytes
);
212 bytes
= TYPE_SIZE_UNIT (TREE_TYPE (pt_var
));
214 if (host_integerp (bytes
, 1))
215 return tree_low_cst (bytes
, 1);
218 return unknown
[object_size_type
];
222 /* Compute __builtin_object_size for CALL, which is a CALL_EXPR.
223 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
224 argument from __builtin_object_size. If unknown, return
225 unknown[object_size_type]. */
227 static unsigned HOST_WIDE_INT
228 alloc_object_size (tree call
, int object_size_type
)
230 tree callee
, arglist
, a
, bytes
= NULL_TREE
;
231 unsigned int arg_mask
= 0;
233 gcc_assert (TREE_CODE (call
) == CALL_EXPR
);
235 callee
= get_callee_fndecl (call
);
236 arglist
= TREE_OPERAND (call
, 1);
238 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
239 switch (DECL_FUNCTION_CODE (callee
))
241 case BUILT_IN_MALLOC
:
242 case BUILT_IN_ALLOCA
:
246 case BUILT_IN_REALLOC:
250 case BUILT_IN_CALLOC
:
257 for (a
= arglist
; arg_mask
&& a
; arg_mask
>>= 1, a
= TREE_CHAIN (a
))
260 tree arg
= TREE_VALUE (a
);
262 if (TREE_CODE (arg
) != INTEGER_CST
)
266 bytes
= fold_convert (sizetype
, arg
);
268 bytes
= size_binop (MULT_EXPR
, bytes
,
269 fold_convert (sizetype
, arg
));
272 if (! arg_mask
&& bytes
&& host_integerp (bytes
, 1))
273 return tree_low_cst (bytes
, 1);
275 return unknown
[object_size_type
];
279 /* If object size is propagated from one of function's arguments directly
280 to its return value, return that argument for CALL_EXPR CALL.
281 Otherwise return NULL. */
284 pass_through_call (tree call
)
286 tree callee
= get_callee_fndecl (call
);
287 tree arglist
= TREE_OPERAND (call
, 1);
290 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
291 switch (DECL_FUNCTION_CODE (callee
))
293 case BUILT_IN_MEMCPY
:
294 case BUILT_IN_MEMMOVE
:
295 case BUILT_IN_MEMSET
:
296 case BUILT_IN_STRCPY
:
297 case BUILT_IN_STRNCPY
:
298 case BUILT_IN_STRCAT
:
299 case BUILT_IN_STRNCAT
:
300 case BUILT_IN_MEMCPY_CHK
:
301 case BUILT_IN_MEMMOVE_CHK
:
302 case BUILT_IN_MEMSET_CHK
:
303 case BUILT_IN_STRCPY_CHK
:
304 case BUILT_IN_STRNCPY_CHK
:
305 case BUILT_IN_STRCAT_CHK
:
306 case BUILT_IN_STRNCAT_CHK
:
308 return TREE_VALUE (arglist
);
318 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
319 second argument from __builtin_object_size. */
321 unsigned HOST_WIDE_INT
322 compute_builtin_object_size (tree ptr
, int object_size_type
)
324 gcc_assert (object_size_type
>= 0 && object_size_type
<= 3);
327 init_offset_limit ();
329 if (TREE_CODE (ptr
) == ADDR_EXPR
)
330 return addr_object_size (ptr
, object_size_type
);
331 else if (TREE_CODE (ptr
) == CALL_EXPR
)
333 tree arg
= pass_through_call (ptr
);
336 return compute_builtin_object_size (arg
, object_size_type
);
338 return alloc_object_size (ptr
, object_size_type
);
340 else if (TREE_CODE (ptr
) == SSA_NAME
341 && POINTER_TYPE_P (TREE_TYPE (ptr
))
342 && object_sizes
[object_size_type
] != NULL
)
344 if (!bitmap_bit_p (computed
[object_size_type
], SSA_NAME_VERSION (ptr
)))
346 struct object_size_info osi
;
352 fprintf (dump_file
, "Computing %s %sobject size for ",
353 (object_size_type
& 2) ? "minimum" : "maximum",
354 (object_size_type
& 1) ? "sub" : "");
355 print_generic_expr (dump_file
, ptr
, dump_flags
);
356 fprintf (dump_file
, ":\n");
359 osi
.visited
= BITMAP_ALLOC (NULL
);
360 osi
.reexamine
= BITMAP_ALLOC (NULL
);
361 osi
.object_size_type
= object_size_type
;
366 /* First pass: walk UD chains, compute object sizes that
367 can be computed. osi.reexamine bitmap at the end will
368 contain what variables were found in dependency cycles
369 and therefore need to be reexamined. */
372 collect_object_sizes_for (&osi
, ptr
);
374 /* Second pass: keep recomputing object sizes of variables
375 that need reexamination, until no object sizes are
376 increased or all object sizes are computed. */
377 if (! bitmap_empty_p (osi
.reexamine
))
379 bitmap reexamine
= BITMAP_ALLOC (NULL
);
381 /* If looking for minimum instead of maximum object size,
382 detect cases where a pointer is increased in a loop.
383 Although even without this detection pass 2 would eventually
384 terminate, it could take a long time. If a pointer is
385 increasing this way, we need to assume 0 object size.
386 E.g. p = &buf[0]; while (cond) p = p + 4; */
387 if (object_size_type
& 2)
389 osi
.depths
= xcalloc (num_ssa_names
, sizeof (unsigned int));
390 osi
.stack
= xmalloc (num_ssa_names
* sizeof (unsigned int));
393 /* collect_object_sizes_for is changing
394 osi.reexamine bitmap, so iterate over a copy. */
395 bitmap_copy (reexamine
, osi
.reexamine
);
396 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
397 if (bitmap_bit_p (osi
.reexamine
, i
))
398 check_for_plus_in_loops (&osi
, ssa_name (i
));
411 /* collect_object_sizes_for is changing
412 osi.reexamine bitmap, so iterate over a copy. */
413 bitmap_copy (reexamine
, osi
.reexamine
);
414 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
415 if (bitmap_bit_p (osi
.reexamine
, i
))
417 collect_object_sizes_for (&osi
, ssa_name (i
));
418 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
420 fprintf (dump_file
, "Reexamining ");
421 print_generic_expr (dump_file
, ssa_name (i
),
423 fprintf (dump_file
, "\n");
429 BITMAP_FREE (reexamine
);
431 EXECUTE_IF_SET_IN_BITMAP (osi
.reexamine
, 0, i
, bi
)
432 bitmap_set_bit (computed
[object_size_type
], i
);
434 /* Debugging dumps. */
437 EXECUTE_IF_SET_IN_BITMAP (osi
.visited
, 0, i
, bi
)
438 if (object_sizes
[object_size_type
][i
]
439 != unknown
[object_size_type
])
441 print_generic_expr (dump_file
, ssa_name (i
),
444 ": %s %sobject size "
445 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
446 (object_size_type
& 2) ? "minimum" : "maximum",
447 (object_size_type
& 1) ? "sub" : "",
448 object_sizes
[object_size_type
][i
]);
452 BITMAP_FREE (osi
.reexamine
);
453 BITMAP_FREE (osi
.visited
);
456 return object_sizes
[object_size_type
][SSA_NAME_VERSION (ptr
)];
459 return unknown
[object_size_type
];
463 /* Compute object_sizes for PTR, defined to VALUE, which is not
467 expr_object_size (struct object_size_info
*osi
, tree ptr
, tree value
)
469 int object_size_type
= osi
->object_size_type
;
470 unsigned int varno
= SSA_NAME_VERSION (ptr
);
471 unsigned HOST_WIDE_INT bytes
;
473 gcc_assert (object_sizes
[object_size_type
][varno
]
474 != unknown
[object_size_type
]);
475 gcc_assert (osi
->pass
== 0);
477 if (TREE_CODE (value
) == WITH_SIZE_EXPR
)
478 value
= TREE_OPERAND (value
, 0);
480 /* Pointer variables should have been handled by merge_object_sizes. */
481 gcc_assert (TREE_CODE (value
) != SSA_NAME
482 || !POINTER_TYPE_P (TREE_TYPE (value
)));
484 if (TREE_CODE (value
) == ADDR_EXPR
)
485 bytes
= addr_object_size (value
, object_size_type
);
486 else if (TREE_CODE (value
) == CALL_EXPR
)
487 bytes
= alloc_object_size (value
, object_size_type
);
489 bytes
= unknown
[object_size_type
];
491 if ((object_size_type
& 2) == 0)
493 if (object_sizes
[object_size_type
][varno
] < bytes
)
494 object_sizes
[object_size_type
][varno
] = bytes
;
498 if (object_sizes
[object_size_type
][varno
] > bytes
)
499 object_sizes
[object_size_type
][varno
] = bytes
;
504 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
505 the object size might need reexamination later. */
508 merge_object_sizes (struct object_size_info
*osi
, tree dest
, tree orig
,
509 unsigned HOST_WIDE_INT offset
)
511 int object_size_type
= osi
->object_size_type
;
512 unsigned int varno
= SSA_NAME_VERSION (dest
);
513 unsigned HOST_WIDE_INT orig_bytes
;
515 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
517 if (offset
>= offset_limit
)
519 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
524 collect_object_sizes_for (osi
, orig
);
526 orig_bytes
= object_sizes
[object_size_type
][SSA_NAME_VERSION (orig
)];
527 if (orig_bytes
!= unknown
[object_size_type
])
528 orig_bytes
= (offset
> orig_bytes
)
529 ? (unsigned HOST_WIDE_INT
) 0 : orig_bytes
- offset
;
531 if ((object_size_type
& 2) == 0)
533 if (object_sizes
[object_size_type
][varno
] < orig_bytes
)
535 object_sizes
[object_size_type
][varno
] = orig_bytes
;
541 if (object_sizes
[object_size_type
][varno
] > orig_bytes
)
543 object_sizes
[object_size_type
][varno
] = orig_bytes
;
547 return bitmap_bit_p (osi
->reexamine
, SSA_NAME_VERSION (orig
));
551 /* Compute object_sizes for PTR, defined to VALUE, which is
552 a PLUS_EXPR. Return true if the object size might need reexamination
556 plus_expr_object_size (struct object_size_info
*osi
, tree var
, tree value
)
558 tree op0
= TREE_OPERAND (value
, 0);
559 tree op1
= TREE_OPERAND (value
, 1);
560 bool ptr1_p
= POINTER_TYPE_P (TREE_TYPE (op0
))
561 && TREE_CODE (op0
) != INTEGER_CST
;
562 bool ptr2_p
= POINTER_TYPE_P (TREE_TYPE (op1
))
563 && TREE_CODE (op1
) != INTEGER_CST
;
564 int object_size_type
= osi
->object_size_type
;
565 unsigned int varno
= SSA_NAME_VERSION (var
);
566 unsigned HOST_WIDE_INT bytes
;
568 gcc_assert (TREE_CODE (value
) == PLUS_EXPR
);
570 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
573 /* Swap operands if needed. */
574 if (ptr2_p
&& !ptr1_p
)
583 /* Handle PTR + OFFSET here. */
586 && TREE_CODE (op1
) == INTEGER_CST
587 && (TREE_CODE (op0
) == SSA_NAME
588 || TREE_CODE (op0
) == ADDR_EXPR
))
590 if (! host_integerp (op1
, 1))
591 bytes
= unknown
[object_size_type
];
592 else if (TREE_CODE (op0
) == SSA_NAME
)
593 return merge_object_sizes (osi
, var
, op0
, tree_low_cst (op1
, 1));
596 unsigned HOST_WIDE_INT off
= tree_low_cst (op1
, 1);
598 bytes
= compute_builtin_object_size (value
, object_size_type
);
599 if (off
> offset_limit
)
600 bytes
= unknown
[object_size_type
];
601 else if (off
> bytes
)
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
;
617 if (object_sizes
[object_size_type
][varno
] > bytes
)
618 object_sizes
[object_size_type
][varno
] = bytes
;
624 /* Compute object sizes for VAR.
625 For ADDR_EXPR an object size is the number of remaining bytes
626 to the end of the object (where what is considered an object depends on
627 OSI->object_size_type).
628 For allocation CALL_EXPR like malloc or calloc object size is the size
630 For pointer PLUS_EXPR where second operand is a constant integer,
631 object size is object size of the first operand minus the constant.
632 If the constant is bigger than the number of remaining bytes until the
633 end of the object, object size is 0, but if it is instead a pointer
634 subtraction, object size is unknown[object_size_type].
635 To differentiate addition from subtraction, ADDR_EXPR returns
636 unknown[object_size_type] for all objects bigger than half of the address
637 space, and constants less than half of the address space are considered
638 addition, while bigger constants subtraction.
639 For a memcpy like CALL_EXPR that always returns one of its arguments, the
640 object size is object size of that argument.
641 Otherwise, object size is the maximum of object sizes of variables
642 that it might be set to. */
645 collect_object_sizes_for (struct object_size_info
*osi
, tree var
)
647 int object_size_type
= osi
->object_size_type
;
648 unsigned int varno
= SSA_NAME_VERSION (var
);
652 if (bitmap_bit_p (computed
[object_size_type
], varno
))
657 if (! bitmap_bit_p (osi
->visited
, varno
))
659 bitmap_set_bit (osi
->visited
, varno
);
660 object_sizes
[object_size_type
][varno
]
661 = (object_size_type
& 2) ? -1 : 0;
665 /* Found a dependency loop. Mark the variable for later
667 bitmap_set_bit (osi
->reexamine
, varno
);
668 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
670 fprintf (dump_file
, "Found a dependency loop at ");
671 print_generic_expr (dump_file
, var
, dump_flags
);
672 fprintf (dump_file
, "\n");
678 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
680 fprintf (dump_file
, "Visiting use-def links for ");
681 print_generic_expr (dump_file
, var
, dump_flags
);
682 fprintf (dump_file
, "\n");
685 stmt
= SSA_NAME_DEF_STMT (var
);
688 switch (TREE_CODE (stmt
))
691 if (TREE_CODE (TREE_OPERAND (stmt
, 0)) != MODIFY_EXPR
)
693 stmt
= TREE_OPERAND (stmt
, 0);
698 tree rhs
= TREE_OPERAND (stmt
, 1), arg
;
701 if (TREE_CODE (rhs
) == CALL_EXPR
)
703 arg
= pass_through_call (rhs
);
708 if (TREE_CODE (rhs
) == SSA_NAME
709 && POINTER_TYPE_P (TREE_TYPE (rhs
)))
710 reexamine
= merge_object_sizes (osi
, var
, rhs
, 0);
712 else if (TREE_CODE (rhs
) == PLUS_EXPR
)
713 reexamine
= plus_expr_object_size (osi
, var
, rhs
);
716 expr_object_size (osi
, var
, rhs
);
721 /* Pointers defined by __asm__ statements can point anywhere. */
722 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
727 tree decl
= SSA_NAME_VAR (var
);
729 gcc_assert (IS_EMPTY_STMT (stmt
));
731 if (TREE_CODE (decl
) != PARM_DECL
&& DECL_INITIAL (decl
))
732 expr_object_size (osi
, var
, DECL_INITIAL (decl
));
734 expr_object_size (osi
, var
, decl
);
742 for (i
= 0; i
< PHI_NUM_ARGS (stmt
); i
++)
744 tree rhs
= PHI_ARG_DEF (stmt
, i
);
746 if (object_sizes
[object_size_type
][varno
]
747 == unknown
[object_size_type
])
750 if (TREE_CODE (rhs
) == SSA_NAME
)
751 reexamine
|= merge_object_sizes (osi
, var
, rhs
, 0);
752 else if (osi
->pass
== 0)
753 expr_object_size (osi
, var
, rhs
);
762 || object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
764 bitmap_set_bit (computed
[object_size_type
], varno
);
765 bitmap_clear_bit (osi
->reexamine
, varno
);
769 bitmap_set_bit (osi
->reexamine
, varno
);
770 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
772 fprintf (dump_file
, "Need to reexamine ");
773 print_generic_expr (dump_file
, var
, dump_flags
);
774 fprintf (dump_file
, "\n");
780 /* Helper function for check_for_plus_in_loops. Called recursively
784 check_for_plus_in_loops_1 (struct object_size_info
*osi
, tree var
,
787 tree stmt
= SSA_NAME_DEF_STMT (var
);
788 unsigned int varno
= SSA_NAME_VERSION (var
);
790 if (osi
->depths
[varno
])
792 if (osi
->depths
[varno
] != depth
)
796 /* Found a loop involving pointer addition. */
797 for (sp
= osi
->tos
; sp
> osi
->stack
; )
800 bitmap_clear_bit (osi
->reexamine
, *sp
);
801 bitmap_set_bit (computed
[osi
->object_size_type
], *sp
);
802 object_sizes
[osi
->object_size_type
][*sp
] = 0;
809 else if (! bitmap_bit_p (osi
->reexamine
, varno
))
812 osi
->depths
[varno
] = depth
;
815 switch (TREE_CODE (stmt
))
818 if (TREE_CODE (TREE_OPERAND (stmt
, 0)) != MODIFY_EXPR
)
820 stmt
= TREE_OPERAND (stmt
, 0);
825 tree rhs
= TREE_OPERAND (stmt
, 1), arg
;
828 if (TREE_CODE (rhs
) == CALL_EXPR
)
830 arg
= pass_through_call (rhs
);
835 if (TREE_CODE (rhs
) == SSA_NAME
)
836 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
837 else if (TREE_CODE (rhs
) == PLUS_EXPR
)
839 tree op0
= TREE_OPERAND (rhs
, 0);
840 tree op1
= TREE_OPERAND (rhs
, 1);
843 if (TREE_CODE (op0
) == SSA_NAME
)
852 gcc_assert (TREE_CODE (basevar
) == SSA_NAME
);
854 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
856 check_for_plus_in_loops_1 (osi
, basevar
,
857 depth
+ !integer_zerop (cst
));
867 for (i
= 0; i
< PHI_NUM_ARGS (stmt
); i
++)
869 tree rhs
= PHI_ARG_DEF (stmt
, i
);
871 if (TREE_CODE (rhs
) == SSA_NAME
)
872 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
880 osi
->depths
[varno
] = 0;
885 /* Check if some pointer we are computing object size of is being increased
886 within a loop. If yes, assume all the SSA variables participating in
887 that loop have minimum object sizes 0. */
890 check_for_plus_in_loops (struct object_size_info
*osi
, tree var
)
892 tree stmt
= SSA_NAME_DEF_STMT (var
);
894 switch (TREE_CODE (stmt
))
897 if (TREE_CODE (TREE_OPERAND (stmt
, 0)) != MODIFY_EXPR
)
899 stmt
= TREE_OPERAND (stmt
, 0);
904 tree rhs
= TREE_OPERAND (stmt
, 1), arg
;
907 if (TREE_CODE (rhs
) == CALL_EXPR
)
909 arg
= pass_through_call (rhs
);
914 if (TREE_CODE (rhs
) == PLUS_EXPR
)
916 tree op0
= TREE_OPERAND (rhs
, 0);
917 tree op1
= TREE_OPERAND (rhs
, 1);
920 if (TREE_CODE (op0
) == SSA_NAME
)
929 gcc_assert (TREE_CODE (basevar
) == SSA_NAME
);
931 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
933 if (integer_zerop (cst
))
936 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 1;
937 *osi
->tos
++ = SSA_NAME_VERSION (basevar
);
938 check_for_plus_in_loops_1 (osi
, var
, 2);
939 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 0;
950 /* Initialize data structures for the object size computation. */
953 init_object_sizes (void)
955 int object_size_type
;
960 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
962 object_sizes
[object_size_type
]
963 = xmalloc (num_ssa_names
* sizeof (HOST_WIDE_INT
));
964 computed
[object_size_type
] = BITMAP_ALLOC (NULL
);
967 init_offset_limit ();
971 /* Destroy data structures after the object size computation. */
974 fini_object_sizes (void)
976 int object_size_type
;
978 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
980 free (object_sizes
[object_size_type
]);
981 BITMAP_FREE (computed
[object_size_type
]);
982 object_sizes
[object_size_type
] = NULL
;
987 /* Simple pass to optimize all __builtin_object_size () builtins. */
990 compute_object_sizes (void)
995 block_stmt_iterator i
;
996 for (i
= bsi_start (bb
); !bsi_end_p (i
); bsi_next (&i
))
998 tree
*stmtp
= bsi_stmt_ptr (i
);
999 tree call
= get_rhs (*stmtp
);
1000 tree callee
, result
;
1002 if (!call
|| TREE_CODE (call
) != CALL_EXPR
)
1005 callee
= get_callee_fndecl (call
);
1007 || DECL_BUILT_IN_CLASS (callee
) != BUILT_IN_NORMAL
1008 || DECL_FUNCTION_CODE (callee
) != BUILT_IN_OBJECT_SIZE
)
1011 init_object_sizes ();
1012 result
= fold_builtin (callee
, TREE_OPERAND (call
, 1), false);
1015 tree arglist
= TREE_OPERAND (call
, 1);
1018 && POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist
)))
1019 && TREE_CHAIN (arglist
) != NULL
1020 && TREE_CHAIN (TREE_CHAIN (arglist
)) == NULL
)
1022 tree ost
= TREE_VALUE (TREE_CHAIN (arglist
));
1024 if (host_integerp (ost
, 1))
1026 unsigned HOST_WIDE_INT object_size_type
1027 = tree_low_cst (ost
, 1);
1029 if (object_size_type
< 2)
1030 result
= fold_convert (size_type_node
,
1031 integer_minus_one_node
);
1032 else if (object_size_type
< 4)
1033 result
= size_zero_node
;
1041 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1043 fprintf (dump_file
, "Simplified\n ");
1044 print_generic_stmt (dump_file
, *stmtp
, dump_flags
);
1047 if (!set_rhs (stmtp
, result
))
1049 update_stmt (*stmtp
);
1051 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1053 fprintf (dump_file
, "to\n ");
1054 print_generic_stmt (dump_file
, *stmtp
, dump_flags
);
1055 fprintf (dump_file
, "\n");
1060 fini_object_sizes ();
1063 struct tree_opt_pass pass_object_sizes
=
1067 compute_object_sizes
, /* execute */
1070 0, /* static_pass_number */
1072 PROP_cfg
| PROP_ssa
| PROP_alias
, /* properties_required */
1073 0, /* properties_provided */
1074 0, /* properties_destroyed */
1075 0, /* todo_flags_start */
1076 TODO_dump_func
| TODO_verify_ssa
, /* todo_flags_finish */