1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
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 "gimple-pretty-print.h"
29 #include "tree-flow.h"
30 #include "tree-pass.h"
31 #include "tree-ssa-propagate.h"
33 struct object_size_info
36 bitmap visited
, reexamine
;
40 unsigned int *stack
, *tos
;
43 static unsigned HOST_WIDE_INT unknown
[4] = { -1, -1, 0, 0 };
45 static tree
compute_object_offset (const_tree
, const_tree
);
46 static unsigned HOST_WIDE_INT
addr_object_size (struct object_size_info
*,
48 static unsigned HOST_WIDE_INT
alloc_object_size (const_gimple
, int);
49 static tree
pass_through_call (const_gimple
);
50 static void collect_object_sizes_for (struct object_size_info
*, tree
);
51 static void expr_object_size (struct object_size_info
*, tree
, tree
);
52 static bool merge_object_sizes (struct object_size_info
*, tree
, tree
,
53 unsigned HOST_WIDE_INT
);
54 static bool plus_stmt_object_size (struct object_size_info
*, tree
, gimple
);
55 static bool cond_expr_object_size (struct object_size_info
*, tree
, gimple
);
56 static unsigned int compute_object_sizes (void);
57 static void init_offset_limit (void);
58 static void check_for_plus_in_loops (struct object_size_info
*, tree
);
59 static void check_for_plus_in_loops_1 (struct object_size_info
*, tree
,
62 /* object_sizes[0] is upper bound for number of bytes till the end of
64 object_sizes[1] is upper bound for number of bytes till the end of
65 the subobject (innermost array or field with address taken).
66 object_sizes[2] is lower bound for number of bytes till the end of
67 the object and object_sizes[3] lower bound for subobject. */
68 static unsigned HOST_WIDE_INT
*object_sizes
[4];
70 /* Bitmaps what object sizes have been computed already. */
71 static bitmap computed
[4];
73 /* Maximum value of offset we consider to be addition. */
74 static unsigned HOST_WIDE_INT offset_limit
;
77 /* Initialize OFFSET_LIMIT variable. */
79 init_offset_limit (void)
81 if (host_integerp (TYPE_MAX_VALUE (sizetype
), 1))
82 offset_limit
= tree_low_cst (TYPE_MAX_VALUE (sizetype
), 1);
89 /* Compute offset of EXPR within VAR. Return error_mark_node
93 compute_object_offset (const_tree expr
, const_tree var
)
95 enum tree_code code
= PLUS_EXPR
;
99 return size_zero_node
;
101 switch (TREE_CODE (expr
))
104 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
105 if (base
== error_mark_node
)
108 t
= TREE_OPERAND (expr
, 1);
109 off
= size_binop (PLUS_EXPR
, DECL_FIELD_OFFSET (t
),
110 size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t
), 1)
116 case VIEW_CONVERT_EXPR
:
117 case NON_LVALUE_EXPR
:
118 return compute_object_offset (TREE_OPERAND (expr
, 0), var
);
121 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
122 if (base
== error_mark_node
)
125 off
= TYPE_SIZE_UNIT (TREE_TYPE (expr
));
129 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
130 if (base
== error_mark_node
)
133 t
= TREE_OPERAND (expr
, 1);
134 if (TREE_CODE (t
) == INTEGER_CST
&& tree_int_cst_sgn (t
) < 0)
137 t
= fold_build1 (NEGATE_EXPR
, TREE_TYPE (t
), t
);
139 t
= fold_convert (sizetype
, t
);
140 off
= size_binop (MULT_EXPR
, TYPE_SIZE_UNIT (TREE_TYPE (expr
)), t
);
144 gcc_assert (TREE_CODE (TREE_OPERAND (expr
, 0)) == ADDR_EXPR
);
145 return double_int_to_tree (sizetype
, mem_ref_offset (expr
));
148 return error_mark_node
;
151 return size_binop (code
, base
, off
);
155 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
156 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
157 If unknown, return unknown[object_size_type]. */
159 static unsigned HOST_WIDE_INT
160 addr_object_size (struct object_size_info
*osi
, const_tree ptr
,
161 int object_size_type
)
163 tree pt_var
, pt_var_size
= NULL_TREE
, var_size
, bytes
;
165 gcc_assert (TREE_CODE (ptr
) == ADDR_EXPR
);
167 pt_var
= TREE_OPERAND (ptr
, 0);
168 while (handled_component_p (pt_var
))
169 pt_var
= TREE_OPERAND (pt_var
, 0);
172 && TREE_CODE (pt_var
) == MEM_REF
)
174 unsigned HOST_WIDE_INT sz
;
176 if (!osi
|| (object_size_type
& 1) != 0
177 || TREE_CODE (TREE_OPERAND (pt_var
, 0)) != SSA_NAME
)
179 sz
= compute_builtin_object_size (TREE_OPERAND (pt_var
, 0),
180 object_size_type
& ~1);
184 tree var
= TREE_OPERAND (pt_var
, 0);
186 collect_object_sizes_for (osi
, var
);
187 if (bitmap_bit_p (computed
[object_size_type
],
188 SSA_NAME_VERSION (var
)))
189 sz
= object_sizes
[object_size_type
][SSA_NAME_VERSION (var
)];
191 sz
= unknown
[object_size_type
];
193 if (sz
!= unknown
[object_size_type
])
195 double_int dsz
= double_int::from_uhwi (sz
) - mem_ref_offset (pt_var
);
196 if (dsz
.is_negative ())
198 else if (dsz
.fits_uhwi ())
201 sz
= unknown
[object_size_type
];
204 if (sz
!= unknown
[object_size_type
] && sz
< offset_limit
)
205 pt_var_size
= size_int (sz
);
209 && host_integerp (DECL_SIZE_UNIT (pt_var
), 1)
210 && (unsigned HOST_WIDE_INT
)
211 tree_low_cst (DECL_SIZE_UNIT (pt_var
), 1) < offset_limit
)
212 pt_var_size
= DECL_SIZE_UNIT (pt_var
);
214 && TREE_CODE (pt_var
) == STRING_CST
215 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var
))
216 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)), 1)
217 && (unsigned HOST_WIDE_INT
)
218 tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)), 1)
220 pt_var_size
= TYPE_SIZE_UNIT (TREE_TYPE (pt_var
));
222 return unknown
[object_size_type
];
224 if (pt_var
!= TREE_OPERAND (ptr
, 0))
228 if (object_size_type
& 1)
230 var
= TREE_OPERAND (ptr
, 0);
233 && TREE_CODE (var
) != BIT_FIELD_REF
234 && TREE_CODE (var
) != COMPONENT_REF
235 && TREE_CODE (var
) != ARRAY_REF
236 && TREE_CODE (var
) != ARRAY_RANGE_REF
237 && TREE_CODE (var
) != REALPART_EXPR
238 && TREE_CODE (var
) != IMAGPART_EXPR
)
239 var
= TREE_OPERAND (var
, 0);
240 if (var
!= pt_var
&& TREE_CODE (var
) == ARRAY_REF
)
241 var
= TREE_OPERAND (var
, 0);
242 if (! TYPE_SIZE_UNIT (TREE_TYPE (var
))
243 || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var
)), 1)
245 && tree_int_cst_lt (pt_var_size
,
246 TYPE_SIZE_UNIT (TREE_TYPE (var
)))))
248 else if (var
!= pt_var
&& TREE_CODE (pt_var
) == MEM_REF
)
251 /* For &X->fld, compute object size only if fld isn't the last
252 field, as struct { int i; char c[1]; } is often used instead
253 of flexible array member. */
254 while (v
&& v
!= pt_var
)
255 switch (TREE_CODE (v
))
258 if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v
, 0)))
259 && TREE_CODE (TREE_OPERAND (v
, 1)) == INTEGER_CST
)
262 = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v
, 0)));
264 && TYPE_MAX_VALUE (domain
)
265 && TREE_CODE (TYPE_MAX_VALUE (domain
))
267 && tree_int_cst_lt (TREE_OPERAND (v
, 1),
268 TYPE_MAX_VALUE (domain
)))
274 v
= TREE_OPERAND (v
, 0);
281 if (TREE_CODE (TREE_TYPE (v
)) != ARRAY_TYPE
)
286 while (v
!= pt_var
&& TREE_CODE (v
) == COMPONENT_REF
)
287 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
289 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
293 v
= TREE_OPERAND (v
, 0);
294 if (TREE_CODE (v
) == COMPONENT_REF
295 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
298 tree fld_chain
= DECL_CHAIN (TREE_OPERAND (v
, 1));
299 for (; fld_chain
; fld_chain
= DECL_CHAIN (fld_chain
))
300 if (TREE_CODE (fld_chain
) == FIELD_DECL
)
308 v
= TREE_OPERAND (v
, 0);
310 while (v
!= pt_var
&& TREE_CODE (v
) == COMPONENT_REF
)
311 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
313 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
317 v
= TREE_OPERAND (v
, 0);
335 var_size
= TYPE_SIZE_UNIT (TREE_TYPE (var
));
336 else if (!pt_var_size
)
337 return unknown
[object_size_type
];
339 var_size
= pt_var_size
;
340 bytes
= compute_object_offset (TREE_OPERAND (ptr
, 0), var
);
341 if (bytes
!= error_mark_node
)
343 if (TREE_CODE (bytes
) == INTEGER_CST
344 && tree_int_cst_lt (var_size
, bytes
))
345 bytes
= size_zero_node
;
347 bytes
= size_binop (MINUS_EXPR
, var_size
, bytes
);
351 && TREE_CODE (pt_var
) == MEM_REF
352 && bytes
!= error_mark_node
)
354 tree bytes2
= compute_object_offset (TREE_OPERAND (ptr
, 0), pt_var
);
355 if (bytes2
!= error_mark_node
)
357 if (TREE_CODE (bytes2
) == INTEGER_CST
358 && tree_int_cst_lt (pt_var_size
, bytes2
))
359 bytes2
= size_zero_node
;
361 bytes2
= size_binop (MINUS_EXPR
, pt_var_size
, bytes2
);
362 bytes
= size_binop (MIN_EXPR
, bytes
, bytes2
);
366 else if (!pt_var_size
)
367 return unknown
[object_size_type
];
371 if (host_integerp (bytes
, 1))
372 return tree_low_cst (bytes
, 1);
374 return unknown
[object_size_type
];
378 /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
379 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
380 argument from __builtin_object_size. If unknown, return
381 unknown[object_size_type]. */
383 static unsigned HOST_WIDE_INT
384 alloc_object_size (const_gimple call
, int object_size_type
)
386 tree callee
, bytes
= NULL_TREE
;
388 int arg1
= -1, arg2
= -1;
390 gcc_assert (is_gimple_call (call
));
392 callee
= gimple_call_fndecl (call
);
394 return unknown
[object_size_type
];
396 alloc_size
= lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee
)));
397 if (alloc_size
&& TREE_VALUE (alloc_size
))
399 tree p
= TREE_VALUE (alloc_size
);
401 arg1
= TREE_INT_CST_LOW (TREE_VALUE (p
))-1;
403 arg2
= TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p
)))-1;
406 if (DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
407 switch (DECL_FUNCTION_CODE (callee
))
409 case BUILT_IN_CALLOC
:
412 case BUILT_IN_MALLOC
:
413 case BUILT_IN_ALLOCA
:
414 case BUILT_IN_ALLOCA_WITH_ALIGN
:
420 if (arg1
< 0 || arg1
>= (int)gimple_call_num_args (call
)
421 || TREE_CODE (gimple_call_arg (call
, arg1
)) != INTEGER_CST
423 && (arg2
>= (int)gimple_call_num_args (call
)
424 || TREE_CODE (gimple_call_arg (call
, arg2
)) != INTEGER_CST
)))
425 return unknown
[object_size_type
];
428 bytes
= size_binop (MULT_EXPR
,
429 fold_convert (sizetype
, gimple_call_arg (call
, arg1
)),
430 fold_convert (sizetype
, gimple_call_arg (call
, arg2
)));
432 bytes
= fold_convert (sizetype
, gimple_call_arg (call
, arg1
));
434 if (bytes
&& host_integerp (bytes
, 1))
435 return tree_low_cst (bytes
, 1);
437 return unknown
[object_size_type
];
441 /* If object size is propagated from one of function's arguments directly
442 to its return value, return that argument for GIMPLE_CALL statement CALL.
443 Otherwise return NULL. */
446 pass_through_call (const_gimple call
)
448 tree callee
= gimple_call_fndecl (call
);
451 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
452 switch (DECL_FUNCTION_CODE (callee
))
454 case BUILT_IN_MEMCPY
:
455 case BUILT_IN_MEMMOVE
:
456 case BUILT_IN_MEMSET
:
457 case BUILT_IN_STRCPY
:
458 case BUILT_IN_STRNCPY
:
459 case BUILT_IN_STRCAT
:
460 case BUILT_IN_STRNCAT
:
461 case BUILT_IN_MEMCPY_CHK
:
462 case BUILT_IN_MEMMOVE_CHK
:
463 case BUILT_IN_MEMSET_CHK
:
464 case BUILT_IN_STRCPY_CHK
:
465 case BUILT_IN_STRNCPY_CHK
:
466 case BUILT_IN_STPNCPY_CHK
:
467 case BUILT_IN_STRCAT_CHK
:
468 case BUILT_IN_STRNCAT_CHK
:
469 case BUILT_IN_ASSUME_ALIGNED
:
470 if (gimple_call_num_args (call
) >= 1)
471 return gimple_call_arg (call
, 0);
481 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
482 second argument from __builtin_object_size. */
484 unsigned HOST_WIDE_INT
485 compute_builtin_object_size (tree ptr
, int object_size_type
)
487 gcc_assert (object_size_type
>= 0 && object_size_type
<= 3);
490 init_offset_limit ();
492 if (TREE_CODE (ptr
) == ADDR_EXPR
)
493 return addr_object_size (NULL
, ptr
, object_size_type
);
495 if (TREE_CODE (ptr
) == SSA_NAME
496 && POINTER_TYPE_P (TREE_TYPE (ptr
))
497 && object_sizes
[object_size_type
] != NULL
)
499 if (!bitmap_bit_p (computed
[object_size_type
], SSA_NAME_VERSION (ptr
)))
501 struct object_size_info osi
;
507 fprintf (dump_file
, "Computing %s %sobject size for ",
508 (object_size_type
& 2) ? "minimum" : "maximum",
509 (object_size_type
& 1) ? "sub" : "");
510 print_generic_expr (dump_file
, ptr
, dump_flags
);
511 fprintf (dump_file
, ":\n");
514 osi
.visited
= BITMAP_ALLOC (NULL
);
515 osi
.reexamine
= BITMAP_ALLOC (NULL
);
516 osi
.object_size_type
= object_size_type
;
521 /* First pass: walk UD chains, compute object sizes that
522 can be computed. osi.reexamine bitmap at the end will
523 contain what variables were found in dependency cycles
524 and therefore need to be reexamined. */
527 collect_object_sizes_for (&osi
, ptr
);
529 /* Second pass: keep recomputing object sizes of variables
530 that need reexamination, until no object sizes are
531 increased or all object sizes are computed. */
532 if (! bitmap_empty_p (osi
.reexamine
))
534 bitmap reexamine
= BITMAP_ALLOC (NULL
);
536 /* If looking for minimum instead of maximum object size,
537 detect cases where a pointer is increased in a loop.
538 Although even without this detection pass 2 would eventually
539 terminate, it could take a long time. If a pointer is
540 increasing this way, we need to assume 0 object size.
541 E.g. p = &buf[0]; while (cond) p = p + 4; */
542 if (object_size_type
& 2)
544 osi
.depths
= XCNEWVEC (unsigned int, num_ssa_names
);
545 osi
.stack
= XNEWVEC (unsigned int, num_ssa_names
);
548 /* collect_object_sizes_for is changing
549 osi.reexamine bitmap, so iterate over a copy. */
550 bitmap_copy (reexamine
, osi
.reexamine
);
551 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
552 if (bitmap_bit_p (osi
.reexamine
, i
))
553 check_for_plus_in_loops (&osi
, ssa_name (i
));
566 /* collect_object_sizes_for is changing
567 osi.reexamine bitmap, so iterate over a copy. */
568 bitmap_copy (reexamine
, osi
.reexamine
);
569 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
570 if (bitmap_bit_p (osi
.reexamine
, i
))
572 collect_object_sizes_for (&osi
, ssa_name (i
));
573 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
575 fprintf (dump_file
, "Reexamining ");
576 print_generic_expr (dump_file
, ssa_name (i
),
578 fprintf (dump_file
, "\n");
584 BITMAP_FREE (reexamine
);
586 EXECUTE_IF_SET_IN_BITMAP (osi
.reexamine
, 0, i
, bi
)
587 bitmap_set_bit (computed
[object_size_type
], i
);
589 /* Debugging dumps. */
592 EXECUTE_IF_SET_IN_BITMAP (osi
.visited
, 0, i
, bi
)
593 if (object_sizes
[object_size_type
][i
]
594 != unknown
[object_size_type
])
596 print_generic_expr (dump_file
, ssa_name (i
),
599 ": %s %sobject size "
600 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
601 (object_size_type
& 2) ? "minimum" : "maximum",
602 (object_size_type
& 1) ? "sub" : "",
603 object_sizes
[object_size_type
][i
]);
607 BITMAP_FREE (osi
.reexamine
);
608 BITMAP_FREE (osi
.visited
);
611 return object_sizes
[object_size_type
][SSA_NAME_VERSION (ptr
)];
614 return unknown
[object_size_type
];
617 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */
620 expr_object_size (struct object_size_info
*osi
, tree ptr
, tree value
)
622 int object_size_type
= osi
->object_size_type
;
623 unsigned int varno
= SSA_NAME_VERSION (ptr
);
624 unsigned HOST_WIDE_INT bytes
;
626 gcc_assert (object_sizes
[object_size_type
][varno
]
627 != unknown
[object_size_type
]);
628 gcc_assert (osi
->pass
== 0);
630 if (TREE_CODE (value
) == WITH_SIZE_EXPR
)
631 value
= TREE_OPERAND (value
, 0);
633 /* Pointer variables should have been handled by merge_object_sizes. */
634 gcc_assert (TREE_CODE (value
) != SSA_NAME
635 || !POINTER_TYPE_P (TREE_TYPE (value
)));
637 if (TREE_CODE (value
) == ADDR_EXPR
)
638 bytes
= addr_object_size (osi
, value
, object_size_type
);
640 bytes
= unknown
[object_size_type
];
642 if ((object_size_type
& 2) == 0)
644 if (object_sizes
[object_size_type
][varno
] < bytes
)
645 object_sizes
[object_size_type
][varno
] = bytes
;
649 if (object_sizes
[object_size_type
][varno
] > bytes
)
650 object_sizes
[object_size_type
][varno
] = bytes
;
655 /* Compute object_sizes for PTR, defined to the result of a call. */
658 call_object_size (struct object_size_info
*osi
, tree ptr
, gimple call
)
660 int object_size_type
= osi
->object_size_type
;
661 unsigned int varno
= SSA_NAME_VERSION (ptr
);
662 unsigned HOST_WIDE_INT bytes
;
664 gcc_assert (is_gimple_call (call
));
666 gcc_assert (object_sizes
[object_size_type
][varno
]
667 != unknown
[object_size_type
]);
668 gcc_assert (osi
->pass
== 0);
670 bytes
= alloc_object_size (call
, object_size_type
);
672 if ((object_size_type
& 2) == 0)
674 if (object_sizes
[object_size_type
][varno
] < bytes
)
675 object_sizes
[object_size_type
][varno
] = bytes
;
679 if (object_sizes
[object_size_type
][varno
] > bytes
)
680 object_sizes
[object_size_type
][varno
] = bytes
;
685 /* Compute object_sizes for PTR, defined to an unknown value. */
688 unknown_object_size (struct object_size_info
*osi
, tree ptr
)
690 int object_size_type
= osi
->object_size_type
;
691 unsigned int varno
= SSA_NAME_VERSION (ptr
);
692 unsigned HOST_WIDE_INT bytes
;
694 gcc_assert (object_sizes
[object_size_type
][varno
]
695 != unknown
[object_size_type
]);
696 gcc_assert (osi
->pass
== 0);
698 bytes
= unknown
[object_size_type
];
700 if ((object_size_type
& 2) == 0)
702 if (object_sizes
[object_size_type
][varno
] < bytes
)
703 object_sizes
[object_size_type
][varno
] = bytes
;
707 if (object_sizes
[object_size_type
][varno
] > bytes
)
708 object_sizes
[object_size_type
][varno
] = bytes
;
713 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
714 the object size might need reexamination later. */
717 merge_object_sizes (struct object_size_info
*osi
, tree dest
, tree orig
,
718 unsigned HOST_WIDE_INT offset
)
720 int object_size_type
= osi
->object_size_type
;
721 unsigned int varno
= SSA_NAME_VERSION (dest
);
722 unsigned HOST_WIDE_INT orig_bytes
;
724 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
726 if (offset
>= offset_limit
)
728 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
733 collect_object_sizes_for (osi
, orig
);
735 orig_bytes
= object_sizes
[object_size_type
][SSA_NAME_VERSION (orig
)];
736 if (orig_bytes
!= unknown
[object_size_type
])
737 orig_bytes
= (offset
> orig_bytes
)
738 ? (unsigned HOST_WIDE_INT
) 0 : orig_bytes
- offset
;
740 if ((object_size_type
& 2) == 0)
742 if (object_sizes
[object_size_type
][varno
] < orig_bytes
)
744 object_sizes
[object_size_type
][varno
] = orig_bytes
;
750 if (object_sizes
[object_size_type
][varno
] > orig_bytes
)
752 object_sizes
[object_size_type
][varno
] = orig_bytes
;
756 return bitmap_bit_p (osi
->reexamine
, SSA_NAME_VERSION (orig
));
760 /* Compute object_sizes for VAR, defined to the result of an assignment
761 with operator POINTER_PLUS_EXPR. Return true if the object size might
762 need reexamination later. */
765 plus_stmt_object_size (struct object_size_info
*osi
, tree var
, gimple stmt
)
767 int object_size_type
= osi
->object_size_type
;
768 unsigned int varno
= SSA_NAME_VERSION (var
);
769 unsigned HOST_WIDE_INT bytes
;
772 if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
774 op0
= gimple_assign_rhs1 (stmt
);
775 op1
= gimple_assign_rhs2 (stmt
);
777 else if (gimple_assign_rhs_code (stmt
) == ADDR_EXPR
)
779 tree rhs
= TREE_OPERAND (gimple_assign_rhs1 (stmt
), 0);
780 gcc_assert (TREE_CODE (rhs
) == MEM_REF
);
781 op0
= TREE_OPERAND (rhs
, 0);
782 op1
= TREE_OPERAND (rhs
, 1);
787 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
790 /* Handle PTR + OFFSET here. */
791 if (TREE_CODE (op1
) == INTEGER_CST
792 && (TREE_CODE (op0
) == SSA_NAME
793 || TREE_CODE (op0
) == ADDR_EXPR
))
795 if (! host_integerp (op1
, 1))
796 bytes
= unknown
[object_size_type
];
797 else if (TREE_CODE (op0
) == SSA_NAME
)
798 return merge_object_sizes (osi
, var
, op0
, tree_low_cst (op1
, 1));
801 unsigned HOST_WIDE_INT off
= tree_low_cst (op1
, 1);
803 /* op0 will be ADDR_EXPR here. */
804 bytes
= addr_object_size (osi
, op0
, object_size_type
);
805 if (bytes
== unknown
[object_size_type
])
807 else if (off
> offset_limit
)
808 bytes
= unknown
[object_size_type
];
809 else if (off
> bytes
)
816 bytes
= unknown
[object_size_type
];
818 if ((object_size_type
& 2) == 0)
820 if (object_sizes
[object_size_type
][varno
] < bytes
)
821 object_sizes
[object_size_type
][varno
] = bytes
;
825 if (object_sizes
[object_size_type
][varno
] > bytes
)
826 object_sizes
[object_size_type
][varno
] = bytes
;
832 /* Compute object_sizes for VAR, defined at STMT, which is
833 a COND_EXPR. Return true if the object size might need reexamination
837 cond_expr_object_size (struct object_size_info
*osi
, tree var
, gimple stmt
)
840 int object_size_type
= osi
->object_size_type
;
841 unsigned int varno
= SSA_NAME_VERSION (var
);
842 bool reexamine
= false;
844 gcc_assert (gimple_assign_rhs_code (stmt
) == COND_EXPR
);
846 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
849 then_
= gimple_assign_rhs2 (stmt
);
850 else_
= gimple_assign_rhs3 (stmt
);
852 if (TREE_CODE (then_
) == SSA_NAME
)
853 reexamine
|= merge_object_sizes (osi
, var
, then_
, 0);
855 expr_object_size (osi
, var
, then_
);
857 if (TREE_CODE (else_
) == SSA_NAME
)
858 reexamine
|= merge_object_sizes (osi
, var
, else_
, 0);
860 expr_object_size (osi
, var
, else_
);
865 /* Compute object sizes for VAR.
866 For ADDR_EXPR an object size is the number of remaining bytes
867 to the end of the object (where what is considered an object depends on
868 OSI->object_size_type).
869 For allocation GIMPLE_CALL like malloc or calloc object size is the size
871 For POINTER_PLUS_EXPR where second operand is a constant integer,
872 object size is object size of the first operand minus the constant.
873 If the constant is bigger than the number of remaining bytes until the
874 end of the object, object size is 0, but if it is instead a pointer
875 subtraction, object size is unknown[object_size_type].
876 To differentiate addition from subtraction, ADDR_EXPR returns
877 unknown[object_size_type] for all objects bigger than half of the address
878 space, and constants less than half of the address space are considered
879 addition, while bigger constants subtraction.
880 For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
881 object size is object size of that argument.
882 Otherwise, object size is the maximum of object sizes of variables
883 that it might be set to. */
886 collect_object_sizes_for (struct object_size_info
*osi
, tree var
)
888 int object_size_type
= osi
->object_size_type
;
889 unsigned int varno
= SSA_NAME_VERSION (var
);
893 if (bitmap_bit_p (computed
[object_size_type
], varno
))
898 if (bitmap_set_bit (osi
->visited
, varno
))
900 object_sizes
[object_size_type
][varno
]
901 = (object_size_type
& 2) ? -1 : 0;
905 /* Found a dependency loop. Mark the variable for later
907 bitmap_set_bit (osi
->reexamine
, varno
);
908 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
910 fprintf (dump_file
, "Found a dependency loop at ");
911 print_generic_expr (dump_file
, var
, dump_flags
);
912 fprintf (dump_file
, "\n");
918 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
920 fprintf (dump_file
, "Visiting use-def links for ");
921 print_generic_expr (dump_file
, var
, dump_flags
);
922 fprintf (dump_file
, "\n");
925 stmt
= SSA_NAME_DEF_STMT (var
);
928 switch (gimple_code (stmt
))
932 tree rhs
= gimple_assign_rhs1 (stmt
);
933 if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
934 || (gimple_assign_rhs_code (stmt
) == ADDR_EXPR
935 && TREE_CODE (TREE_OPERAND (rhs
, 0)) == MEM_REF
))
936 reexamine
= plus_stmt_object_size (osi
, var
, stmt
);
937 else if (gimple_assign_rhs_code (stmt
) == COND_EXPR
)
938 reexamine
= cond_expr_object_size (osi
, var
, stmt
);
939 else if (gimple_assign_single_p (stmt
)
940 || gimple_assign_unary_nop_p (stmt
))
942 if (TREE_CODE (rhs
) == SSA_NAME
943 && POINTER_TYPE_P (TREE_TYPE (rhs
)))
944 reexamine
= merge_object_sizes (osi
, var
, rhs
, 0);
946 expr_object_size (osi
, var
, rhs
);
949 unknown_object_size (osi
, var
);
955 tree arg
= pass_through_call (stmt
);
958 if (TREE_CODE (arg
) == SSA_NAME
959 && POINTER_TYPE_P (TREE_TYPE (arg
)))
960 reexamine
= merge_object_sizes (osi
, var
, arg
, 0);
962 expr_object_size (osi
, var
, arg
);
965 call_object_size (osi
, var
, stmt
);
970 /* Pointers defined by __asm__ statements can point anywhere. */
971 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
975 if (SSA_NAME_VAR (var
)
976 && TREE_CODE (SSA_NAME_VAR (var
)) == PARM_DECL
)
977 expr_object_size (osi
, var
, SSA_NAME_VAR (var
));
979 /* Uninitialized SSA names point nowhere. */
980 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
987 for (i
= 0; i
< gimple_phi_num_args (stmt
); i
++)
989 tree rhs
= gimple_phi_arg (stmt
, i
)->def
;
991 if (object_sizes
[object_size_type
][varno
]
992 == unknown
[object_size_type
])
995 if (TREE_CODE (rhs
) == SSA_NAME
)
996 reexamine
|= merge_object_sizes (osi
, var
, rhs
, 0);
997 else if (osi
->pass
== 0)
998 expr_object_size (osi
, var
, rhs
);
1008 || object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
1010 bitmap_set_bit (computed
[object_size_type
], varno
);
1011 bitmap_clear_bit (osi
->reexamine
, varno
);
1015 bitmap_set_bit (osi
->reexamine
, varno
);
1016 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1018 fprintf (dump_file
, "Need to reexamine ");
1019 print_generic_expr (dump_file
, var
, dump_flags
);
1020 fprintf (dump_file
, "\n");
1026 /* Helper function for check_for_plus_in_loops. Called recursively
1030 check_for_plus_in_loops_1 (struct object_size_info
*osi
, tree var
,
1033 gimple stmt
= SSA_NAME_DEF_STMT (var
);
1034 unsigned int varno
= SSA_NAME_VERSION (var
);
1036 if (osi
->depths
[varno
])
1038 if (osi
->depths
[varno
] != depth
)
1042 /* Found a loop involving pointer addition. */
1043 for (sp
= osi
->tos
; sp
> osi
->stack
; )
1046 bitmap_clear_bit (osi
->reexamine
, *sp
);
1047 bitmap_set_bit (computed
[osi
->object_size_type
], *sp
);
1048 object_sizes
[osi
->object_size_type
][*sp
] = 0;
1055 else if (! bitmap_bit_p (osi
->reexamine
, varno
))
1058 osi
->depths
[varno
] = depth
;
1059 *osi
->tos
++ = varno
;
1061 switch (gimple_code (stmt
))
1066 if ((gimple_assign_single_p (stmt
)
1067 || gimple_assign_unary_nop_p (stmt
))
1068 && TREE_CODE (gimple_assign_rhs1 (stmt
)) == SSA_NAME
)
1070 tree rhs
= gimple_assign_rhs1 (stmt
);
1072 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
1074 else if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
1076 tree basevar
= gimple_assign_rhs1 (stmt
);
1077 tree cst
= gimple_assign_rhs2 (stmt
);
1079 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
1081 check_for_plus_in_loops_1 (osi
, basevar
,
1082 depth
+ !integer_zerop (cst
));
1091 tree arg
= pass_through_call (stmt
);
1094 if (TREE_CODE (arg
) == SSA_NAME
)
1095 check_for_plus_in_loops_1 (osi
, arg
, depth
);
1106 for (i
= 0; i
< gimple_phi_num_args (stmt
); i
++)
1108 tree rhs
= gimple_phi_arg (stmt
, i
)->def
;
1110 if (TREE_CODE (rhs
) == SSA_NAME
)
1111 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
1120 osi
->depths
[varno
] = 0;
1125 /* Check if some pointer we are computing object size of is being increased
1126 within a loop. If yes, assume all the SSA variables participating in
1127 that loop have minimum object sizes 0. */
1130 check_for_plus_in_loops (struct object_size_info
*osi
, tree var
)
1132 gimple stmt
= SSA_NAME_DEF_STMT (var
);
1134 /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
1135 and looked for a POINTER_PLUS_EXPR in the pass-through
1136 argument, if any. In GIMPLE, however, such an expression
1137 is not a valid call operand. */
1139 if (is_gimple_assign (stmt
)
1140 && gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
1142 tree basevar
= gimple_assign_rhs1 (stmt
);
1143 tree cst
= gimple_assign_rhs2 (stmt
);
1145 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
1147 if (integer_zerop (cst
))
1150 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 1;
1151 *osi
->tos
++ = SSA_NAME_VERSION (basevar
);
1152 check_for_plus_in_loops_1 (osi
, var
, 2);
1153 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 0;
1159 /* Initialize data structures for the object size computation. */
1162 init_object_sizes (void)
1164 int object_size_type
;
1166 if (object_sizes
[0])
1169 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
1171 object_sizes
[object_size_type
] = XNEWVEC (unsigned HOST_WIDE_INT
, num_ssa_names
);
1172 computed
[object_size_type
] = BITMAP_ALLOC (NULL
);
1175 init_offset_limit ();
1179 /* Destroy data structures after the object size computation. */
1182 fini_object_sizes (void)
1184 int object_size_type
;
1186 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
1188 free (object_sizes
[object_size_type
]);
1189 BITMAP_FREE (computed
[object_size_type
]);
1190 object_sizes
[object_size_type
] = NULL
;
1195 /* Simple pass to optimize all __builtin_object_size () builtins. */
1198 compute_object_sizes (void)
1203 gimple_stmt_iterator i
;
1204 for (i
= gsi_start_bb (bb
); !gsi_end_p (i
); gsi_next (&i
))
1206 tree callee
, result
;
1207 gimple call
= gsi_stmt (i
);
1209 if (gimple_code (call
) != GIMPLE_CALL
)
1212 callee
= gimple_call_fndecl (call
);
1214 || DECL_BUILT_IN_CLASS (callee
) != BUILT_IN_NORMAL
1215 || DECL_FUNCTION_CODE (callee
) != BUILT_IN_OBJECT_SIZE
)
1218 init_object_sizes ();
1219 result
= fold_call_stmt (call
, false);
1222 if (gimple_call_num_args (call
) == 2
1223 && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call
, 0))))
1225 tree ost
= gimple_call_arg (call
, 1);
1227 if (host_integerp (ost
, 1))
1229 unsigned HOST_WIDE_INT object_size_type
1230 = tree_low_cst (ost
, 1);
1232 if (object_size_type
< 2)
1233 result
= fold_convert (size_type_node
,
1234 integer_minus_one_node
);
1235 else if (object_size_type
< 4)
1236 result
= build_zero_cst (size_type_node
);
1244 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1246 fprintf (dump_file
, "Simplified\n ");
1247 print_gimple_stmt (dump_file
, call
, 0, dump_flags
);
1250 if (!update_call_from_tree (&i
, result
))
1253 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1255 fprintf (dump_file
, "to\n ");
1256 print_gimple_stmt (dump_file
, gsi_stmt (i
), 0, dump_flags
);
1257 fprintf (dump_file
, "\n");
1262 fini_object_sizes ();
1266 struct gimple_opt_pass pass_object_sizes
=
1271 OPTGROUP_NONE
, /* optinfo_flags */
1273 compute_object_sizes
, /* execute */
1276 0, /* static_pass_number */
1277 TV_NONE
, /* tv_id */
1278 PROP_cfg
| PROP_ssa
, /* properties_required */
1279 0, /* properties_provided */
1280 0, /* properties_destroyed */
1281 0, /* todo_flags_start */
1282 TODO_verify_ssa
/* todo_flags_finish */