1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004-2014 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"
26 #include "tree-object-size.h"
27 #include "diagnostic-core.h"
28 #include "gimple-pretty-print.h"
30 #include "basic-block.h"
31 #include "tree-ssa-alias.h"
32 #include "internal-fn.h"
33 #include "gimple-fold.h"
34 #include "gimple-expr.h"
37 #include "gimple-iterator.h"
38 #include "gimple-ssa.h"
39 #include "stringpool.h"
40 #include "tree-ssanames.h"
41 #include "tree-pass.h"
42 #include "tree-ssa-propagate.h"
43 #include "tree-phinodes.h"
44 #include "ssa-iterators.h"
46 struct object_size_info
49 bitmap visited
, reexamine
;
53 unsigned int *stack
, *tos
;
56 static const unsigned HOST_WIDE_INT unknown
[4] = { -1, -1, 0, 0 };
58 static tree
compute_object_offset (const_tree
, const_tree
);
59 static unsigned HOST_WIDE_INT
addr_object_size (struct object_size_info
*,
61 static unsigned HOST_WIDE_INT
alloc_object_size (const_gimple
, int);
62 static tree
pass_through_call (const_gimple
);
63 static void collect_object_sizes_for (struct object_size_info
*, tree
);
64 static void expr_object_size (struct object_size_info
*, tree
, tree
);
65 static bool merge_object_sizes (struct object_size_info
*, tree
, tree
,
66 unsigned HOST_WIDE_INT
);
67 static bool plus_stmt_object_size (struct object_size_info
*, tree
, gimple
);
68 static bool cond_expr_object_size (struct object_size_info
*, tree
, gimple
);
69 static void init_offset_limit (void);
70 static void check_for_plus_in_loops (struct object_size_info
*, tree
);
71 static void check_for_plus_in_loops_1 (struct object_size_info
*, tree
,
74 /* object_sizes[0] is upper bound for number of bytes till the end of
76 object_sizes[1] is upper bound for number of bytes till the end of
77 the subobject (innermost array or field with address taken).
78 object_sizes[2] is lower bound for number of bytes till the end of
79 the object and object_sizes[3] lower bound for subobject. */
80 static vec
<unsigned HOST_WIDE_INT
> object_sizes
[4];
82 /* Bitmaps what object sizes have been computed already. */
83 static bitmap computed
[4];
85 /* Maximum value of offset we consider to be addition. */
86 static unsigned HOST_WIDE_INT offset_limit
;
89 /* Initialize OFFSET_LIMIT variable. */
91 init_offset_limit (void)
93 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (sizetype
)))
94 offset_limit
= tree_to_uhwi (TYPE_MAX_VALUE (sizetype
));
101 /* Compute offset of EXPR within VAR. Return error_mark_node
105 compute_object_offset (const_tree expr
, const_tree var
)
107 enum tree_code code
= PLUS_EXPR
;
111 return size_zero_node
;
113 switch (TREE_CODE (expr
))
116 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
117 if (base
== error_mark_node
)
120 t
= TREE_OPERAND (expr
, 1);
121 off
= size_binop (PLUS_EXPR
, DECL_FIELD_OFFSET (t
),
122 size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t
))
128 case VIEW_CONVERT_EXPR
:
129 case NON_LVALUE_EXPR
:
130 return compute_object_offset (TREE_OPERAND (expr
, 0), var
);
133 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
134 if (base
== error_mark_node
)
137 off
= TYPE_SIZE_UNIT (TREE_TYPE (expr
));
141 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
142 if (base
== error_mark_node
)
145 t
= TREE_OPERAND (expr
, 1);
146 if (TREE_CODE (t
) == INTEGER_CST
&& tree_int_cst_sgn (t
) < 0)
149 t
= fold_build1 (NEGATE_EXPR
, TREE_TYPE (t
), t
);
151 t
= fold_convert (sizetype
, t
);
152 off
= size_binop (MULT_EXPR
, TYPE_SIZE_UNIT (TREE_TYPE (expr
)), t
);
156 gcc_assert (TREE_CODE (TREE_OPERAND (expr
, 0)) == ADDR_EXPR
);
157 return double_int_to_tree (sizetype
, mem_ref_offset (expr
));
160 return error_mark_node
;
163 return size_binop (code
, base
, off
);
167 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
168 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
169 If unknown, return unknown[object_size_type]. */
171 static unsigned HOST_WIDE_INT
172 addr_object_size (struct object_size_info
*osi
, const_tree ptr
,
173 int object_size_type
)
175 tree pt_var
, pt_var_size
= NULL_TREE
, var_size
, bytes
;
177 gcc_assert (TREE_CODE (ptr
) == ADDR_EXPR
);
179 pt_var
= TREE_OPERAND (ptr
, 0);
180 while (handled_component_p (pt_var
))
181 pt_var
= TREE_OPERAND (pt_var
, 0);
184 && TREE_CODE (pt_var
) == MEM_REF
)
186 unsigned HOST_WIDE_INT sz
;
188 if (!osi
|| (object_size_type
& 1) != 0
189 || TREE_CODE (TREE_OPERAND (pt_var
, 0)) != SSA_NAME
)
191 sz
= compute_builtin_object_size (TREE_OPERAND (pt_var
, 0),
192 object_size_type
& ~1);
196 tree var
= TREE_OPERAND (pt_var
, 0);
198 collect_object_sizes_for (osi
, var
);
199 if (bitmap_bit_p (computed
[object_size_type
],
200 SSA_NAME_VERSION (var
)))
201 sz
= object_sizes
[object_size_type
][SSA_NAME_VERSION (var
)];
203 sz
= unknown
[object_size_type
];
205 if (sz
!= unknown
[object_size_type
])
207 double_int dsz
= double_int::from_uhwi (sz
) - mem_ref_offset (pt_var
);
208 if (dsz
.is_negative ())
210 else if (dsz
.fits_uhwi ())
213 sz
= unknown
[object_size_type
];
216 if (sz
!= unknown
[object_size_type
] && sz
< offset_limit
)
217 pt_var_size
= size_int (sz
);
221 && tree_fits_uhwi_p (DECL_SIZE_UNIT (pt_var
))
222 && tree_to_uhwi (DECL_SIZE_UNIT (pt_var
)) < offset_limit
)
223 pt_var_size
= DECL_SIZE_UNIT (pt_var
);
225 && TREE_CODE (pt_var
) == STRING_CST
226 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var
))
227 && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)))
228 && tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)))
230 pt_var_size
= TYPE_SIZE_UNIT (TREE_TYPE (pt_var
));
232 return unknown
[object_size_type
];
234 if (pt_var
!= TREE_OPERAND (ptr
, 0))
238 if (object_size_type
& 1)
240 var
= TREE_OPERAND (ptr
, 0);
243 && TREE_CODE (var
) != BIT_FIELD_REF
244 && TREE_CODE (var
) != COMPONENT_REF
245 && TREE_CODE (var
) != ARRAY_REF
246 && TREE_CODE (var
) != ARRAY_RANGE_REF
247 && TREE_CODE (var
) != REALPART_EXPR
248 && TREE_CODE (var
) != IMAGPART_EXPR
)
249 var
= TREE_OPERAND (var
, 0);
250 if (var
!= pt_var
&& TREE_CODE (var
) == ARRAY_REF
)
251 var
= TREE_OPERAND (var
, 0);
252 if (! TYPE_SIZE_UNIT (TREE_TYPE (var
))
253 || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var
)))
255 && tree_int_cst_lt (pt_var_size
,
256 TYPE_SIZE_UNIT (TREE_TYPE (var
)))))
258 else if (var
!= pt_var
&& TREE_CODE (pt_var
) == MEM_REF
)
261 /* For &X->fld, compute object size only if fld isn't the last
262 field, as struct { int i; char c[1]; } is often used instead
263 of flexible array member. */
264 while (v
&& v
!= pt_var
)
265 switch (TREE_CODE (v
))
268 if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v
, 0)))
269 && TREE_CODE (TREE_OPERAND (v
, 1)) == INTEGER_CST
)
272 = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v
, 0)));
274 && TYPE_MAX_VALUE (domain
)
275 && TREE_CODE (TYPE_MAX_VALUE (domain
))
277 && tree_int_cst_lt (TREE_OPERAND (v
, 1),
278 TYPE_MAX_VALUE (domain
)))
284 v
= TREE_OPERAND (v
, 0);
291 if (TREE_CODE (TREE_TYPE (v
)) != ARRAY_TYPE
)
296 while (v
!= pt_var
&& TREE_CODE (v
) == COMPONENT_REF
)
297 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
299 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
303 v
= TREE_OPERAND (v
, 0);
304 if (TREE_CODE (v
) == COMPONENT_REF
305 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
308 tree fld_chain
= DECL_CHAIN (TREE_OPERAND (v
, 1));
309 for (; fld_chain
; fld_chain
= DECL_CHAIN (fld_chain
))
310 if (TREE_CODE (fld_chain
) == FIELD_DECL
)
318 v
= TREE_OPERAND (v
, 0);
320 while (v
!= pt_var
&& TREE_CODE (v
) == COMPONENT_REF
)
321 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
323 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
327 v
= TREE_OPERAND (v
, 0);
345 var_size
= TYPE_SIZE_UNIT (TREE_TYPE (var
));
346 else if (!pt_var_size
)
347 return unknown
[object_size_type
];
349 var_size
= pt_var_size
;
350 bytes
= compute_object_offset (TREE_OPERAND (ptr
, 0), var
);
351 if (bytes
!= error_mark_node
)
353 if (TREE_CODE (bytes
) == INTEGER_CST
354 && tree_int_cst_lt (var_size
, bytes
))
355 bytes
= size_zero_node
;
357 bytes
= size_binop (MINUS_EXPR
, var_size
, bytes
);
361 && TREE_CODE (pt_var
) == MEM_REF
362 && bytes
!= error_mark_node
)
364 tree bytes2
= compute_object_offset (TREE_OPERAND (ptr
, 0), pt_var
);
365 if (bytes2
!= error_mark_node
)
367 if (TREE_CODE (bytes2
) == INTEGER_CST
368 && tree_int_cst_lt (pt_var_size
, bytes2
))
369 bytes2
= size_zero_node
;
371 bytes2
= size_binop (MINUS_EXPR
, pt_var_size
, bytes2
);
372 bytes
= size_binop (MIN_EXPR
, bytes
, bytes2
);
376 else if (!pt_var_size
)
377 return unknown
[object_size_type
];
381 if (tree_fits_uhwi_p (bytes
))
382 return tree_to_uhwi (bytes
);
384 return unknown
[object_size_type
];
388 /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
389 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
390 argument from __builtin_object_size. If unknown, return
391 unknown[object_size_type]. */
393 static unsigned HOST_WIDE_INT
394 alloc_object_size (const_gimple call
, int object_size_type
)
396 tree callee
, bytes
= NULL_TREE
;
398 int arg1
= -1, arg2
= -1;
400 gcc_assert (is_gimple_call (call
));
402 callee
= gimple_call_fndecl (call
);
404 return unknown
[object_size_type
];
406 alloc_size
= lookup_attribute ("alloc_size",
407 TYPE_ATTRIBUTES (TREE_TYPE (callee
)));
408 if (alloc_size
&& TREE_VALUE (alloc_size
))
410 tree p
= TREE_VALUE (alloc_size
);
412 arg1
= TREE_INT_CST_LOW (TREE_VALUE (p
))-1;
414 arg2
= TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p
)))-1;
417 if (DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
418 switch (DECL_FUNCTION_CODE (callee
))
420 case BUILT_IN_CALLOC
:
423 case BUILT_IN_MALLOC
:
424 case BUILT_IN_ALLOCA
:
425 case BUILT_IN_ALLOCA_WITH_ALIGN
:
431 if (arg1
< 0 || arg1
>= (int)gimple_call_num_args (call
)
432 || TREE_CODE (gimple_call_arg (call
, arg1
)) != INTEGER_CST
434 && (arg2
>= (int)gimple_call_num_args (call
)
435 || TREE_CODE (gimple_call_arg (call
, arg2
)) != INTEGER_CST
)))
436 return unknown
[object_size_type
];
439 bytes
= size_binop (MULT_EXPR
,
440 fold_convert (sizetype
, gimple_call_arg (call
, arg1
)),
441 fold_convert (sizetype
, gimple_call_arg (call
, arg2
)));
443 bytes
= fold_convert (sizetype
, gimple_call_arg (call
, arg1
));
445 if (bytes
&& tree_fits_uhwi_p (bytes
))
446 return tree_to_uhwi (bytes
);
448 return unknown
[object_size_type
];
452 /* If object size is propagated from one of function's arguments directly
453 to its return value, return that argument for GIMPLE_CALL statement CALL.
454 Otherwise return NULL. */
457 pass_through_call (const_gimple call
)
459 tree callee
= gimple_call_fndecl (call
);
462 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
463 switch (DECL_FUNCTION_CODE (callee
))
465 case BUILT_IN_MEMCPY
:
466 case BUILT_IN_MEMMOVE
:
467 case BUILT_IN_MEMSET
:
468 case BUILT_IN_STRCPY
:
469 case BUILT_IN_STRNCPY
:
470 case BUILT_IN_STRCAT
:
471 case BUILT_IN_STRNCAT
:
472 case BUILT_IN_MEMCPY_CHK
:
473 case BUILT_IN_MEMMOVE_CHK
:
474 case BUILT_IN_MEMSET_CHK
:
475 case BUILT_IN_STRCPY_CHK
:
476 case BUILT_IN_STRNCPY_CHK
:
477 case BUILT_IN_STPNCPY_CHK
:
478 case BUILT_IN_STRCAT_CHK
:
479 case BUILT_IN_STRNCAT_CHK
:
480 case BUILT_IN_ASSUME_ALIGNED
:
481 if (gimple_call_num_args (call
) >= 1)
482 return gimple_call_arg (call
, 0);
492 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
493 second argument from __builtin_object_size. */
495 unsigned HOST_WIDE_INT
496 compute_builtin_object_size (tree ptr
, int object_size_type
)
498 gcc_assert (object_size_type
>= 0 && object_size_type
<= 3);
501 init_offset_limit ();
503 if (TREE_CODE (ptr
) == ADDR_EXPR
)
504 return addr_object_size (NULL
, ptr
, object_size_type
);
506 if (TREE_CODE (ptr
) == SSA_NAME
507 && POINTER_TYPE_P (TREE_TYPE (ptr
))
508 && computed
[object_size_type
] != NULL
)
510 if (!bitmap_bit_p (computed
[object_size_type
], SSA_NAME_VERSION (ptr
)))
512 struct object_size_info osi
;
516 if (num_ssa_names
> object_sizes
[object_size_type
].length ())
517 object_sizes
[object_size_type
].safe_grow (num_ssa_names
);
520 fprintf (dump_file
, "Computing %s %sobject size for ",
521 (object_size_type
& 2) ? "minimum" : "maximum",
522 (object_size_type
& 1) ? "sub" : "");
523 print_generic_expr (dump_file
, ptr
, dump_flags
);
524 fprintf (dump_file
, ":\n");
527 osi
.visited
= BITMAP_ALLOC (NULL
);
528 osi
.reexamine
= BITMAP_ALLOC (NULL
);
529 osi
.object_size_type
= object_size_type
;
534 /* First pass: walk UD chains, compute object sizes that
535 can be computed. osi.reexamine bitmap at the end will
536 contain what variables were found in dependency cycles
537 and therefore need to be reexamined. */
540 collect_object_sizes_for (&osi
, ptr
);
542 /* Second pass: keep recomputing object sizes of variables
543 that need reexamination, until no object sizes are
544 increased or all object sizes are computed. */
545 if (! bitmap_empty_p (osi
.reexamine
))
547 bitmap reexamine
= BITMAP_ALLOC (NULL
);
549 /* If looking for minimum instead of maximum object size,
550 detect cases where a pointer is increased in a loop.
551 Although even without this detection pass 2 would eventually
552 terminate, it could take a long time. If a pointer is
553 increasing this way, we need to assume 0 object size.
554 E.g. p = &buf[0]; while (cond) p = p + 4; */
555 if (object_size_type
& 2)
557 osi
.depths
= XCNEWVEC (unsigned int, num_ssa_names
);
558 osi
.stack
= XNEWVEC (unsigned int, num_ssa_names
);
561 /* collect_object_sizes_for is changing
562 osi.reexamine bitmap, so iterate over a copy. */
563 bitmap_copy (reexamine
, osi
.reexamine
);
564 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
565 if (bitmap_bit_p (osi
.reexamine
, i
))
566 check_for_plus_in_loops (&osi
, ssa_name (i
));
579 /* collect_object_sizes_for is changing
580 osi.reexamine bitmap, so iterate over a copy. */
581 bitmap_copy (reexamine
, osi
.reexamine
);
582 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
583 if (bitmap_bit_p (osi
.reexamine
, i
))
585 collect_object_sizes_for (&osi
, ssa_name (i
));
586 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
588 fprintf (dump_file
, "Reexamining ");
589 print_generic_expr (dump_file
, ssa_name (i
),
591 fprintf (dump_file
, "\n");
597 BITMAP_FREE (reexamine
);
599 EXECUTE_IF_SET_IN_BITMAP (osi
.reexamine
, 0, i
, bi
)
600 bitmap_set_bit (computed
[object_size_type
], i
);
602 /* Debugging dumps. */
605 EXECUTE_IF_SET_IN_BITMAP (osi
.visited
, 0, i
, bi
)
606 if (object_sizes
[object_size_type
][i
]
607 != unknown
[object_size_type
])
609 print_generic_expr (dump_file
, ssa_name (i
),
612 ": %s %sobject size "
613 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
614 (object_size_type
& 2) ? "minimum" : "maximum",
615 (object_size_type
& 1) ? "sub" : "",
616 object_sizes
[object_size_type
][i
]);
620 BITMAP_FREE (osi
.reexamine
);
621 BITMAP_FREE (osi
.visited
);
624 return object_sizes
[object_size_type
][SSA_NAME_VERSION (ptr
)];
627 return unknown
[object_size_type
];
630 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */
633 expr_object_size (struct object_size_info
*osi
, tree ptr
, tree value
)
635 int object_size_type
= osi
->object_size_type
;
636 unsigned int varno
= SSA_NAME_VERSION (ptr
);
637 unsigned HOST_WIDE_INT bytes
;
639 gcc_assert (object_sizes
[object_size_type
][varno
]
640 != unknown
[object_size_type
]);
641 gcc_assert (osi
->pass
== 0);
643 if (TREE_CODE (value
) == WITH_SIZE_EXPR
)
644 value
= TREE_OPERAND (value
, 0);
646 /* Pointer variables should have been handled by merge_object_sizes. */
647 gcc_assert (TREE_CODE (value
) != SSA_NAME
648 || !POINTER_TYPE_P (TREE_TYPE (value
)));
650 if (TREE_CODE (value
) == ADDR_EXPR
)
651 bytes
= addr_object_size (osi
, value
, object_size_type
);
653 bytes
= unknown
[object_size_type
];
655 if ((object_size_type
& 2) == 0)
657 if (object_sizes
[object_size_type
][varno
] < bytes
)
658 object_sizes
[object_size_type
][varno
] = bytes
;
662 if (object_sizes
[object_size_type
][varno
] > bytes
)
663 object_sizes
[object_size_type
][varno
] = bytes
;
668 /* Compute object_sizes for PTR, defined to the result of a call. */
671 call_object_size (struct object_size_info
*osi
, tree ptr
, gimple call
)
673 int object_size_type
= osi
->object_size_type
;
674 unsigned int varno
= SSA_NAME_VERSION (ptr
);
675 unsigned HOST_WIDE_INT bytes
;
677 gcc_assert (is_gimple_call (call
));
679 gcc_assert (object_sizes
[object_size_type
][varno
]
680 != unknown
[object_size_type
]);
681 gcc_assert (osi
->pass
== 0);
683 bytes
= alloc_object_size (call
, object_size_type
);
685 if ((object_size_type
& 2) == 0)
687 if (object_sizes
[object_size_type
][varno
] < bytes
)
688 object_sizes
[object_size_type
][varno
] = bytes
;
692 if (object_sizes
[object_size_type
][varno
] > bytes
)
693 object_sizes
[object_size_type
][varno
] = bytes
;
698 /* Compute object_sizes for PTR, defined to an unknown value. */
701 unknown_object_size (struct object_size_info
*osi
, tree ptr
)
703 int object_size_type
= osi
->object_size_type
;
704 unsigned int varno
= SSA_NAME_VERSION (ptr
);
705 unsigned HOST_WIDE_INT bytes
;
707 gcc_assert (object_sizes
[object_size_type
][varno
]
708 != unknown
[object_size_type
]);
709 gcc_assert (osi
->pass
== 0);
711 bytes
= unknown
[object_size_type
];
713 if ((object_size_type
& 2) == 0)
715 if (object_sizes
[object_size_type
][varno
] < bytes
)
716 object_sizes
[object_size_type
][varno
] = bytes
;
720 if (object_sizes
[object_size_type
][varno
] > bytes
)
721 object_sizes
[object_size_type
][varno
] = bytes
;
726 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
727 the object size might need reexamination later. */
730 merge_object_sizes (struct object_size_info
*osi
, tree dest
, tree orig
,
731 unsigned HOST_WIDE_INT offset
)
733 int object_size_type
= osi
->object_size_type
;
734 unsigned int varno
= SSA_NAME_VERSION (dest
);
735 unsigned HOST_WIDE_INT orig_bytes
;
737 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
739 if (offset
>= offset_limit
)
741 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
746 collect_object_sizes_for (osi
, orig
);
748 orig_bytes
= object_sizes
[object_size_type
][SSA_NAME_VERSION (orig
)];
749 if (orig_bytes
!= unknown
[object_size_type
])
750 orig_bytes
= (offset
> orig_bytes
)
751 ? (unsigned HOST_WIDE_INT
) 0 : orig_bytes
- offset
;
753 if ((object_size_type
& 2) == 0)
755 if (object_sizes
[object_size_type
][varno
] < orig_bytes
)
757 object_sizes
[object_size_type
][varno
] = orig_bytes
;
763 if (object_sizes
[object_size_type
][varno
] > orig_bytes
)
765 object_sizes
[object_size_type
][varno
] = orig_bytes
;
769 return bitmap_bit_p (osi
->reexamine
, SSA_NAME_VERSION (orig
));
773 /* Compute object_sizes for VAR, defined to the result of an assignment
774 with operator POINTER_PLUS_EXPR. Return true if the object size might
775 need reexamination later. */
778 plus_stmt_object_size (struct object_size_info
*osi
, tree var
, gimple stmt
)
780 int object_size_type
= osi
->object_size_type
;
781 unsigned int varno
= SSA_NAME_VERSION (var
);
782 unsigned HOST_WIDE_INT bytes
;
785 if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
787 op0
= gimple_assign_rhs1 (stmt
);
788 op1
= gimple_assign_rhs2 (stmt
);
790 else if (gimple_assign_rhs_code (stmt
) == ADDR_EXPR
)
792 tree rhs
= TREE_OPERAND (gimple_assign_rhs1 (stmt
), 0);
793 gcc_assert (TREE_CODE (rhs
) == MEM_REF
);
794 op0
= TREE_OPERAND (rhs
, 0);
795 op1
= TREE_OPERAND (rhs
, 1);
800 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
803 /* Handle PTR + OFFSET here. */
804 if (TREE_CODE (op1
) == INTEGER_CST
805 && (TREE_CODE (op0
) == SSA_NAME
806 || TREE_CODE (op0
) == ADDR_EXPR
))
808 if (! tree_fits_uhwi_p (op1
))
809 bytes
= unknown
[object_size_type
];
810 else if (TREE_CODE (op0
) == SSA_NAME
)
811 return merge_object_sizes (osi
, var
, op0
, tree_to_uhwi (op1
));
814 unsigned HOST_WIDE_INT off
= tree_to_uhwi (op1
);
816 /* op0 will be ADDR_EXPR here. */
817 bytes
= addr_object_size (osi
, op0
, object_size_type
);
818 if (bytes
== unknown
[object_size_type
])
820 else if (off
> offset_limit
)
821 bytes
= unknown
[object_size_type
];
822 else if (off
> bytes
)
829 bytes
= unknown
[object_size_type
];
831 if ((object_size_type
& 2) == 0)
833 if (object_sizes
[object_size_type
][varno
] < bytes
)
834 object_sizes
[object_size_type
][varno
] = bytes
;
838 if (object_sizes
[object_size_type
][varno
] > bytes
)
839 object_sizes
[object_size_type
][varno
] = bytes
;
845 /* Compute object_sizes for VAR, defined at STMT, which is
846 a COND_EXPR. Return true if the object size might need reexamination
850 cond_expr_object_size (struct object_size_info
*osi
, tree var
, gimple stmt
)
853 int object_size_type
= osi
->object_size_type
;
854 unsigned int varno
= SSA_NAME_VERSION (var
);
855 bool reexamine
= false;
857 gcc_assert (gimple_assign_rhs_code (stmt
) == COND_EXPR
);
859 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
862 then_
= gimple_assign_rhs2 (stmt
);
863 else_
= gimple_assign_rhs3 (stmt
);
865 if (TREE_CODE (then_
) == SSA_NAME
)
866 reexamine
|= merge_object_sizes (osi
, var
, then_
, 0);
868 expr_object_size (osi
, var
, then_
);
870 if (TREE_CODE (else_
) == SSA_NAME
)
871 reexamine
|= merge_object_sizes (osi
, var
, else_
, 0);
873 expr_object_size (osi
, var
, else_
);
878 /* Compute object sizes for VAR.
879 For ADDR_EXPR an object size is the number of remaining bytes
880 to the end of the object (where what is considered an object depends on
881 OSI->object_size_type).
882 For allocation GIMPLE_CALL like malloc or calloc object size is the size
884 For POINTER_PLUS_EXPR where second operand is a constant integer,
885 object size is object size of the first operand minus the constant.
886 If the constant is bigger than the number of remaining bytes until the
887 end of the object, object size is 0, but if it is instead a pointer
888 subtraction, object size is unknown[object_size_type].
889 To differentiate addition from subtraction, ADDR_EXPR returns
890 unknown[object_size_type] for all objects bigger than half of the address
891 space, and constants less than half of the address space are considered
892 addition, while bigger constants subtraction.
893 For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
894 object size is object size of that argument.
895 Otherwise, object size is the maximum of object sizes of variables
896 that it might be set to. */
899 collect_object_sizes_for (struct object_size_info
*osi
, tree var
)
901 int object_size_type
= osi
->object_size_type
;
902 unsigned int varno
= SSA_NAME_VERSION (var
);
906 if (bitmap_bit_p (computed
[object_size_type
], varno
))
911 if (bitmap_set_bit (osi
->visited
, varno
))
913 object_sizes
[object_size_type
][varno
]
914 = (object_size_type
& 2) ? -1 : 0;
918 /* Found a dependency loop. Mark the variable for later
920 bitmap_set_bit (osi
->reexamine
, varno
);
921 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
923 fprintf (dump_file
, "Found a dependency loop at ");
924 print_generic_expr (dump_file
, var
, dump_flags
);
925 fprintf (dump_file
, "\n");
931 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
933 fprintf (dump_file
, "Visiting use-def links for ");
934 print_generic_expr (dump_file
, var
, dump_flags
);
935 fprintf (dump_file
, "\n");
938 stmt
= SSA_NAME_DEF_STMT (var
);
941 switch (gimple_code (stmt
))
945 tree rhs
= gimple_assign_rhs1 (stmt
);
946 if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
947 || (gimple_assign_rhs_code (stmt
) == ADDR_EXPR
948 && TREE_CODE (TREE_OPERAND (rhs
, 0)) == MEM_REF
))
949 reexamine
= plus_stmt_object_size (osi
, var
, stmt
);
950 else if (gimple_assign_rhs_code (stmt
) == COND_EXPR
)
951 reexamine
= cond_expr_object_size (osi
, var
, stmt
);
952 else if (gimple_assign_single_p (stmt
)
953 || gimple_assign_unary_nop_p (stmt
))
955 if (TREE_CODE (rhs
) == SSA_NAME
956 && POINTER_TYPE_P (TREE_TYPE (rhs
)))
957 reexamine
= merge_object_sizes (osi
, var
, rhs
, 0);
959 expr_object_size (osi
, var
, rhs
);
962 unknown_object_size (osi
, var
);
968 tree arg
= pass_through_call (stmt
);
971 if (TREE_CODE (arg
) == SSA_NAME
972 && POINTER_TYPE_P (TREE_TYPE (arg
)))
973 reexamine
= merge_object_sizes (osi
, var
, arg
, 0);
975 expr_object_size (osi
, var
, arg
);
978 call_object_size (osi
, var
, stmt
);
983 /* Pointers defined by __asm__ statements can point anywhere. */
984 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
988 if (SSA_NAME_VAR (var
)
989 && TREE_CODE (SSA_NAME_VAR (var
)) == PARM_DECL
)
990 expr_object_size (osi
, var
, SSA_NAME_VAR (var
));
992 /* Uninitialized SSA names point nowhere. */
993 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
1000 for (i
= 0; i
< gimple_phi_num_args (stmt
); i
++)
1002 tree rhs
= gimple_phi_arg (stmt
, i
)->def
;
1004 if (object_sizes
[object_size_type
][varno
]
1005 == unknown
[object_size_type
])
1008 if (TREE_CODE (rhs
) == SSA_NAME
)
1009 reexamine
|= merge_object_sizes (osi
, var
, rhs
, 0);
1010 else if (osi
->pass
== 0)
1011 expr_object_size (osi
, var
, rhs
);
1021 || object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
1023 bitmap_set_bit (computed
[object_size_type
], varno
);
1024 bitmap_clear_bit (osi
->reexamine
, varno
);
1028 bitmap_set_bit (osi
->reexamine
, varno
);
1029 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1031 fprintf (dump_file
, "Need to reexamine ");
1032 print_generic_expr (dump_file
, var
, dump_flags
);
1033 fprintf (dump_file
, "\n");
1039 /* Helper function for check_for_plus_in_loops. Called recursively
1043 check_for_plus_in_loops_1 (struct object_size_info
*osi
, tree var
,
1046 gimple stmt
= SSA_NAME_DEF_STMT (var
);
1047 unsigned int varno
= SSA_NAME_VERSION (var
);
1049 if (osi
->depths
[varno
])
1051 if (osi
->depths
[varno
] != depth
)
1055 /* Found a loop involving pointer addition. */
1056 for (sp
= osi
->tos
; sp
> osi
->stack
; )
1059 bitmap_clear_bit (osi
->reexamine
, *sp
);
1060 bitmap_set_bit (computed
[osi
->object_size_type
], *sp
);
1061 object_sizes
[osi
->object_size_type
][*sp
] = 0;
1068 else if (! bitmap_bit_p (osi
->reexamine
, varno
))
1071 osi
->depths
[varno
] = depth
;
1072 *osi
->tos
++ = varno
;
1074 switch (gimple_code (stmt
))
1079 if ((gimple_assign_single_p (stmt
)
1080 || gimple_assign_unary_nop_p (stmt
))
1081 && TREE_CODE (gimple_assign_rhs1 (stmt
)) == SSA_NAME
)
1083 tree rhs
= gimple_assign_rhs1 (stmt
);
1085 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
1087 else if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
1089 tree basevar
= gimple_assign_rhs1 (stmt
);
1090 tree cst
= gimple_assign_rhs2 (stmt
);
1092 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
1094 check_for_plus_in_loops_1 (osi
, basevar
,
1095 depth
+ !integer_zerop (cst
));
1104 tree arg
= pass_through_call (stmt
);
1107 if (TREE_CODE (arg
) == SSA_NAME
)
1108 check_for_plus_in_loops_1 (osi
, arg
, depth
);
1119 for (i
= 0; i
< gimple_phi_num_args (stmt
); i
++)
1121 tree rhs
= gimple_phi_arg (stmt
, i
)->def
;
1123 if (TREE_CODE (rhs
) == SSA_NAME
)
1124 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
1133 osi
->depths
[varno
] = 0;
1138 /* Check if some pointer we are computing object size of is being increased
1139 within a loop. If yes, assume all the SSA variables participating in
1140 that loop have minimum object sizes 0. */
1143 check_for_plus_in_loops (struct object_size_info
*osi
, tree var
)
1145 gimple stmt
= SSA_NAME_DEF_STMT (var
);
1147 /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
1148 and looked for a POINTER_PLUS_EXPR in the pass-through
1149 argument, if any. In GIMPLE, however, such an expression
1150 is not a valid call operand. */
1152 if (is_gimple_assign (stmt
)
1153 && gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
1155 tree basevar
= gimple_assign_rhs1 (stmt
);
1156 tree cst
= gimple_assign_rhs2 (stmt
);
1158 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
1160 if (integer_zerop (cst
))
1163 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 1;
1164 *osi
->tos
++ = SSA_NAME_VERSION (basevar
);
1165 check_for_plus_in_loops_1 (osi
, var
, 2);
1166 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 0;
1172 /* Initialize data structures for the object size computation. */
1175 init_object_sizes (void)
1177 int object_size_type
;
1182 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
1184 object_sizes
[object_size_type
].safe_grow (num_ssa_names
);
1185 computed
[object_size_type
] = BITMAP_ALLOC (NULL
);
1188 init_offset_limit ();
1192 /* Destroy data structures after the object size computation. */
1195 fini_object_sizes (void)
1197 int object_size_type
;
1199 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
1201 object_sizes
[object_size_type
].release ();
1202 BITMAP_FREE (computed
[object_size_type
]);
1207 /* Simple pass to optimize all __builtin_object_size () builtins. */
1211 const pass_data pass_data_object_sizes
=
1213 GIMPLE_PASS
, /* type */
1215 OPTGROUP_NONE
, /* optinfo_flags */
1216 true, /* has_execute */
1217 TV_NONE
, /* tv_id */
1218 ( PROP_cfg
| PROP_ssa
), /* properties_required */
1219 0, /* properties_provided */
1220 0, /* properties_destroyed */
1221 0, /* todo_flags_start */
1222 TODO_verify_ssa
, /* todo_flags_finish */
1225 class pass_object_sizes
: public gimple_opt_pass
1228 pass_object_sizes (gcc::context
*ctxt
)
1229 : gimple_opt_pass (pass_data_object_sizes
, ctxt
)
1232 /* opt_pass methods: */
1233 opt_pass
* clone () { return new pass_object_sizes (m_ctxt
); }
1234 virtual unsigned int execute (function
*);
1236 }; // class pass_object_sizes
1239 pass_object_sizes::execute (function
*fun
)
1242 FOR_EACH_BB_FN (bb
, fun
)
1244 gimple_stmt_iterator i
;
1245 for (i
= gsi_start_bb (bb
); !gsi_end_p (i
); gsi_next (&i
))
1248 gimple call
= gsi_stmt (i
);
1249 if (!gimple_call_builtin_p (call
, BUILT_IN_OBJECT_SIZE
))
1252 init_object_sizes ();
1253 result
= fold_call_stmt (call
, false);
1256 if (gimple_call_num_args (call
) == 2
1257 && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call
, 0))))
1259 tree ost
= gimple_call_arg (call
, 1);
1261 if (tree_fits_uhwi_p (ost
))
1263 unsigned HOST_WIDE_INT object_size_type
1264 = tree_to_uhwi (ost
);
1266 if (object_size_type
< 2)
1267 result
= fold_convert (size_type_node
,
1268 integer_minus_one_node
);
1269 else if (object_size_type
< 4)
1270 result
= build_zero_cst (size_type_node
);
1278 gcc_assert (TREE_CODE (result
) == INTEGER_CST
);
1280 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1282 fprintf (dump_file
, "Simplified\n ");
1283 print_gimple_stmt (dump_file
, call
, 0, dump_flags
);
1284 fprintf (dump_file
, " to ");
1285 print_generic_expr (dump_file
, result
, 0);
1286 fprintf (dump_file
, "\n");
1289 tree lhs
= gimple_call_lhs (call
);
1293 /* Propagate into all uses and fold those stmts. */
1295 imm_use_iterator iter
;
1296 FOR_EACH_IMM_USE_STMT (use_stmt
, iter
, lhs
)
1298 use_operand_p use_p
;
1299 FOR_EACH_IMM_USE_ON_STMT (use_p
, iter
)
1300 SET_USE (use_p
, result
);
1301 gimple_stmt_iterator gsi
= gsi_for_stmt (use_stmt
);
1303 update_stmt (gsi_stmt (gsi
));
1308 fini_object_sizes ();
1315 make_pass_object_sizes (gcc::context
*ctxt
)
1317 return new pass_object_sizes (ctxt
);