1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004, 2005, 2006, 2007 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 3, 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 COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #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 (const_tree
, const_tree
);
45 static unsigned HOST_WIDE_INT
addr_object_size (const_tree
, int);
46 static unsigned HOST_WIDE_INT
alloc_object_size (const_tree
, int);
47 static tree
pass_through_call (const_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 (const_tree expr
, const_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)
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
= fold_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 (const_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 (const_tree call
, int object_size_type
)
230 tree callee
, bytes
= NULL_TREE
;
232 int arg1
= -1, arg2
= -1;
234 gcc_assert (TREE_CODE (call
) == CALL_EXPR
);
236 callee
= get_callee_fndecl (call
);
238 return unknown
[object_size_type
];
240 alloc_size
= lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee
)));
241 if (alloc_size
&& TREE_VALUE (alloc_size
))
243 tree p
= TREE_VALUE (alloc_size
);
245 arg1
= TREE_INT_CST_LOW (TREE_VALUE (p
))-1;
247 arg2
= TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p
)))-1;
250 if (DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
251 switch (DECL_FUNCTION_CODE (callee
))
253 case BUILT_IN_CALLOC
:
256 case BUILT_IN_MALLOC
:
257 case BUILT_IN_ALLOCA
:
263 if (arg1
< 0 || arg1
>= call_expr_nargs (call
)
264 || TREE_CODE (CALL_EXPR_ARG (call
, arg1
)) != INTEGER_CST
266 && (arg2
>= call_expr_nargs (call
)
267 || TREE_CODE (CALL_EXPR_ARG (call
, arg2
)) != INTEGER_CST
)))
268 return unknown
[object_size_type
];
271 bytes
= size_binop (MULT_EXPR
,
272 fold_convert (sizetype
, CALL_EXPR_ARG (call
, arg1
)),
273 fold_convert (sizetype
, CALL_EXPR_ARG (call
, arg2
)));
275 bytes
= fold_convert (sizetype
, CALL_EXPR_ARG (call
, arg1
));
277 if (bytes
&& host_integerp (bytes
, 1))
278 return tree_low_cst (bytes
, 1);
280 return unknown
[object_size_type
];
284 /* If object size is propagated from one of function's arguments directly
285 to its return value, return that argument for CALL_EXPR CALL.
286 Otherwise return NULL. */
289 pass_through_call (const_tree call
)
291 tree callee
= get_callee_fndecl (call
);
294 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
295 switch (DECL_FUNCTION_CODE (callee
))
297 case BUILT_IN_MEMCPY
:
298 case BUILT_IN_MEMMOVE
:
299 case BUILT_IN_MEMSET
:
300 case BUILT_IN_STRCPY
:
301 case BUILT_IN_STRNCPY
:
302 case BUILT_IN_STRCAT
:
303 case BUILT_IN_STRNCAT
:
304 case BUILT_IN_MEMCPY_CHK
:
305 case BUILT_IN_MEMMOVE_CHK
:
306 case BUILT_IN_MEMSET_CHK
:
307 case BUILT_IN_STRCPY_CHK
:
308 case BUILT_IN_STRNCPY_CHK
:
309 case BUILT_IN_STRCAT_CHK
:
310 case BUILT_IN_STRNCAT_CHK
:
311 if (call_expr_nargs (call
) >= 1)
312 return CALL_EXPR_ARG (call
, 0);
322 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
323 second argument from __builtin_object_size. */
325 unsigned HOST_WIDE_INT
326 compute_builtin_object_size (tree ptr
, int object_size_type
)
328 gcc_assert (object_size_type
>= 0 && object_size_type
<= 3);
331 init_offset_limit ();
333 if (TREE_CODE (ptr
) == ADDR_EXPR
)
334 return addr_object_size (ptr
, object_size_type
);
335 else if (TREE_CODE (ptr
) == CALL_EXPR
)
337 tree arg
= pass_through_call (ptr
);
340 return compute_builtin_object_size (arg
, object_size_type
);
342 return alloc_object_size (ptr
, object_size_type
);
344 else if (TREE_CODE (ptr
) == SSA_NAME
345 && POINTER_TYPE_P (TREE_TYPE (ptr
))
346 && object_sizes
[object_size_type
] != NULL
)
348 if (!bitmap_bit_p (computed
[object_size_type
], SSA_NAME_VERSION (ptr
)))
350 struct object_size_info osi
;
356 fprintf (dump_file
, "Computing %s %sobject size for ",
357 (object_size_type
& 2) ? "minimum" : "maximum",
358 (object_size_type
& 1) ? "sub" : "");
359 print_generic_expr (dump_file
, ptr
, dump_flags
);
360 fprintf (dump_file
, ":\n");
363 osi
.visited
= BITMAP_ALLOC (NULL
);
364 osi
.reexamine
= BITMAP_ALLOC (NULL
);
365 osi
.object_size_type
= object_size_type
;
370 /* First pass: walk UD chains, compute object sizes that
371 can be computed. osi.reexamine bitmap at the end will
372 contain what variables were found in dependency cycles
373 and therefore need to be reexamined. */
376 collect_object_sizes_for (&osi
, ptr
);
378 /* Second pass: keep recomputing object sizes of variables
379 that need reexamination, until no object sizes are
380 increased or all object sizes are computed. */
381 if (! bitmap_empty_p (osi
.reexamine
))
383 bitmap reexamine
= BITMAP_ALLOC (NULL
);
385 /* If looking for minimum instead of maximum object size,
386 detect cases where a pointer is increased in a loop.
387 Although even without this detection pass 2 would eventually
388 terminate, it could take a long time. If a pointer is
389 increasing this way, we need to assume 0 object size.
390 E.g. p = &buf[0]; while (cond) p = p + 4; */
391 if (object_size_type
& 2)
393 osi
.depths
= XCNEWVEC (unsigned int, num_ssa_names
);
394 osi
.stack
= XNEWVEC (unsigned int, num_ssa_names
);
397 /* collect_object_sizes_for is changing
398 osi.reexamine bitmap, so iterate over a copy. */
399 bitmap_copy (reexamine
, osi
.reexamine
);
400 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
401 if (bitmap_bit_p (osi
.reexamine
, i
))
402 check_for_plus_in_loops (&osi
, ssa_name (i
));
415 /* collect_object_sizes_for is changing
416 osi.reexamine bitmap, so iterate over a copy. */
417 bitmap_copy (reexamine
, osi
.reexamine
);
418 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
419 if (bitmap_bit_p (osi
.reexamine
, i
))
421 collect_object_sizes_for (&osi
, ssa_name (i
));
422 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
424 fprintf (dump_file
, "Reexamining ");
425 print_generic_expr (dump_file
, ssa_name (i
),
427 fprintf (dump_file
, "\n");
433 BITMAP_FREE (reexamine
);
435 EXECUTE_IF_SET_IN_BITMAP (osi
.reexamine
, 0, i
, bi
)
436 bitmap_set_bit (computed
[object_size_type
], i
);
438 /* Debugging dumps. */
441 EXECUTE_IF_SET_IN_BITMAP (osi
.visited
, 0, i
, bi
)
442 if (object_sizes
[object_size_type
][i
]
443 != unknown
[object_size_type
])
445 print_generic_expr (dump_file
, ssa_name (i
),
448 ": %s %sobject size "
449 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
450 (object_size_type
& 2) ? "minimum" : "maximum",
451 (object_size_type
& 1) ? "sub" : "",
452 object_sizes
[object_size_type
][i
]);
456 BITMAP_FREE (osi
.reexamine
);
457 BITMAP_FREE (osi
.visited
);
460 return object_sizes
[object_size_type
][SSA_NAME_VERSION (ptr
)];
463 return unknown
[object_size_type
];
467 /* Compute object_sizes for PTR, defined to VALUE, which is not
471 expr_object_size (struct object_size_info
*osi
, tree ptr
, tree value
)
473 int object_size_type
= osi
->object_size_type
;
474 unsigned int varno
= SSA_NAME_VERSION (ptr
);
475 unsigned HOST_WIDE_INT bytes
;
477 gcc_assert (object_sizes
[object_size_type
][varno
]
478 != unknown
[object_size_type
]);
479 gcc_assert (osi
->pass
== 0);
481 if (TREE_CODE (value
) == WITH_SIZE_EXPR
)
482 value
= TREE_OPERAND (value
, 0);
484 /* Pointer variables should have been handled by merge_object_sizes. */
485 gcc_assert (TREE_CODE (value
) != SSA_NAME
486 || !POINTER_TYPE_P (TREE_TYPE (value
)));
488 if (TREE_CODE (value
) == ADDR_EXPR
)
489 bytes
= addr_object_size (value
, object_size_type
);
490 else if (TREE_CODE (value
) == CALL_EXPR
)
491 bytes
= alloc_object_size (value
, object_size_type
);
493 bytes
= unknown
[object_size_type
];
495 if ((object_size_type
& 2) == 0)
497 if (object_sizes
[object_size_type
][varno
] < bytes
)
498 object_sizes
[object_size_type
][varno
] = bytes
;
502 if (object_sizes
[object_size_type
][varno
] > bytes
)
503 object_sizes
[object_size_type
][varno
] = bytes
;
508 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
509 the object size might need reexamination later. */
512 merge_object_sizes (struct object_size_info
*osi
, tree dest
, tree orig
,
513 unsigned HOST_WIDE_INT offset
)
515 int object_size_type
= osi
->object_size_type
;
516 unsigned int varno
= SSA_NAME_VERSION (dest
);
517 unsigned HOST_WIDE_INT orig_bytes
;
519 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
521 if (offset
>= offset_limit
)
523 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
528 collect_object_sizes_for (osi
, orig
);
530 orig_bytes
= object_sizes
[object_size_type
][SSA_NAME_VERSION (orig
)];
531 if (orig_bytes
!= unknown
[object_size_type
])
532 orig_bytes
= (offset
> orig_bytes
)
533 ? (unsigned HOST_WIDE_INT
) 0 : orig_bytes
- offset
;
535 if ((object_size_type
& 2) == 0)
537 if (object_sizes
[object_size_type
][varno
] < orig_bytes
)
539 object_sizes
[object_size_type
][varno
] = orig_bytes
;
545 if (object_sizes
[object_size_type
][varno
] > orig_bytes
)
547 object_sizes
[object_size_type
][varno
] = orig_bytes
;
551 return bitmap_bit_p (osi
->reexamine
, SSA_NAME_VERSION (orig
));
555 /* Compute object_sizes for PTR, defined to VALUE, which is
556 a POINTER_PLUS_EXPR. Return true if the object size might need reexamination
560 plus_expr_object_size (struct object_size_info
*osi
, tree var
, tree value
)
562 tree op0
= TREE_OPERAND (value
, 0);
563 tree op1
= TREE_OPERAND (value
, 1);
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
) == POINTER_PLUS_EXPR
);
570 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
573 /* Handle PTR + OFFSET here. */
574 if (TREE_CODE (op1
) == INTEGER_CST
575 && (TREE_CODE (op0
) == SSA_NAME
576 || TREE_CODE (op0
) == ADDR_EXPR
))
578 if (! host_integerp (op1
, 1))
579 bytes
= unknown
[object_size_type
];
580 else if (TREE_CODE (op0
) == SSA_NAME
)
581 return merge_object_sizes (osi
, var
, op0
, tree_low_cst (op1
, 1));
584 unsigned HOST_WIDE_INT off
= tree_low_cst (op1
, 1);
586 bytes
= compute_builtin_object_size (op0
, object_size_type
);
587 if (bytes
== unknown
[object_size_type
])
589 else if (off
> offset_limit
)
590 bytes
= unknown
[object_size_type
];
591 else if (off
> bytes
)
598 bytes
= unknown
[object_size_type
];
600 if ((object_size_type
& 2) == 0)
602 if (object_sizes
[object_size_type
][varno
] < bytes
)
603 object_sizes
[object_size_type
][varno
] = bytes
;
607 if (object_sizes
[object_size_type
][varno
] > bytes
)
608 object_sizes
[object_size_type
][varno
] = bytes
;
614 /* Compute object_sizes for PTR, defined to VALUE, which is
615 a COND_EXPR. Return true if the object size might need reexamination
619 cond_expr_object_size (struct object_size_info
*osi
, tree var
, tree value
)
622 int object_size_type
= osi
->object_size_type
;
623 unsigned int varno
= SSA_NAME_VERSION (var
);
624 bool reexamine
= false;
626 gcc_assert (TREE_CODE (value
) == COND_EXPR
);
628 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
631 then_
= COND_EXPR_THEN (value
);
632 else_
= COND_EXPR_ELSE (value
);
634 if (TREE_CODE (then_
) == SSA_NAME
)
635 reexamine
|= merge_object_sizes (osi
, var
, then_
, 0);
637 expr_object_size (osi
, var
, then_
);
639 if (TREE_CODE (else_
) == SSA_NAME
)
640 reexamine
|= merge_object_sizes (osi
, var
, else_
, 0);
642 expr_object_size (osi
, var
, else_
);
648 /* Compute object sizes for VAR.
649 For ADDR_EXPR an object size is the number of remaining bytes
650 to the end of the object (where what is considered an object depends on
651 OSI->object_size_type).
652 For allocation CALL_EXPR like malloc or calloc object size is the size
654 For POINTER_PLUS_EXPR where second operand is a constant integer,
655 object size is object size of the first operand minus the constant.
656 If the constant is bigger than the number of remaining bytes until the
657 end of the object, object size is 0, but if it is instead a pointer
658 subtraction, object size is unknown[object_size_type].
659 To differentiate addition from subtraction, ADDR_EXPR returns
660 unknown[object_size_type] for all objects bigger than half of the address
661 space, and constants less than half of the address space are considered
662 addition, while bigger constants subtraction.
663 For a memcpy like CALL_EXPR that always returns one of its arguments, the
664 object size is object size of that argument.
665 Otherwise, object size is the maximum of object sizes of variables
666 that it might be set to. */
669 collect_object_sizes_for (struct object_size_info
*osi
, tree var
)
671 int object_size_type
= osi
->object_size_type
;
672 unsigned int varno
= SSA_NAME_VERSION (var
);
676 if (bitmap_bit_p (computed
[object_size_type
], varno
))
681 if (! bitmap_bit_p (osi
->visited
, varno
))
683 bitmap_set_bit (osi
->visited
, varno
);
684 object_sizes
[object_size_type
][varno
]
685 = (object_size_type
& 2) ? -1 : 0;
689 /* Found a dependency loop. Mark the variable for later
691 bitmap_set_bit (osi
->reexamine
, varno
);
692 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
694 fprintf (dump_file
, "Found a dependency loop at ");
695 print_generic_expr (dump_file
, var
, dump_flags
);
696 fprintf (dump_file
, "\n");
702 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
704 fprintf (dump_file
, "Visiting use-def links for ");
705 print_generic_expr (dump_file
, var
, dump_flags
);
706 fprintf (dump_file
, "\n");
709 stmt
= SSA_NAME_DEF_STMT (var
);
712 switch (TREE_CODE (stmt
))
715 gcc_assert (TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
);
716 stmt
= TREE_OPERAND (stmt
, 0);
719 case GIMPLE_MODIFY_STMT
:
721 tree rhs
= GIMPLE_STMT_OPERAND (stmt
, 1), arg
;
724 if (TREE_CODE (rhs
) == CALL_EXPR
)
726 arg
= pass_through_call (rhs
);
731 if (TREE_CODE (rhs
) == SSA_NAME
732 && POINTER_TYPE_P (TREE_TYPE (rhs
)))
733 reexamine
= merge_object_sizes (osi
, var
, rhs
, 0);
735 else if (TREE_CODE (rhs
) == POINTER_PLUS_EXPR
)
736 reexamine
= plus_expr_object_size (osi
, var
, rhs
);
738 else if (TREE_CODE (rhs
) == COND_EXPR
)
739 reexamine
= cond_expr_object_size (osi
, var
, rhs
);
742 expr_object_size (osi
, var
, rhs
);
747 /* Pointers defined by __asm__ statements can point anywhere. */
748 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
753 tree decl
= SSA_NAME_VAR (var
);
755 gcc_assert (IS_EMPTY_STMT (stmt
));
757 if (TREE_CODE (decl
) != PARM_DECL
&& DECL_INITIAL (decl
))
758 expr_object_size (osi
, var
, DECL_INITIAL (decl
));
760 expr_object_size (osi
, var
, decl
);
768 for (i
= 0; i
< PHI_NUM_ARGS (stmt
); i
++)
770 tree rhs
= PHI_ARG_DEF (stmt
, i
);
772 if (object_sizes
[object_size_type
][varno
]
773 == unknown
[object_size_type
])
776 if (TREE_CODE (rhs
) == SSA_NAME
)
777 reexamine
|= merge_object_sizes (osi
, var
, rhs
, 0);
778 else if (osi
->pass
== 0)
779 expr_object_size (osi
, var
, rhs
);
788 || object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
790 bitmap_set_bit (computed
[object_size_type
], varno
);
791 bitmap_clear_bit (osi
->reexamine
, varno
);
795 bitmap_set_bit (osi
->reexamine
, varno
);
796 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
798 fprintf (dump_file
, "Need to reexamine ");
799 print_generic_expr (dump_file
, var
, dump_flags
);
800 fprintf (dump_file
, "\n");
806 /* Helper function for check_for_plus_in_loops. Called recursively
810 check_for_plus_in_loops_1 (struct object_size_info
*osi
, tree var
,
813 tree stmt
= SSA_NAME_DEF_STMT (var
);
814 unsigned int varno
= SSA_NAME_VERSION (var
);
816 if (osi
->depths
[varno
])
818 if (osi
->depths
[varno
] != depth
)
822 /* Found a loop involving pointer addition. */
823 for (sp
= osi
->tos
; sp
> osi
->stack
; )
826 bitmap_clear_bit (osi
->reexamine
, *sp
);
827 bitmap_set_bit (computed
[osi
->object_size_type
], *sp
);
828 object_sizes
[osi
->object_size_type
][*sp
] = 0;
835 else if (! bitmap_bit_p (osi
->reexamine
, varno
))
838 osi
->depths
[varno
] = depth
;
841 switch (TREE_CODE (stmt
))
844 gcc_assert (TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
);
845 stmt
= TREE_OPERAND (stmt
, 0);
848 case GIMPLE_MODIFY_STMT
:
850 tree rhs
= GIMPLE_STMT_OPERAND (stmt
, 1), arg
;
853 if (TREE_CODE (rhs
) == CALL_EXPR
)
855 arg
= pass_through_call (rhs
);
860 if (TREE_CODE (rhs
) == SSA_NAME
)
861 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
862 else if (TREE_CODE (rhs
) == POINTER_PLUS_EXPR
)
864 tree op0
= TREE_OPERAND (rhs
, 0);
865 tree op1
= TREE_OPERAND (rhs
, 1);
870 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
872 check_for_plus_in_loops_1 (osi
, basevar
,
873 depth
+ !integer_zerop (cst
));
883 for (i
= 0; i
< PHI_NUM_ARGS (stmt
); i
++)
885 tree rhs
= PHI_ARG_DEF (stmt
, i
);
887 if (TREE_CODE (rhs
) == SSA_NAME
)
888 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
896 osi
->depths
[varno
] = 0;
901 /* Check if some pointer we are computing object size of is being increased
902 within a loop. If yes, assume all the SSA variables participating in
903 that loop have minimum object sizes 0. */
906 check_for_plus_in_loops (struct object_size_info
*osi
, tree var
)
908 tree stmt
= SSA_NAME_DEF_STMT (var
);
910 switch (TREE_CODE (stmt
))
913 gcc_assert (TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
);
914 stmt
= TREE_OPERAND (stmt
, 0);
917 case GIMPLE_MODIFY_STMT
:
919 tree rhs
= GIMPLE_STMT_OPERAND (stmt
, 1), arg
;
922 if (TREE_CODE (rhs
) == CALL_EXPR
)
924 arg
= pass_through_call (rhs
);
929 if (TREE_CODE (rhs
) == POINTER_PLUS_EXPR
)
931 tree op0
= TREE_OPERAND (rhs
, 0);
932 tree op1
= TREE_OPERAND (rhs
, 1);
937 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
939 if (integer_zerop (cst
))
942 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 1;
943 *osi
->tos
++ = SSA_NAME_VERSION (basevar
);
944 check_for_plus_in_loops_1 (osi
, var
, 2);
945 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 0;
956 /* Initialize data structures for the object size computation. */
959 init_object_sizes (void)
961 int object_size_type
;
966 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
968 object_sizes
[object_size_type
] = XNEWVEC (unsigned HOST_WIDE_INT
, num_ssa_names
);
969 computed
[object_size_type
] = BITMAP_ALLOC (NULL
);
972 init_offset_limit ();
976 /* Destroy data structures after the object size computation. */
979 fini_object_sizes (void)
981 int object_size_type
;
983 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
985 free (object_sizes
[object_size_type
]);
986 BITMAP_FREE (computed
[object_size_type
]);
987 object_sizes
[object_size_type
] = NULL
;
992 /* Simple pass to optimize all __builtin_object_size () builtins. */
995 compute_object_sizes (void)
1000 block_stmt_iterator i
;
1001 for (i
= bsi_start (bb
); !bsi_end_p (i
); bsi_next (&i
))
1003 tree
*stmtp
= bsi_stmt_ptr (i
);
1004 tree call
= get_rhs (*stmtp
);
1005 tree callee
, result
;
1007 if (!call
|| TREE_CODE (call
) != CALL_EXPR
)
1010 callee
= get_callee_fndecl (call
);
1012 || DECL_BUILT_IN_CLASS (callee
) != BUILT_IN_NORMAL
1013 || DECL_FUNCTION_CODE (callee
) != BUILT_IN_OBJECT_SIZE
)
1016 init_object_sizes ();
1017 result
= fold_call_expr (call
, false);
1020 if (call_expr_nargs (call
) == 2
1021 && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (call
, 0))))
1023 tree ost
= CALL_EXPR_ARG (call
, 1);
1025 if (host_integerp (ost
, 1))
1027 unsigned HOST_WIDE_INT object_size_type
1028 = tree_low_cst (ost
, 1);
1030 if (object_size_type
< 2)
1031 result
= fold_convert (size_type_node
,
1032 integer_minus_one_node
);
1033 else if (object_size_type
< 4)
1034 result
= size_zero_node
;
1042 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1044 fprintf (dump_file
, "Simplified\n ");
1045 print_generic_stmt (dump_file
, *stmtp
, dump_flags
);
1048 if (!set_rhs (stmtp
, result
))
1050 update_stmt (*stmtp
);
1052 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1054 fprintf (dump_file
, "to\n ");
1055 print_generic_stmt (dump_file
, *stmtp
, dump_flags
);
1056 fprintf (dump_file
, "\n");
1061 fini_object_sizes ();
1065 struct gimple_opt_pass pass_object_sizes
=
1071 compute_object_sizes
, /* execute */
1074 0, /* static_pass_number */
1076 PROP_cfg
| PROP_ssa
| PROP_alias
, /* properties_required */
1077 0, /* properties_provided */
1078 0, /* properties_destroyed */
1079 0, /* todo_flags_start */
1080 TODO_dump_func
| TODO_verify_ssa
/* todo_flags_finish */