1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Jakub Jelinek <jakub@redhat.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
27 #include "diagnostic-core.h"
28 #include "tree-pretty-print.h"
29 #include "gimple-pretty-print.h"
30 #include "tree-flow.h"
31 #include "tree-pass.h"
32 #include "tree-ssa-propagate.h"
34 struct object_size_info
37 bitmap visited
, reexamine
;
41 unsigned int *stack
, *tos
;
44 static unsigned HOST_WIDE_INT unknown
[4] = { -1, -1, 0, 0 };
46 static tree
compute_object_offset (const_tree
, const_tree
);
47 static unsigned HOST_WIDE_INT
addr_object_size (struct object_size_info
*,
49 static unsigned HOST_WIDE_INT
alloc_object_size (const_gimple
, int);
50 static tree
pass_through_call (const_gimple
);
51 static void collect_object_sizes_for (struct object_size_info
*, tree
);
52 static void expr_object_size (struct object_size_info
*, tree
, tree
);
53 static bool merge_object_sizes (struct object_size_info
*, tree
, tree
,
54 unsigned HOST_WIDE_INT
);
55 static bool plus_stmt_object_size (struct object_size_info
*, tree
, gimple
);
56 static bool cond_expr_object_size (struct object_size_info
*, tree
, tree
);
57 static unsigned int compute_object_sizes (void);
58 static void init_offset_limit (void);
59 static void check_for_plus_in_loops (struct object_size_info
*, tree
);
60 static void check_for_plus_in_loops_1 (struct object_size_info
*, tree
,
63 /* object_sizes[0] is upper bound for number of bytes till the end of
65 object_sizes[1] is upper bound for number of bytes till the end of
66 the subobject (innermost array or field with address taken).
67 object_sizes[2] is lower bound for number of bytes till the end of
68 the object and object_sizes[3] lower bound for subobject. */
69 static unsigned HOST_WIDE_INT
*object_sizes
[4];
71 /* Bitmaps what object sizes have been computed already. */
72 static bitmap computed
[4];
74 /* Maximum value of offset we consider to be addition. */
75 static unsigned HOST_WIDE_INT offset_limit
;
78 /* Initialize OFFSET_LIMIT variable. */
80 init_offset_limit (void)
82 if (host_integerp (TYPE_MAX_VALUE (sizetype
), 1))
83 offset_limit
= tree_low_cst (TYPE_MAX_VALUE (sizetype
), 1);
90 /* Compute offset of EXPR within VAR. Return error_mark_node
94 compute_object_offset (const_tree expr
, const_tree var
)
96 enum tree_code code
= PLUS_EXPR
;
100 return size_zero_node
;
102 switch (TREE_CODE (expr
))
105 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
106 if (base
== error_mark_node
)
109 t
= TREE_OPERAND (expr
, 1);
110 off
= size_binop (PLUS_EXPR
, DECL_FIELD_OFFSET (t
),
111 size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t
), 1)
117 case VIEW_CONVERT_EXPR
:
118 case NON_LVALUE_EXPR
:
119 return compute_object_offset (TREE_OPERAND (expr
, 0), var
);
122 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
123 if (base
== error_mark_node
)
126 off
= TYPE_SIZE_UNIT (TREE_TYPE (expr
));
130 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
131 if (base
== error_mark_node
)
134 t
= TREE_OPERAND (expr
, 1);
135 if (TREE_CODE (t
) == INTEGER_CST
&& tree_int_cst_sgn (t
) < 0)
138 t
= fold_build1 (NEGATE_EXPR
, TREE_TYPE (t
), t
);
140 t
= fold_convert (sizetype
, t
);
141 off
= size_binop (MULT_EXPR
, TYPE_SIZE_UNIT (TREE_TYPE (expr
)), t
);
145 gcc_assert (TREE_CODE (TREE_OPERAND (expr
, 0)) == ADDR_EXPR
);
146 return double_int_to_tree (sizetype
, mem_ref_offset (expr
));
149 return error_mark_node
;
152 return size_binop (code
, base
, off
);
156 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
157 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
158 If unknown, return unknown[object_size_type]. */
160 static unsigned HOST_WIDE_INT
161 addr_object_size (struct object_size_info
*osi
, const_tree ptr
,
162 int object_size_type
)
164 tree pt_var
, pt_var_size
= NULL_TREE
, var_size
, bytes
;
166 gcc_assert (TREE_CODE (ptr
) == ADDR_EXPR
);
168 pt_var
= TREE_OPERAND (ptr
, 0);
169 if (REFERENCE_CLASS_P (pt_var
))
170 pt_var
= get_base_address (pt_var
);
173 && TREE_CODE (pt_var
) == MEM_REF
174 && TREE_CODE (TREE_OPERAND (pt_var
, 0)) == SSA_NAME
175 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (pt_var
, 0))))
177 unsigned HOST_WIDE_INT sz
;
179 if (!osi
|| (object_size_type
& 1) != 0)
181 sz
= compute_builtin_object_size (TREE_OPERAND (pt_var
, 0),
182 object_size_type
& ~1);
183 if (host_integerp (TREE_OPERAND (pt_var
, 1), 0))
184 sz
-= TREE_INT_CST_LOW (TREE_OPERAND (pt_var
, 1));
190 tree var
= TREE_OPERAND (pt_var
, 0);
192 collect_object_sizes_for (osi
, var
);
193 if (bitmap_bit_p (computed
[object_size_type
],
194 SSA_NAME_VERSION (var
)))
195 sz
= object_sizes
[object_size_type
][SSA_NAME_VERSION (var
)];
197 sz
= unknown
[object_size_type
];
198 if (host_integerp (TREE_OPERAND (pt_var
, 1), 0))
199 sz
-= TREE_INT_CST_LOW (TREE_OPERAND (pt_var
, 1));
204 if (sz
!= unknown
[object_size_type
] && sz
< offset_limit
)
205 pt_var_size
= size_int (sz
);
208 && (SSA_VAR_P (pt_var
) || TREE_CODE (pt_var
) == STRING_CST
)
209 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var
))
210 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)), 1)
211 && (unsigned HOST_WIDE_INT
)
212 tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)), 1)
214 pt_var_size
= TYPE_SIZE_UNIT (TREE_TYPE (pt_var
));
216 return unknown
[object_size_type
];
218 if (pt_var
!= TREE_OPERAND (ptr
, 0))
222 if (object_size_type
& 1)
224 var
= TREE_OPERAND (ptr
, 0);
227 && TREE_CODE (var
) != BIT_FIELD_REF
228 && TREE_CODE (var
) != COMPONENT_REF
229 && TREE_CODE (var
) != ARRAY_REF
230 && TREE_CODE (var
) != ARRAY_RANGE_REF
231 && TREE_CODE (var
) != REALPART_EXPR
232 && TREE_CODE (var
) != IMAGPART_EXPR
)
233 var
= TREE_OPERAND (var
, 0);
234 if (var
!= pt_var
&& TREE_CODE (var
) == ARRAY_REF
)
235 var
= TREE_OPERAND (var
, 0);
236 if (! TYPE_SIZE_UNIT (TREE_TYPE (var
))
237 || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var
)), 1)
239 && tree_int_cst_lt (pt_var_size
,
240 TYPE_SIZE_UNIT (TREE_TYPE (var
)))))
242 else if (var
!= pt_var
&& TREE_CODE (pt_var
) == MEM_REF
)
245 /* For &X->fld, compute object size only if fld isn't the last
246 field, as struct { int i; char c[1]; } is often used instead
247 of flexible array member. */
248 while (v
&& v
!= pt_var
)
249 switch (TREE_CODE (v
))
252 if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v
, 0)))
253 && TREE_CODE (TREE_OPERAND (v
, 1)) == INTEGER_CST
)
256 = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v
, 0)));
258 && TYPE_MAX_VALUE (domain
)
259 && TREE_CODE (TYPE_MAX_VALUE (domain
))
261 && tree_int_cst_lt (TREE_OPERAND (v
, 1),
262 TYPE_MAX_VALUE (domain
)))
268 v
= TREE_OPERAND (v
, 0);
275 if (TREE_CODE (TREE_TYPE (v
)) != ARRAY_TYPE
)
280 while (v
!= pt_var
&& TREE_CODE (v
) == COMPONENT_REF
)
281 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
283 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
287 v
= TREE_OPERAND (v
, 0);
288 if (TREE_CODE (v
) == COMPONENT_REF
289 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
292 tree fld_chain
= DECL_CHAIN (TREE_OPERAND (v
, 1));
293 for (; fld_chain
; fld_chain
= DECL_CHAIN (fld_chain
))
294 if (TREE_CODE (fld_chain
) == FIELD_DECL
)
302 v
= TREE_OPERAND (v
, 0);
304 while (v
!= pt_var
&& TREE_CODE (v
) == COMPONENT_REF
)
305 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
307 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
311 v
= TREE_OPERAND (v
, 0);
329 var_size
= TYPE_SIZE_UNIT (TREE_TYPE (var
));
330 else if (!pt_var_size
)
331 return unknown
[object_size_type
];
333 var_size
= pt_var_size
;
334 bytes
= compute_object_offset (TREE_OPERAND (ptr
, 0), var
);
335 if (bytes
!= error_mark_node
)
337 if (TREE_CODE (bytes
) == INTEGER_CST
338 && tree_int_cst_lt (var_size
, bytes
))
339 bytes
= size_zero_node
;
341 bytes
= size_binop (MINUS_EXPR
, var_size
, bytes
);
345 && TREE_CODE (pt_var
) == MEM_REF
346 && bytes
!= error_mark_node
)
348 tree bytes2
= compute_object_offset (TREE_OPERAND (ptr
, 0), pt_var
);
349 if (bytes2
!= error_mark_node
)
351 if (TREE_CODE (bytes2
) == INTEGER_CST
352 && tree_int_cst_lt (pt_var_size
, bytes2
))
353 bytes2
= size_zero_node
;
355 bytes2
= size_binop (MINUS_EXPR
, pt_var_size
, bytes2
);
356 bytes
= size_binop (MIN_EXPR
, bytes
, bytes2
);
360 else if (!pt_var_size
)
361 return unknown
[object_size_type
];
365 if (host_integerp (bytes
, 1))
366 return tree_low_cst (bytes
, 1);
368 return unknown
[object_size_type
];
372 /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
373 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
374 argument from __builtin_object_size. If unknown, return
375 unknown[object_size_type]. */
377 static unsigned HOST_WIDE_INT
378 alloc_object_size (const_gimple call
, int object_size_type
)
380 tree callee
, bytes
= NULL_TREE
;
382 int arg1
= -1, arg2
= -1;
384 gcc_assert (is_gimple_call (call
));
386 callee
= gimple_call_fndecl (call
);
388 return unknown
[object_size_type
];
390 alloc_size
= lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee
)));
391 if (alloc_size
&& TREE_VALUE (alloc_size
))
393 tree p
= TREE_VALUE (alloc_size
);
395 arg1
= TREE_INT_CST_LOW (TREE_VALUE (p
))-1;
397 arg2
= TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p
)))-1;
400 if (DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
401 switch (DECL_FUNCTION_CODE (callee
))
403 case BUILT_IN_CALLOC
:
406 case BUILT_IN_MALLOC
:
407 case BUILT_IN_ALLOCA
:
413 if (arg1
< 0 || arg1
>= (int)gimple_call_num_args (call
)
414 || TREE_CODE (gimple_call_arg (call
, arg1
)) != INTEGER_CST
416 && (arg2
>= (int)gimple_call_num_args (call
)
417 || TREE_CODE (gimple_call_arg (call
, arg2
)) != INTEGER_CST
)))
418 return unknown
[object_size_type
];
421 bytes
= size_binop (MULT_EXPR
,
422 fold_convert (sizetype
, gimple_call_arg (call
, arg1
)),
423 fold_convert (sizetype
, gimple_call_arg (call
, arg2
)));
425 bytes
= fold_convert (sizetype
, gimple_call_arg (call
, arg1
));
427 if (bytes
&& host_integerp (bytes
, 1))
428 return tree_low_cst (bytes
, 1);
430 return unknown
[object_size_type
];
434 /* If object size is propagated from one of function's arguments directly
435 to its return value, return that argument for GIMPLE_CALL statement CALL.
436 Otherwise return NULL. */
439 pass_through_call (const_gimple call
)
441 tree callee
= gimple_call_fndecl (call
);
444 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
445 switch (DECL_FUNCTION_CODE (callee
))
447 case BUILT_IN_MEMCPY
:
448 case BUILT_IN_MEMMOVE
:
449 case BUILT_IN_MEMSET
:
450 case BUILT_IN_STRCPY
:
451 case BUILT_IN_STRNCPY
:
452 case BUILT_IN_STRCAT
:
453 case BUILT_IN_STRNCAT
:
454 case BUILT_IN_MEMCPY_CHK
:
455 case BUILT_IN_MEMMOVE_CHK
:
456 case BUILT_IN_MEMSET_CHK
:
457 case BUILT_IN_STRCPY_CHK
:
458 case BUILT_IN_STRNCPY_CHK
:
459 case BUILT_IN_STRCAT_CHK
:
460 case BUILT_IN_STRNCAT_CHK
:
461 if (gimple_call_num_args (call
) >= 1)
462 return gimple_call_arg (call
, 0);
472 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
473 second argument from __builtin_object_size. */
475 unsigned HOST_WIDE_INT
476 compute_builtin_object_size (tree ptr
, int object_size_type
)
478 gcc_assert (object_size_type
>= 0 && object_size_type
<= 3);
481 init_offset_limit ();
483 if (TREE_CODE (ptr
) == ADDR_EXPR
)
484 return addr_object_size (NULL
, ptr
, object_size_type
);
486 if (TREE_CODE (ptr
) == SSA_NAME
487 && POINTER_TYPE_P (TREE_TYPE (ptr
))
488 && object_sizes
[object_size_type
] != NULL
)
490 if (!bitmap_bit_p (computed
[object_size_type
], SSA_NAME_VERSION (ptr
)))
492 struct object_size_info osi
;
498 fprintf (dump_file
, "Computing %s %sobject size for ",
499 (object_size_type
& 2) ? "minimum" : "maximum",
500 (object_size_type
& 1) ? "sub" : "");
501 print_generic_expr (dump_file
, ptr
, dump_flags
);
502 fprintf (dump_file
, ":\n");
505 osi
.visited
= BITMAP_ALLOC (NULL
);
506 osi
.reexamine
= BITMAP_ALLOC (NULL
);
507 osi
.object_size_type
= object_size_type
;
512 /* First pass: walk UD chains, compute object sizes that
513 can be computed. osi.reexamine bitmap at the end will
514 contain what variables were found in dependency cycles
515 and therefore need to be reexamined. */
518 collect_object_sizes_for (&osi
, ptr
);
520 /* Second pass: keep recomputing object sizes of variables
521 that need reexamination, until no object sizes are
522 increased or all object sizes are computed. */
523 if (! bitmap_empty_p (osi
.reexamine
))
525 bitmap reexamine
= BITMAP_ALLOC (NULL
);
527 /* If looking for minimum instead of maximum object size,
528 detect cases where a pointer is increased in a loop.
529 Although even without this detection pass 2 would eventually
530 terminate, it could take a long time. If a pointer is
531 increasing this way, we need to assume 0 object size.
532 E.g. p = &buf[0]; while (cond) p = p + 4; */
533 if (object_size_type
& 2)
535 osi
.depths
= XCNEWVEC (unsigned int, num_ssa_names
);
536 osi
.stack
= XNEWVEC (unsigned int, num_ssa_names
);
539 /* collect_object_sizes_for is changing
540 osi.reexamine bitmap, so iterate over a copy. */
541 bitmap_copy (reexamine
, osi
.reexamine
);
542 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
543 if (bitmap_bit_p (osi
.reexamine
, i
))
544 check_for_plus_in_loops (&osi
, ssa_name (i
));
557 /* collect_object_sizes_for is changing
558 osi.reexamine bitmap, so iterate over a copy. */
559 bitmap_copy (reexamine
, osi
.reexamine
);
560 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
561 if (bitmap_bit_p (osi
.reexamine
, i
))
563 collect_object_sizes_for (&osi
, ssa_name (i
));
564 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
566 fprintf (dump_file
, "Reexamining ");
567 print_generic_expr (dump_file
, ssa_name (i
),
569 fprintf (dump_file
, "\n");
575 BITMAP_FREE (reexamine
);
577 EXECUTE_IF_SET_IN_BITMAP (osi
.reexamine
, 0, i
, bi
)
578 bitmap_set_bit (computed
[object_size_type
], i
);
580 /* Debugging dumps. */
583 EXECUTE_IF_SET_IN_BITMAP (osi
.visited
, 0, i
, bi
)
584 if (object_sizes
[object_size_type
][i
]
585 != unknown
[object_size_type
])
587 print_generic_expr (dump_file
, ssa_name (i
),
590 ": %s %sobject size "
591 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
592 (object_size_type
& 2) ? "minimum" : "maximum",
593 (object_size_type
& 1) ? "sub" : "",
594 object_sizes
[object_size_type
][i
]);
598 BITMAP_FREE (osi
.reexamine
);
599 BITMAP_FREE (osi
.visited
);
602 return object_sizes
[object_size_type
][SSA_NAME_VERSION (ptr
)];
605 return unknown
[object_size_type
];
608 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */
611 expr_object_size (struct object_size_info
*osi
, tree ptr
, tree value
)
613 int object_size_type
= osi
->object_size_type
;
614 unsigned int varno
= SSA_NAME_VERSION (ptr
);
615 unsigned HOST_WIDE_INT bytes
;
617 gcc_assert (object_sizes
[object_size_type
][varno
]
618 != unknown
[object_size_type
]);
619 gcc_assert (osi
->pass
== 0);
621 if (TREE_CODE (value
) == WITH_SIZE_EXPR
)
622 value
= TREE_OPERAND (value
, 0);
624 /* Pointer variables should have been handled by merge_object_sizes. */
625 gcc_assert (TREE_CODE (value
) != SSA_NAME
626 || !POINTER_TYPE_P (TREE_TYPE (value
)));
628 if (TREE_CODE (value
) == ADDR_EXPR
)
629 bytes
= addr_object_size (osi
, value
, object_size_type
);
631 bytes
= unknown
[object_size_type
];
633 if ((object_size_type
& 2) == 0)
635 if (object_sizes
[object_size_type
][varno
] < bytes
)
636 object_sizes
[object_size_type
][varno
] = bytes
;
640 if (object_sizes
[object_size_type
][varno
] > bytes
)
641 object_sizes
[object_size_type
][varno
] = bytes
;
646 /* Compute object_sizes for PTR, defined to the result of a call. */
649 call_object_size (struct object_size_info
*osi
, tree ptr
, gimple call
)
651 int object_size_type
= osi
->object_size_type
;
652 unsigned int varno
= SSA_NAME_VERSION (ptr
);
653 unsigned HOST_WIDE_INT bytes
;
655 gcc_assert (is_gimple_call (call
));
657 gcc_assert (object_sizes
[object_size_type
][varno
]
658 != unknown
[object_size_type
]);
659 gcc_assert (osi
->pass
== 0);
661 bytes
= alloc_object_size (call
, object_size_type
);
663 if ((object_size_type
& 2) == 0)
665 if (object_sizes
[object_size_type
][varno
] < bytes
)
666 object_sizes
[object_size_type
][varno
] = bytes
;
670 if (object_sizes
[object_size_type
][varno
] > bytes
)
671 object_sizes
[object_size_type
][varno
] = bytes
;
676 /* Compute object_sizes for PTR, defined to an unknown value. */
679 unknown_object_size (struct object_size_info
*osi
, tree ptr
)
681 int object_size_type
= osi
->object_size_type
;
682 unsigned int varno
= SSA_NAME_VERSION (ptr
);
683 unsigned HOST_WIDE_INT bytes
;
685 gcc_assert (object_sizes
[object_size_type
][varno
]
686 != unknown
[object_size_type
]);
687 gcc_assert (osi
->pass
== 0);
689 bytes
= unknown
[object_size_type
];
691 if ((object_size_type
& 2) == 0)
693 if (object_sizes
[object_size_type
][varno
] < bytes
)
694 object_sizes
[object_size_type
][varno
] = bytes
;
698 if (object_sizes
[object_size_type
][varno
] > bytes
)
699 object_sizes
[object_size_type
][varno
] = bytes
;
704 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
705 the object size might need reexamination later. */
708 merge_object_sizes (struct object_size_info
*osi
, tree dest
, tree orig
,
709 unsigned HOST_WIDE_INT offset
)
711 int object_size_type
= osi
->object_size_type
;
712 unsigned int varno
= SSA_NAME_VERSION (dest
);
713 unsigned HOST_WIDE_INT orig_bytes
;
715 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
717 if (offset
>= offset_limit
)
719 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
724 collect_object_sizes_for (osi
, orig
);
726 orig_bytes
= object_sizes
[object_size_type
][SSA_NAME_VERSION (orig
)];
727 if (orig_bytes
!= unknown
[object_size_type
])
728 orig_bytes
= (offset
> orig_bytes
)
729 ? (unsigned HOST_WIDE_INT
) 0 : orig_bytes
- offset
;
731 if ((object_size_type
& 2) == 0)
733 if (object_sizes
[object_size_type
][varno
] < orig_bytes
)
735 object_sizes
[object_size_type
][varno
] = orig_bytes
;
741 if (object_sizes
[object_size_type
][varno
] > orig_bytes
)
743 object_sizes
[object_size_type
][varno
] = orig_bytes
;
747 return bitmap_bit_p (osi
->reexamine
, SSA_NAME_VERSION (orig
));
751 /* Compute object_sizes for VAR, defined to the result of an assignment
752 with operator POINTER_PLUS_EXPR. Return true if the object size might
753 need reexamination later. */
756 plus_stmt_object_size (struct object_size_info
*osi
, tree var
, gimple stmt
)
758 int object_size_type
= osi
->object_size_type
;
759 unsigned int varno
= SSA_NAME_VERSION (var
);
760 unsigned HOST_WIDE_INT bytes
;
763 if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
765 op0
= gimple_assign_rhs1 (stmt
);
766 op1
= gimple_assign_rhs2 (stmt
);
768 else if (gimple_assign_rhs_code (stmt
) == ADDR_EXPR
)
770 tree rhs
= TREE_OPERAND (gimple_assign_rhs1 (stmt
), 0);
771 gcc_assert (TREE_CODE (rhs
) == MEM_REF
);
772 op0
= TREE_OPERAND (rhs
, 0);
773 op1
= TREE_OPERAND (rhs
, 1);
778 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
781 /* Handle PTR + OFFSET here. */
782 if (TREE_CODE (op1
) == INTEGER_CST
783 && (TREE_CODE (op0
) == SSA_NAME
784 || TREE_CODE (op0
) == ADDR_EXPR
))
786 if (! host_integerp (op1
, 1))
787 bytes
= unknown
[object_size_type
];
788 else if (TREE_CODE (op0
) == SSA_NAME
)
789 return merge_object_sizes (osi
, var
, op0
, tree_low_cst (op1
, 1));
792 unsigned HOST_WIDE_INT off
= tree_low_cst (op1
, 1);
794 /* op0 will be ADDR_EXPR here. */
795 bytes
= addr_object_size (osi
, op0
, object_size_type
);
796 if (bytes
== unknown
[object_size_type
])
798 else if (off
> offset_limit
)
799 bytes
= unknown
[object_size_type
];
800 else if (off
> bytes
)
807 bytes
= unknown
[object_size_type
];
809 if ((object_size_type
& 2) == 0)
811 if (object_sizes
[object_size_type
][varno
] < bytes
)
812 object_sizes
[object_size_type
][varno
] = bytes
;
816 if (object_sizes
[object_size_type
][varno
] > bytes
)
817 object_sizes
[object_size_type
][varno
] = bytes
;
823 /* Compute object_sizes for VAR, defined to VALUE, which is
824 a COND_EXPR. Return true if the object size might need reexamination
828 cond_expr_object_size (struct object_size_info
*osi
, tree var
, tree value
)
831 int object_size_type
= osi
->object_size_type
;
832 unsigned int varno
= SSA_NAME_VERSION (var
);
833 bool reexamine
= false;
835 gcc_assert (TREE_CODE (value
) == COND_EXPR
);
837 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
840 then_
= COND_EXPR_THEN (value
);
841 else_
= COND_EXPR_ELSE (value
);
843 if (TREE_CODE (then_
) == SSA_NAME
)
844 reexamine
|= merge_object_sizes (osi
, var
, then_
, 0);
846 expr_object_size (osi
, var
, then_
);
848 if (TREE_CODE (else_
) == SSA_NAME
)
849 reexamine
|= merge_object_sizes (osi
, var
, else_
, 0);
851 expr_object_size (osi
, var
, else_
);
856 /* Compute object sizes for VAR.
857 For ADDR_EXPR an object size is the number of remaining bytes
858 to the end of the object (where what is considered an object depends on
859 OSI->object_size_type).
860 For allocation GIMPLE_CALL like malloc or calloc object size is the size
862 For POINTER_PLUS_EXPR where second operand is a constant integer,
863 object size is object size of the first operand minus the constant.
864 If the constant is bigger than the number of remaining bytes until the
865 end of the object, object size is 0, but if it is instead a pointer
866 subtraction, object size is unknown[object_size_type].
867 To differentiate addition from subtraction, ADDR_EXPR returns
868 unknown[object_size_type] for all objects bigger than half of the address
869 space, and constants less than half of the address space are considered
870 addition, while bigger constants subtraction.
871 For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
872 object size is object size of that argument.
873 Otherwise, object size is the maximum of object sizes of variables
874 that it might be set to. */
877 collect_object_sizes_for (struct object_size_info
*osi
, tree var
)
879 int object_size_type
= osi
->object_size_type
;
880 unsigned int varno
= SSA_NAME_VERSION (var
);
884 if (bitmap_bit_p (computed
[object_size_type
], varno
))
889 if (bitmap_set_bit (osi
->visited
, varno
))
891 object_sizes
[object_size_type
][varno
]
892 = (object_size_type
& 2) ? -1 : 0;
896 /* Found a dependency loop. Mark the variable for later
898 bitmap_set_bit (osi
->reexamine
, varno
);
899 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
901 fprintf (dump_file
, "Found a dependency loop at ");
902 print_generic_expr (dump_file
, var
, dump_flags
);
903 fprintf (dump_file
, "\n");
909 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
911 fprintf (dump_file
, "Visiting use-def links for ");
912 print_generic_expr (dump_file
, var
, dump_flags
);
913 fprintf (dump_file
, "\n");
916 stmt
= SSA_NAME_DEF_STMT (var
);
919 switch (gimple_code (stmt
))
923 tree rhs
= gimple_assign_rhs1 (stmt
);
924 if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
925 || (gimple_assign_rhs_code (stmt
) == ADDR_EXPR
926 && TREE_CODE (TREE_OPERAND (rhs
, 0)) == MEM_REF
))
927 reexamine
= plus_stmt_object_size (osi
, var
, stmt
);
928 else if (gimple_assign_single_p (stmt
)
929 || gimple_assign_unary_nop_p (stmt
))
931 if (TREE_CODE (rhs
) == SSA_NAME
932 && POINTER_TYPE_P (TREE_TYPE (rhs
)))
933 reexamine
= merge_object_sizes (osi
, var
, rhs
, 0);
934 else if (TREE_CODE (rhs
) == COND_EXPR
)
935 reexamine
= cond_expr_object_size (osi
, var
, rhs
);
937 expr_object_size (osi
, var
, rhs
);
940 unknown_object_size (osi
, var
);
946 tree arg
= pass_through_call (stmt
);
949 if (TREE_CODE (arg
) == SSA_NAME
950 && POINTER_TYPE_P (TREE_TYPE (arg
)))
951 reexamine
= merge_object_sizes (osi
, var
, arg
, 0);
952 else if (TREE_CODE (arg
) == COND_EXPR
)
953 reexamine
= cond_expr_object_size (osi
, var
, arg
);
955 expr_object_size (osi
, var
, arg
);
958 call_object_size (osi
, var
, stmt
);
963 /* Pointers defined by __asm__ statements can point anywhere. */
964 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
969 tree decl
= SSA_NAME_VAR (var
);
971 if (TREE_CODE (decl
) != PARM_DECL
&& DECL_INITIAL (decl
))
972 expr_object_size (osi
, var
, DECL_INITIAL (decl
));
974 expr_object_size (osi
, var
, decl
);
982 for (i
= 0; i
< gimple_phi_num_args (stmt
); i
++)
984 tree rhs
= gimple_phi_arg (stmt
, i
)->def
;
986 if (object_sizes
[object_size_type
][varno
]
987 == unknown
[object_size_type
])
990 if (TREE_CODE (rhs
) == SSA_NAME
)
991 reexamine
|= merge_object_sizes (osi
, var
, rhs
, 0);
992 else if (osi
->pass
== 0)
993 expr_object_size (osi
, var
, rhs
);
1003 || object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
1005 bitmap_set_bit (computed
[object_size_type
], varno
);
1006 bitmap_clear_bit (osi
->reexamine
, varno
);
1010 bitmap_set_bit (osi
->reexamine
, varno
);
1011 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1013 fprintf (dump_file
, "Need to reexamine ");
1014 print_generic_expr (dump_file
, var
, dump_flags
);
1015 fprintf (dump_file
, "\n");
1021 /* Helper function for check_for_plus_in_loops. Called recursively
1025 check_for_plus_in_loops_1 (struct object_size_info
*osi
, tree var
,
1028 gimple stmt
= SSA_NAME_DEF_STMT (var
);
1029 unsigned int varno
= SSA_NAME_VERSION (var
);
1031 if (osi
->depths
[varno
])
1033 if (osi
->depths
[varno
] != depth
)
1037 /* Found a loop involving pointer addition. */
1038 for (sp
= osi
->tos
; sp
> osi
->stack
; )
1041 bitmap_clear_bit (osi
->reexamine
, *sp
);
1042 bitmap_set_bit (computed
[osi
->object_size_type
], *sp
);
1043 object_sizes
[osi
->object_size_type
][*sp
] = 0;
1050 else if (! bitmap_bit_p (osi
->reexamine
, varno
))
1053 osi
->depths
[varno
] = depth
;
1054 *osi
->tos
++ = varno
;
1056 switch (gimple_code (stmt
))
1061 if ((gimple_assign_single_p (stmt
)
1062 || gimple_assign_unary_nop_p (stmt
))
1063 && TREE_CODE (gimple_assign_rhs1 (stmt
)) == SSA_NAME
)
1065 tree rhs
= gimple_assign_rhs1 (stmt
);
1067 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
1069 else if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
1071 tree basevar
= gimple_assign_rhs1 (stmt
);
1072 tree cst
= gimple_assign_rhs2 (stmt
);
1074 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
1076 check_for_plus_in_loops_1 (osi
, basevar
,
1077 depth
+ !integer_zerop (cst
));
1086 tree arg
= pass_through_call (stmt
);
1089 if (TREE_CODE (arg
) == SSA_NAME
)
1090 check_for_plus_in_loops_1 (osi
, arg
, depth
);
1101 for (i
= 0; i
< gimple_phi_num_args (stmt
); i
++)
1103 tree rhs
= gimple_phi_arg (stmt
, i
)->def
;
1105 if (TREE_CODE (rhs
) == SSA_NAME
)
1106 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
1115 osi
->depths
[varno
] = 0;
1120 /* Check if some pointer we are computing object size of is being increased
1121 within a loop. If yes, assume all the SSA variables participating in
1122 that loop have minimum object sizes 0. */
1125 check_for_plus_in_loops (struct object_size_info
*osi
, tree var
)
1127 gimple stmt
= SSA_NAME_DEF_STMT (var
);
1129 /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
1130 and looked for a POINTER_PLUS_EXPR in the pass-through
1131 argument, if any. In GIMPLE, however, such an expression
1132 is not a valid call operand. */
1134 if (is_gimple_assign (stmt
)
1135 && gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
1137 tree basevar
= gimple_assign_rhs1 (stmt
);
1138 tree cst
= gimple_assign_rhs2 (stmt
);
1140 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
1142 if (integer_zerop (cst
))
1145 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 1;
1146 *osi
->tos
++ = SSA_NAME_VERSION (basevar
);
1147 check_for_plus_in_loops_1 (osi
, var
, 2);
1148 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 0;
1154 /* Initialize data structures for the object size computation. */
1157 init_object_sizes (void)
1159 int object_size_type
;
1161 if (object_sizes
[0])
1164 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
1166 object_sizes
[object_size_type
] = XNEWVEC (unsigned HOST_WIDE_INT
, num_ssa_names
);
1167 computed
[object_size_type
] = BITMAP_ALLOC (NULL
);
1170 init_offset_limit ();
1174 /* Destroy data structures after the object size computation. */
1177 fini_object_sizes (void)
1179 int object_size_type
;
1181 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
1183 free (object_sizes
[object_size_type
]);
1184 BITMAP_FREE (computed
[object_size_type
]);
1185 object_sizes
[object_size_type
] = NULL
;
1190 /* Simple pass to optimize all __builtin_object_size () builtins. */
1193 compute_object_sizes (void)
1198 gimple_stmt_iterator i
;
1199 for (i
= gsi_start_bb (bb
); !gsi_end_p (i
); gsi_next (&i
))
1201 tree callee
, result
;
1202 gimple call
= gsi_stmt (i
);
1204 if (gimple_code (call
) != GIMPLE_CALL
)
1207 callee
= gimple_call_fndecl (call
);
1209 || DECL_BUILT_IN_CLASS (callee
) != BUILT_IN_NORMAL
1210 || DECL_FUNCTION_CODE (callee
) != BUILT_IN_OBJECT_SIZE
)
1213 init_object_sizes ();
1214 result
= fold_call_stmt (call
, false);
1217 if (gimple_call_num_args (call
) == 2
1218 && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call
, 0))))
1220 tree ost
= gimple_call_arg (call
, 1);
1222 if (host_integerp (ost
, 1))
1224 unsigned HOST_WIDE_INT object_size_type
1225 = tree_low_cst (ost
, 1);
1227 if (object_size_type
< 2)
1228 result
= fold_convert (size_type_node
,
1229 integer_minus_one_node
);
1230 else if (object_size_type
< 4)
1231 result
= build_zero_cst (size_type_node
);
1239 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1241 fprintf (dump_file
, "Simplified\n ");
1242 print_gimple_stmt (dump_file
, call
, 0, dump_flags
);
1245 if (!update_call_from_tree (&i
, result
))
1248 /* NOTE: In the pre-tuples code, we called update_stmt here. This is
1249 now handled by gsi_replace, called from update_call_from_tree. */
1251 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1253 fprintf (dump_file
, "to\n ");
1254 print_gimple_stmt (dump_file
, call
, 0, dump_flags
);
1255 fprintf (dump_file
, "\n");
1260 fini_object_sizes ();
1264 struct gimple_opt_pass pass_object_sizes
=
1270 compute_object_sizes
, /* execute */
1273 0, /* static_pass_number */
1274 TV_NONE
, /* tv_id */
1275 PROP_cfg
| PROP_ssa
, /* properties_required */
1276 0, /* properties_provided */
1277 0, /* properties_destroyed */
1278 0, /* todo_flags_start */
1279 TODO_dump_func
| TODO_verify_ssa
/* todo_flags_finish */