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
, bytes
= NULL_TREE
;
233 gcc_assert (TREE_CODE (call
) == CALL_EXPR
);
235 callee
= get_callee_fndecl (call
);
237 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
238 switch (DECL_FUNCTION_CODE (callee
))
240 case BUILT_IN_MALLOC
:
241 case BUILT_IN_ALLOCA
:
242 if (call_expr_nargs (call
) == 1
243 && TREE_CODE (CALL_EXPR_ARG (call
, 0)) == INTEGER_CST
)
244 bytes
= fold_convert (sizetype
, CALL_EXPR_ARG (call
, 0));
247 case BUILT_IN_REALLOC:
248 if (call_expr_nargs (call) == 2
249 && TREE_CODE (CALL_EXPR_ARG (call, 1)) == INTEGER_CST)
250 bytes = fold_convert (sizetype, CALL_EXPR_ARG (call, 1));
253 case BUILT_IN_CALLOC
:
254 if (call_expr_nargs (call
) == 2
255 && TREE_CODE (CALL_EXPR_ARG (call
, 0)) == INTEGER_CST
256 && TREE_CODE (CALL_EXPR_ARG (call
, 1)) == INTEGER_CST
)
257 bytes
= size_binop (MULT_EXPR
,
258 fold_convert (sizetype
, CALL_EXPR_ARG (call
, 0)),
259 fold_convert (sizetype
, CALL_EXPR_ARG (call
, 1)));
265 if (bytes
&& host_integerp (bytes
, 1))
266 return tree_low_cst (bytes
, 1);
268 return unknown
[object_size_type
];
272 /* If object size is propagated from one of function's arguments directly
273 to its return value, return that argument for CALL_EXPR CALL.
274 Otherwise return NULL. */
277 pass_through_call (tree call
)
279 tree callee
= get_callee_fndecl (call
);
282 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
283 switch (DECL_FUNCTION_CODE (callee
))
285 case BUILT_IN_MEMCPY
:
286 case BUILT_IN_MEMMOVE
:
287 case BUILT_IN_MEMSET
:
288 case BUILT_IN_STRCPY
:
289 case BUILT_IN_STRNCPY
:
290 case BUILT_IN_STRCAT
:
291 case BUILT_IN_STRNCAT
:
292 case BUILT_IN_MEMCPY_CHK
:
293 case BUILT_IN_MEMMOVE_CHK
:
294 case BUILT_IN_MEMSET_CHK
:
295 case BUILT_IN_STRCPY_CHK
:
296 case BUILT_IN_STRNCPY_CHK
:
297 case BUILT_IN_STRCAT_CHK
:
298 case BUILT_IN_STRNCAT_CHK
:
299 if (call_expr_nargs (call
) >= 1)
300 return CALL_EXPR_ARG (call
, 0);
310 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
311 second argument from __builtin_object_size. */
313 unsigned HOST_WIDE_INT
314 compute_builtin_object_size (tree ptr
, int object_size_type
)
316 gcc_assert (object_size_type
>= 0 && object_size_type
<= 3);
319 init_offset_limit ();
321 if (TREE_CODE (ptr
) == ADDR_EXPR
)
322 return addr_object_size (ptr
, object_size_type
);
323 else if (TREE_CODE (ptr
) == CALL_EXPR
)
325 tree arg
= pass_through_call (ptr
);
328 return compute_builtin_object_size (arg
, object_size_type
);
330 return alloc_object_size (ptr
, object_size_type
);
332 else if (TREE_CODE (ptr
) == SSA_NAME
333 && POINTER_TYPE_P (TREE_TYPE (ptr
))
334 && object_sizes
[object_size_type
] != NULL
)
336 if (!bitmap_bit_p (computed
[object_size_type
], SSA_NAME_VERSION (ptr
)))
338 struct object_size_info osi
;
344 fprintf (dump_file
, "Computing %s %sobject size for ",
345 (object_size_type
& 2) ? "minimum" : "maximum",
346 (object_size_type
& 1) ? "sub" : "");
347 print_generic_expr (dump_file
, ptr
, dump_flags
);
348 fprintf (dump_file
, ":\n");
351 osi
.visited
= BITMAP_ALLOC (NULL
);
352 osi
.reexamine
= BITMAP_ALLOC (NULL
);
353 osi
.object_size_type
= object_size_type
;
358 /* First pass: walk UD chains, compute object sizes that
359 can be computed. osi.reexamine bitmap at the end will
360 contain what variables were found in dependency cycles
361 and therefore need to be reexamined. */
364 collect_object_sizes_for (&osi
, ptr
);
366 /* Second pass: keep recomputing object sizes of variables
367 that need reexamination, until no object sizes are
368 increased or all object sizes are computed. */
369 if (! bitmap_empty_p (osi
.reexamine
))
371 bitmap reexamine
= BITMAP_ALLOC (NULL
);
373 /* If looking for minimum instead of maximum object size,
374 detect cases where a pointer is increased in a loop.
375 Although even without this detection pass 2 would eventually
376 terminate, it could take a long time. If a pointer is
377 increasing this way, we need to assume 0 object size.
378 E.g. p = &buf[0]; while (cond) p = p + 4; */
379 if (object_size_type
& 2)
381 osi
.depths
= XCNEWVEC (unsigned int, num_ssa_names
);
382 osi
.stack
= XNEWVEC (unsigned int, num_ssa_names
);
385 /* collect_object_sizes_for is changing
386 osi.reexamine bitmap, so iterate over a copy. */
387 bitmap_copy (reexamine
, osi
.reexamine
);
388 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
389 if (bitmap_bit_p (osi
.reexamine
, i
))
390 check_for_plus_in_loops (&osi
, ssa_name (i
));
403 /* collect_object_sizes_for is changing
404 osi.reexamine bitmap, so iterate over a copy. */
405 bitmap_copy (reexamine
, osi
.reexamine
);
406 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
407 if (bitmap_bit_p (osi
.reexamine
, i
))
409 collect_object_sizes_for (&osi
, ssa_name (i
));
410 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
412 fprintf (dump_file
, "Reexamining ");
413 print_generic_expr (dump_file
, ssa_name (i
),
415 fprintf (dump_file
, "\n");
421 BITMAP_FREE (reexamine
);
423 EXECUTE_IF_SET_IN_BITMAP (osi
.reexamine
, 0, i
, bi
)
424 bitmap_set_bit (computed
[object_size_type
], i
);
426 /* Debugging dumps. */
429 EXECUTE_IF_SET_IN_BITMAP (osi
.visited
, 0, i
, bi
)
430 if (object_sizes
[object_size_type
][i
]
431 != unknown
[object_size_type
])
433 print_generic_expr (dump_file
, ssa_name (i
),
436 ": %s %sobject size "
437 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
438 (object_size_type
& 2) ? "minimum" : "maximum",
439 (object_size_type
& 1) ? "sub" : "",
440 object_sizes
[object_size_type
][i
]);
444 BITMAP_FREE (osi
.reexamine
);
445 BITMAP_FREE (osi
.visited
);
448 return object_sizes
[object_size_type
][SSA_NAME_VERSION (ptr
)];
451 return unknown
[object_size_type
];
455 /* Compute object_sizes for PTR, defined to VALUE, which is not
459 expr_object_size (struct object_size_info
*osi
, tree ptr
, tree value
)
461 int object_size_type
= osi
->object_size_type
;
462 unsigned int varno
= SSA_NAME_VERSION (ptr
);
463 unsigned HOST_WIDE_INT bytes
;
465 gcc_assert (object_sizes
[object_size_type
][varno
]
466 != unknown
[object_size_type
]);
467 gcc_assert (osi
->pass
== 0);
469 if (TREE_CODE (value
) == WITH_SIZE_EXPR
)
470 value
= TREE_OPERAND (value
, 0);
472 /* Pointer variables should have been handled by merge_object_sizes. */
473 gcc_assert (TREE_CODE (value
) != SSA_NAME
474 || !POINTER_TYPE_P (TREE_TYPE (value
)));
476 if (TREE_CODE (value
) == ADDR_EXPR
)
477 bytes
= addr_object_size (value
, object_size_type
);
478 else if (TREE_CODE (value
) == CALL_EXPR
)
479 bytes
= alloc_object_size (value
, object_size_type
);
481 bytes
= unknown
[object_size_type
];
483 if ((object_size_type
& 2) == 0)
485 if (object_sizes
[object_size_type
][varno
] < bytes
)
486 object_sizes
[object_size_type
][varno
] = bytes
;
490 if (object_sizes
[object_size_type
][varno
] > bytes
)
491 object_sizes
[object_size_type
][varno
] = bytes
;
496 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
497 the object size might need reexamination later. */
500 merge_object_sizes (struct object_size_info
*osi
, tree dest
, tree orig
,
501 unsigned HOST_WIDE_INT offset
)
503 int object_size_type
= osi
->object_size_type
;
504 unsigned int varno
= SSA_NAME_VERSION (dest
);
505 unsigned HOST_WIDE_INT orig_bytes
;
507 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
509 if (offset
>= offset_limit
)
511 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
516 collect_object_sizes_for (osi
, orig
);
518 orig_bytes
= object_sizes
[object_size_type
][SSA_NAME_VERSION (orig
)];
519 if (orig_bytes
!= unknown
[object_size_type
])
520 orig_bytes
= (offset
> orig_bytes
)
521 ? (unsigned HOST_WIDE_INT
) 0 : orig_bytes
- offset
;
523 if ((object_size_type
& 2) == 0)
525 if (object_sizes
[object_size_type
][varno
] < orig_bytes
)
527 object_sizes
[object_size_type
][varno
] = orig_bytes
;
533 if (object_sizes
[object_size_type
][varno
] > orig_bytes
)
535 object_sizes
[object_size_type
][varno
] = orig_bytes
;
539 return bitmap_bit_p (osi
->reexamine
, SSA_NAME_VERSION (orig
));
543 /* Compute object_sizes for PTR, defined to VALUE, which is
544 a PLUS_EXPR. Return true if the object size might need reexamination
548 plus_expr_object_size (struct object_size_info
*osi
, tree var
, tree value
)
550 tree op0
= TREE_OPERAND (value
, 0);
551 tree op1
= TREE_OPERAND (value
, 1);
552 bool ptr1_p
= POINTER_TYPE_P (TREE_TYPE (op0
))
553 && TREE_CODE (op0
) != INTEGER_CST
;
554 bool ptr2_p
= POINTER_TYPE_P (TREE_TYPE (op1
))
555 && TREE_CODE (op1
) != INTEGER_CST
;
556 int object_size_type
= osi
->object_size_type
;
557 unsigned int varno
= SSA_NAME_VERSION (var
);
558 unsigned HOST_WIDE_INT bytes
;
560 gcc_assert (TREE_CODE (value
) == PLUS_EXPR
);
562 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
565 /* Swap operands if needed. */
566 if (ptr2_p
&& !ptr1_p
)
575 /* Handle PTR + OFFSET here. */
578 && TREE_CODE (op1
) == INTEGER_CST
579 && (TREE_CODE (op0
) == SSA_NAME
580 || TREE_CODE (op0
) == ADDR_EXPR
))
582 if (! host_integerp (op1
, 1))
583 bytes
= unknown
[object_size_type
];
584 else if (TREE_CODE (op0
) == SSA_NAME
)
585 return merge_object_sizes (osi
, var
, op0
, tree_low_cst (op1
, 1));
588 unsigned HOST_WIDE_INT off
= tree_low_cst (op1
, 1);
590 bytes
= compute_builtin_object_size (op0
, object_size_type
);
591 if (off
> offset_limit
)
592 bytes
= unknown
[object_size_type
];
593 else if (off
> bytes
)
600 bytes
= unknown
[object_size_type
];
602 if ((object_size_type
& 2) == 0)
604 if (object_sizes
[object_size_type
][varno
] < bytes
)
605 object_sizes
[object_size_type
][varno
] = bytes
;
609 if (object_sizes
[object_size_type
][varno
] > bytes
)
610 object_sizes
[object_size_type
][varno
] = bytes
;
616 /* Compute object_sizes for PTR, defined to VALUE, which is
617 a COND_EXPR. Return true if the object size might need reexamination
621 cond_expr_object_size (struct object_size_info
*osi
, tree var
, tree value
)
624 int object_size_type
= osi
->object_size_type
;
625 unsigned int varno
= SSA_NAME_VERSION (var
);
626 bool reexamine
= false;
628 gcc_assert (TREE_CODE (value
) == COND_EXPR
);
630 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
633 then_
= COND_EXPR_THEN (value
);
634 else_
= COND_EXPR_ELSE (value
);
636 if (TREE_CODE (then_
) == SSA_NAME
)
637 reexamine
|= merge_object_sizes (osi
, var
, then_
, 0);
639 expr_object_size (osi
, var
, then_
);
641 if (TREE_CODE (else_
) == SSA_NAME
)
642 reexamine
|= merge_object_sizes (osi
, var
, else_
, 0);
644 expr_object_size (osi
, var
, else_
);
650 /* Compute object sizes for VAR.
651 For ADDR_EXPR an object size is the number of remaining bytes
652 to the end of the object (where what is considered an object depends on
653 OSI->object_size_type).
654 For allocation CALL_EXPR like malloc or calloc object size is the size
656 For pointer PLUS_EXPR where second operand is a constant integer,
657 object size is object size of the first operand minus the constant.
658 If the constant is bigger than the number of remaining bytes until the
659 end of the object, object size is 0, but if it is instead a pointer
660 subtraction, object size is unknown[object_size_type].
661 To differentiate addition from subtraction, ADDR_EXPR returns
662 unknown[object_size_type] for all objects bigger than half of the address
663 space, and constants less than half of the address space are considered
664 addition, while bigger constants subtraction.
665 For a memcpy like CALL_EXPR that always returns one of its arguments, the
666 object size is object size of that argument.
667 Otherwise, object size is the maximum of object sizes of variables
668 that it might be set to. */
671 collect_object_sizes_for (struct object_size_info
*osi
, tree var
)
673 int object_size_type
= osi
->object_size_type
;
674 unsigned int varno
= SSA_NAME_VERSION (var
);
678 if (bitmap_bit_p (computed
[object_size_type
], varno
))
683 if (! bitmap_bit_p (osi
->visited
, varno
))
685 bitmap_set_bit (osi
->visited
, varno
);
686 object_sizes
[object_size_type
][varno
]
687 = (object_size_type
& 2) ? -1 : 0;
691 /* Found a dependency loop. Mark the variable for later
693 bitmap_set_bit (osi
->reexamine
, varno
);
694 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
696 fprintf (dump_file
, "Found a dependency loop at ");
697 print_generic_expr (dump_file
, var
, dump_flags
);
698 fprintf (dump_file
, "\n");
704 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
706 fprintf (dump_file
, "Visiting use-def links for ");
707 print_generic_expr (dump_file
, var
, dump_flags
);
708 fprintf (dump_file
, "\n");
711 stmt
= SSA_NAME_DEF_STMT (var
);
714 switch (TREE_CODE (stmt
))
717 gcc_assert (TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
);
718 stmt
= TREE_OPERAND (stmt
, 0);
721 case GIMPLE_MODIFY_STMT
:
723 tree rhs
= GIMPLE_STMT_OPERAND (stmt
, 1), arg
;
726 if (TREE_CODE (rhs
) == CALL_EXPR
)
728 arg
= pass_through_call (rhs
);
733 if (TREE_CODE (rhs
) == SSA_NAME
734 && POINTER_TYPE_P (TREE_TYPE (rhs
)))
735 reexamine
= merge_object_sizes (osi
, var
, rhs
, 0);
737 else if (TREE_CODE (rhs
) == PLUS_EXPR
)
738 reexamine
= plus_expr_object_size (osi
, var
, rhs
);
740 else if (TREE_CODE (rhs
) == COND_EXPR
)
741 reexamine
= cond_expr_object_size (osi
, var
, rhs
);
744 expr_object_size (osi
, var
, rhs
);
749 /* Pointers defined by __asm__ statements can point anywhere. */
750 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
755 tree decl
= SSA_NAME_VAR (var
);
757 gcc_assert (IS_EMPTY_STMT (stmt
));
759 if (TREE_CODE (decl
) != PARM_DECL
&& DECL_INITIAL (decl
))
760 expr_object_size (osi
, var
, DECL_INITIAL (decl
));
762 expr_object_size (osi
, var
, decl
);
770 for (i
= 0; i
< PHI_NUM_ARGS (stmt
); i
++)
772 tree rhs
= PHI_ARG_DEF (stmt
, i
);
774 if (object_sizes
[object_size_type
][varno
]
775 == unknown
[object_size_type
])
778 if (TREE_CODE (rhs
) == SSA_NAME
)
779 reexamine
|= merge_object_sizes (osi
, var
, rhs
, 0);
780 else if (osi
->pass
== 0)
781 expr_object_size (osi
, var
, rhs
);
790 || object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
792 bitmap_set_bit (computed
[object_size_type
], varno
);
793 bitmap_clear_bit (osi
->reexamine
, varno
);
797 bitmap_set_bit (osi
->reexamine
, varno
);
798 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
800 fprintf (dump_file
, "Need to reexamine ");
801 print_generic_expr (dump_file
, var
, dump_flags
);
802 fprintf (dump_file
, "\n");
808 /* Helper function for check_for_plus_in_loops. Called recursively
812 check_for_plus_in_loops_1 (struct object_size_info
*osi
, tree var
,
815 tree stmt
= SSA_NAME_DEF_STMT (var
);
816 unsigned int varno
= SSA_NAME_VERSION (var
);
818 if (osi
->depths
[varno
])
820 if (osi
->depths
[varno
] != depth
)
824 /* Found a loop involving pointer addition. */
825 for (sp
= osi
->tos
; sp
> osi
->stack
; )
828 bitmap_clear_bit (osi
->reexamine
, *sp
);
829 bitmap_set_bit (computed
[osi
->object_size_type
], *sp
);
830 object_sizes
[osi
->object_size_type
][*sp
] = 0;
837 else if (! bitmap_bit_p (osi
->reexamine
, varno
))
840 osi
->depths
[varno
] = depth
;
843 switch (TREE_CODE (stmt
))
846 gcc_assert (TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
);
847 stmt
= TREE_OPERAND (stmt
, 0);
850 case GIMPLE_MODIFY_STMT
:
852 tree rhs
= GIMPLE_STMT_OPERAND (stmt
, 1), arg
;
855 if (TREE_CODE (rhs
) == CALL_EXPR
)
857 arg
= pass_through_call (rhs
);
862 if (TREE_CODE (rhs
) == SSA_NAME
)
863 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
864 else if (TREE_CODE (rhs
) == PLUS_EXPR
)
866 tree op0
= TREE_OPERAND (rhs
, 0);
867 tree op1
= TREE_OPERAND (rhs
, 1);
870 if (TREE_CODE (op0
) == SSA_NAME
)
879 gcc_assert (TREE_CODE (basevar
) == SSA_NAME
);
881 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
883 check_for_plus_in_loops_1 (osi
, basevar
,
884 depth
+ !integer_zerop (cst
));
894 for (i
= 0; i
< PHI_NUM_ARGS (stmt
); i
++)
896 tree rhs
= PHI_ARG_DEF (stmt
, i
);
898 if (TREE_CODE (rhs
) == SSA_NAME
)
899 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
907 osi
->depths
[varno
] = 0;
912 /* Check if some pointer we are computing object size of is being increased
913 within a loop. If yes, assume all the SSA variables participating in
914 that loop have minimum object sizes 0. */
917 check_for_plus_in_loops (struct object_size_info
*osi
, tree var
)
919 tree stmt
= SSA_NAME_DEF_STMT (var
);
921 switch (TREE_CODE (stmt
))
924 gcc_assert (TREE_CODE (TREE_OPERAND (stmt
, 0)) == GIMPLE_MODIFY_STMT
);
925 stmt
= TREE_OPERAND (stmt
, 0);
928 case GIMPLE_MODIFY_STMT
:
930 tree rhs
= GIMPLE_STMT_OPERAND (stmt
, 1), arg
;
933 if (TREE_CODE (rhs
) == CALL_EXPR
)
935 arg
= pass_through_call (rhs
);
940 if (TREE_CODE (rhs
) == PLUS_EXPR
)
942 tree op0
= TREE_OPERAND (rhs
, 0);
943 tree op1
= TREE_OPERAND (rhs
, 1);
946 if (TREE_CODE (op0
) == SSA_NAME
)
955 gcc_assert (TREE_CODE (basevar
) == SSA_NAME
);
957 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
959 if (integer_zerop (cst
))
962 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 1;
963 *osi
->tos
++ = SSA_NAME_VERSION (basevar
);
964 check_for_plus_in_loops_1 (osi
, var
, 2);
965 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 0;
976 /* Initialize data structures for the object size computation. */
979 init_object_sizes (void)
981 int object_size_type
;
986 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
988 object_sizes
[object_size_type
] = XNEWVEC (unsigned HOST_WIDE_INT
, num_ssa_names
);
989 computed
[object_size_type
] = BITMAP_ALLOC (NULL
);
992 init_offset_limit ();
996 /* Destroy data structures after the object size computation. */
999 fini_object_sizes (void)
1001 int object_size_type
;
1003 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
1005 free (object_sizes
[object_size_type
]);
1006 BITMAP_FREE (computed
[object_size_type
]);
1007 object_sizes
[object_size_type
] = NULL
;
1012 /* Simple pass to optimize all __builtin_object_size () builtins. */
1015 compute_object_sizes (void)
1020 block_stmt_iterator i
;
1021 for (i
= bsi_start (bb
); !bsi_end_p (i
); bsi_next (&i
))
1023 tree
*stmtp
= bsi_stmt_ptr (i
);
1024 tree call
= get_rhs (*stmtp
);
1025 tree callee
, result
;
1027 if (!call
|| TREE_CODE (call
) != CALL_EXPR
)
1030 callee
= get_callee_fndecl (call
);
1032 || DECL_BUILT_IN_CLASS (callee
) != BUILT_IN_NORMAL
1033 || DECL_FUNCTION_CODE (callee
) != BUILT_IN_OBJECT_SIZE
)
1036 init_object_sizes ();
1037 result
= fold_call_expr (call
, false);
1040 if (call_expr_nargs (call
) == 2
1041 && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (call
, 0))))
1043 tree ost
= CALL_EXPR_ARG (call
, 1);
1045 if (host_integerp (ost
, 1))
1047 unsigned HOST_WIDE_INT object_size_type
1048 = tree_low_cst (ost
, 1);
1050 if (object_size_type
< 2)
1051 result
= fold_convert (size_type_node
,
1052 integer_minus_one_node
);
1053 else if (object_size_type
< 4)
1054 result
= size_zero_node
;
1062 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1064 fprintf (dump_file
, "Simplified\n ");
1065 print_generic_stmt (dump_file
, *stmtp
, dump_flags
);
1068 if (!set_rhs (stmtp
, result
))
1070 update_stmt (*stmtp
);
1072 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1074 fprintf (dump_file
, "to\n ");
1075 print_generic_stmt (dump_file
, *stmtp
, dump_flags
);
1076 fprintf (dump_file
, "\n");
1081 fini_object_sizes ();
1085 struct tree_opt_pass pass_object_sizes
=
1089 compute_object_sizes
, /* execute */
1092 0, /* static_pass_number */
1094 PROP_cfg
| PROP_ssa
| PROP_alias
, /* properties_required */
1095 0, /* properties_provided */
1096 0, /* properties_destroyed */
1097 0, /* todo_flags_start */
1098 TODO_dump_func
| TODO_verify_ssa
, /* todo_flags_finish */