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"
28 #include "diagnostic.h"
29 #include "tree-pretty-print.h"
30 #include "gimple-pretty-print.h"
31 #include "tree-flow.h"
32 #include "tree-pass.h"
33 #include "tree-ssa-propagate.h"
35 struct object_size_info
38 bitmap visited
, reexamine
;
42 unsigned int *stack
, *tos
;
45 static unsigned HOST_WIDE_INT unknown
[4] = { -1, -1, 0, 0 };
47 static tree
compute_object_offset (const_tree
, const_tree
);
48 static unsigned HOST_WIDE_INT
addr_object_size (struct object_size_info
*,
50 static unsigned HOST_WIDE_INT
alloc_object_size (const_gimple
, int);
51 static tree
pass_through_call (const_gimple
);
52 static void collect_object_sizes_for (struct object_size_info
*, tree
);
53 static void expr_object_size (struct object_size_info
*, tree
, tree
);
54 static bool merge_object_sizes (struct object_size_info
*, tree
, tree
,
55 unsigned HOST_WIDE_INT
);
56 static bool plus_stmt_object_size (struct object_size_info
*, tree
, gimple
);
57 static bool cond_expr_object_size (struct object_size_info
*, tree
, tree
);
58 static unsigned int compute_object_sizes (void);
59 static void init_offset_limit (void);
60 static void check_for_plus_in_loops (struct object_size_info
*, tree
);
61 static void check_for_plus_in_loops_1 (struct object_size_info
*, tree
,
64 /* object_sizes[0] is upper bound for number of bytes till the end of
66 object_sizes[1] is upper bound for number of bytes till the end of
67 the subobject (innermost array or field with address taken).
68 object_sizes[2] is lower bound for number of bytes till the end of
69 the object and object_sizes[3] lower bound for subobject. */
70 static unsigned HOST_WIDE_INT
*object_sizes
[4];
72 /* Bitmaps what object sizes have been computed already. */
73 static bitmap computed
[4];
75 /* Maximum value of offset we consider to be addition. */
76 static unsigned HOST_WIDE_INT offset_limit
;
79 /* Initialize OFFSET_LIMIT variable. */
81 init_offset_limit (void)
83 if (host_integerp (TYPE_MAX_VALUE (sizetype
), 1))
84 offset_limit
= tree_low_cst (TYPE_MAX_VALUE (sizetype
), 1);
91 /* Compute offset of EXPR within VAR. Return error_mark_node
95 compute_object_offset (const_tree expr
, const_tree var
)
97 enum tree_code code
= PLUS_EXPR
;
101 return size_zero_node
;
103 switch (TREE_CODE (expr
))
106 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
107 if (base
== error_mark_node
)
110 t
= TREE_OPERAND (expr
, 1);
111 off
= size_binop (PLUS_EXPR
, DECL_FIELD_OFFSET (t
),
112 size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t
), 1)
118 case VIEW_CONVERT_EXPR
:
119 case NON_LVALUE_EXPR
:
120 return compute_object_offset (TREE_OPERAND (expr
, 0), var
);
123 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
124 if (base
== error_mark_node
)
127 off
= TYPE_SIZE_UNIT (TREE_TYPE (expr
));
131 base
= compute_object_offset (TREE_OPERAND (expr
, 0), var
);
132 if (base
== error_mark_node
)
135 t
= TREE_OPERAND (expr
, 1);
136 if (TREE_CODE (t
) == INTEGER_CST
&& tree_int_cst_sgn (t
) < 0)
139 t
= fold_build1 (NEGATE_EXPR
, TREE_TYPE (t
), t
);
141 t
= fold_convert (sizetype
, t
);
142 off
= size_binop (MULT_EXPR
, TYPE_SIZE_UNIT (TREE_TYPE (expr
)), t
);
146 return error_mark_node
;
149 return size_binop (code
, base
, off
);
153 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
154 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
155 If unknown, return unknown[object_size_type]. */
157 static unsigned HOST_WIDE_INT
158 addr_object_size (struct object_size_info
*osi
, const_tree ptr
,
159 int object_size_type
)
161 tree pt_var
, pt_var_size
= NULL_TREE
, var_size
, bytes
;
163 gcc_assert (TREE_CODE (ptr
) == ADDR_EXPR
);
165 pt_var
= TREE_OPERAND (ptr
, 0);
166 if (REFERENCE_CLASS_P (pt_var
))
167 pt_var
= get_base_address (pt_var
);
170 && TREE_CODE (pt_var
) == INDIRECT_REF
171 && TREE_CODE (TREE_OPERAND (pt_var
, 0)) == SSA_NAME
172 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (pt_var
, 0))))
174 unsigned HOST_WIDE_INT sz
;
176 if (!osi
|| (object_size_type
& 1) != 0)
177 sz
= compute_builtin_object_size (TREE_OPERAND (pt_var
, 0),
178 object_size_type
& ~1);
181 tree var
= TREE_OPERAND (pt_var
, 0);
183 collect_object_sizes_for (osi
, var
);
184 if (bitmap_bit_p (computed
[object_size_type
],
185 SSA_NAME_VERSION (var
)))
186 sz
= object_sizes
[object_size_type
][SSA_NAME_VERSION (var
)];
188 sz
= unknown
[object_size_type
];
191 if (sz
!= unknown
[object_size_type
] && sz
< offset_limit
)
192 pt_var_size
= size_int (sz
);
195 && (SSA_VAR_P (pt_var
) || TREE_CODE (pt_var
) == STRING_CST
)
196 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var
))
197 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)), 1)
198 && (unsigned HOST_WIDE_INT
)
199 tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var
)), 1)
201 pt_var_size
= TYPE_SIZE_UNIT (TREE_TYPE (pt_var
));
203 return unknown
[object_size_type
];
205 if (pt_var
!= TREE_OPERAND (ptr
, 0))
209 if (object_size_type
& 1)
211 var
= TREE_OPERAND (ptr
, 0);
214 && TREE_CODE (var
) != BIT_FIELD_REF
215 && TREE_CODE (var
) != COMPONENT_REF
216 && TREE_CODE (var
) != ARRAY_REF
217 && TREE_CODE (var
) != ARRAY_RANGE_REF
218 && TREE_CODE (var
) != REALPART_EXPR
219 && TREE_CODE (var
) != IMAGPART_EXPR
)
220 var
= TREE_OPERAND (var
, 0);
221 if (var
!= pt_var
&& TREE_CODE (var
) == ARRAY_REF
)
222 var
= TREE_OPERAND (var
, 0);
223 if (! TYPE_SIZE_UNIT (TREE_TYPE (var
))
224 || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var
)), 1)
226 && tree_int_cst_lt (pt_var_size
,
227 TYPE_SIZE_UNIT (TREE_TYPE (var
)))))
229 else if (var
!= pt_var
&& TREE_CODE (pt_var
) == INDIRECT_REF
)
232 /* For &X->fld, compute object size only if fld isn't the last
233 field, as struct { int i; char c[1]; } is often used instead
234 of flexible array member. */
235 while (v
&& v
!= pt_var
)
236 switch (TREE_CODE (v
))
239 if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v
, 0)))
240 && TREE_CODE (TREE_OPERAND (v
, 1)) == INTEGER_CST
)
243 = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v
, 0)));
245 && TYPE_MAX_VALUE (domain
)
246 && TREE_CODE (TYPE_MAX_VALUE (domain
))
248 && tree_int_cst_lt (TREE_OPERAND (v
, 1),
249 TYPE_MAX_VALUE (domain
)))
255 v
= TREE_OPERAND (v
, 0);
262 if (TREE_CODE (TREE_TYPE (v
)) != ARRAY_TYPE
)
267 while (v
!= pt_var
&& TREE_CODE (v
) == COMPONENT_REF
)
268 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
270 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
274 v
= TREE_OPERAND (v
, 0);
275 if (TREE_CODE (v
) == COMPONENT_REF
276 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
279 tree fld_chain
= TREE_CHAIN (TREE_OPERAND (v
, 1));
280 for (; fld_chain
; fld_chain
= TREE_CHAIN (fld_chain
))
281 if (TREE_CODE (fld_chain
) == FIELD_DECL
)
289 v
= TREE_OPERAND (v
, 0);
291 while (v
!= pt_var
&& TREE_CODE (v
) == COMPONENT_REF
)
292 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
294 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v
, 0)))
298 v
= TREE_OPERAND (v
, 0);
316 var_size
= TYPE_SIZE_UNIT (TREE_TYPE (var
));
317 else if (!pt_var_size
)
318 return unknown
[object_size_type
];
320 var_size
= pt_var_size
;
321 bytes
= compute_object_offset (TREE_OPERAND (ptr
, 0), var
);
322 if (bytes
!= error_mark_node
)
324 if (TREE_CODE (bytes
) == INTEGER_CST
325 && tree_int_cst_lt (var_size
, bytes
))
326 bytes
= size_zero_node
;
328 bytes
= size_binop (MINUS_EXPR
, var_size
, bytes
);
332 && TREE_CODE (pt_var
) == INDIRECT_REF
333 && bytes
!= error_mark_node
)
335 tree bytes2
= compute_object_offset (TREE_OPERAND (ptr
, 0), pt_var
);
336 if (bytes2
!= error_mark_node
)
338 if (TREE_CODE (bytes2
) == INTEGER_CST
339 && tree_int_cst_lt (pt_var_size
, bytes2
))
340 bytes2
= size_zero_node
;
342 bytes2
= size_binop (MINUS_EXPR
, pt_var_size
, bytes2
);
343 bytes
= size_binop (MIN_EXPR
, bytes
, bytes2
);
347 else if (!pt_var_size
)
348 return unknown
[object_size_type
];
352 if (host_integerp (bytes
, 1))
353 return tree_low_cst (bytes
, 1);
355 return unknown
[object_size_type
];
359 /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
360 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
361 argument from __builtin_object_size. If unknown, return
362 unknown[object_size_type]. */
364 static unsigned HOST_WIDE_INT
365 alloc_object_size (const_gimple call
, int object_size_type
)
367 tree callee
, bytes
= NULL_TREE
;
369 int arg1
= -1, arg2
= -1;
371 gcc_assert (is_gimple_call (call
));
373 callee
= gimple_call_fndecl (call
);
375 return unknown
[object_size_type
];
377 alloc_size
= lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee
)));
378 if (alloc_size
&& TREE_VALUE (alloc_size
))
380 tree p
= TREE_VALUE (alloc_size
);
382 arg1
= TREE_INT_CST_LOW (TREE_VALUE (p
))-1;
384 arg2
= TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p
)))-1;
387 if (DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
388 switch (DECL_FUNCTION_CODE (callee
))
390 case BUILT_IN_CALLOC
:
393 case BUILT_IN_MALLOC
:
394 case BUILT_IN_ALLOCA
:
400 if (arg1
< 0 || arg1
>= (int)gimple_call_num_args (call
)
401 || TREE_CODE (gimple_call_arg (call
, arg1
)) != INTEGER_CST
403 && (arg2
>= (int)gimple_call_num_args (call
)
404 || TREE_CODE (gimple_call_arg (call
, arg2
)) != INTEGER_CST
)))
405 return unknown
[object_size_type
];
408 bytes
= size_binop (MULT_EXPR
,
409 fold_convert (sizetype
, gimple_call_arg (call
, arg1
)),
410 fold_convert (sizetype
, gimple_call_arg (call
, arg2
)));
412 bytes
= fold_convert (sizetype
, gimple_call_arg (call
, arg1
));
414 if (bytes
&& host_integerp (bytes
, 1))
415 return tree_low_cst (bytes
, 1);
417 return unknown
[object_size_type
];
421 /* If object size is propagated from one of function's arguments directly
422 to its return value, return that argument for GIMPLE_CALL statement CALL.
423 Otherwise return NULL. */
426 pass_through_call (const_gimple call
)
428 tree callee
= gimple_call_fndecl (call
);
431 && DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
432 switch (DECL_FUNCTION_CODE (callee
))
434 case BUILT_IN_MEMCPY
:
435 case BUILT_IN_MEMMOVE
:
436 case BUILT_IN_MEMSET
:
437 case BUILT_IN_STRCPY
:
438 case BUILT_IN_STRNCPY
:
439 case BUILT_IN_STRCAT
:
440 case BUILT_IN_STRNCAT
:
441 case BUILT_IN_MEMCPY_CHK
:
442 case BUILT_IN_MEMMOVE_CHK
:
443 case BUILT_IN_MEMSET_CHK
:
444 case BUILT_IN_STRCPY_CHK
:
445 case BUILT_IN_STRNCPY_CHK
:
446 case BUILT_IN_STRCAT_CHK
:
447 case BUILT_IN_STRNCAT_CHK
:
448 if (gimple_call_num_args (call
) >= 1)
449 return gimple_call_arg (call
, 0);
459 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
460 second argument from __builtin_object_size. */
462 unsigned HOST_WIDE_INT
463 compute_builtin_object_size (tree ptr
, int object_size_type
)
465 gcc_assert (object_size_type
>= 0 && object_size_type
<= 3);
468 init_offset_limit ();
470 if (TREE_CODE (ptr
) == ADDR_EXPR
)
471 return addr_object_size (NULL
, ptr
, object_size_type
);
473 if (TREE_CODE (ptr
) == SSA_NAME
474 && POINTER_TYPE_P (TREE_TYPE (ptr
))
475 && object_sizes
[object_size_type
] != NULL
)
477 if (!bitmap_bit_p (computed
[object_size_type
], SSA_NAME_VERSION (ptr
)))
479 struct object_size_info osi
;
485 fprintf (dump_file
, "Computing %s %sobject size for ",
486 (object_size_type
& 2) ? "minimum" : "maximum",
487 (object_size_type
& 1) ? "sub" : "");
488 print_generic_expr (dump_file
, ptr
, dump_flags
);
489 fprintf (dump_file
, ":\n");
492 osi
.visited
= BITMAP_ALLOC (NULL
);
493 osi
.reexamine
= BITMAP_ALLOC (NULL
);
494 osi
.object_size_type
= object_size_type
;
499 /* First pass: walk UD chains, compute object sizes that
500 can be computed. osi.reexamine bitmap at the end will
501 contain what variables were found in dependency cycles
502 and therefore need to be reexamined. */
505 collect_object_sizes_for (&osi
, ptr
);
507 /* Second pass: keep recomputing object sizes of variables
508 that need reexamination, until no object sizes are
509 increased or all object sizes are computed. */
510 if (! bitmap_empty_p (osi
.reexamine
))
512 bitmap reexamine
= BITMAP_ALLOC (NULL
);
514 /* If looking for minimum instead of maximum object size,
515 detect cases where a pointer is increased in a loop.
516 Although even without this detection pass 2 would eventually
517 terminate, it could take a long time. If a pointer is
518 increasing this way, we need to assume 0 object size.
519 E.g. p = &buf[0]; while (cond) p = p + 4; */
520 if (object_size_type
& 2)
522 osi
.depths
= XCNEWVEC (unsigned int, num_ssa_names
);
523 osi
.stack
= XNEWVEC (unsigned int, num_ssa_names
);
526 /* collect_object_sizes_for is changing
527 osi.reexamine bitmap, so iterate over a copy. */
528 bitmap_copy (reexamine
, osi
.reexamine
);
529 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
530 if (bitmap_bit_p (osi
.reexamine
, i
))
531 check_for_plus_in_loops (&osi
, ssa_name (i
));
544 /* collect_object_sizes_for is changing
545 osi.reexamine bitmap, so iterate over a copy. */
546 bitmap_copy (reexamine
, osi
.reexamine
);
547 EXECUTE_IF_SET_IN_BITMAP (reexamine
, 0, i
, bi
)
548 if (bitmap_bit_p (osi
.reexamine
, i
))
550 collect_object_sizes_for (&osi
, ssa_name (i
));
551 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
553 fprintf (dump_file
, "Reexamining ");
554 print_generic_expr (dump_file
, ssa_name (i
),
556 fprintf (dump_file
, "\n");
562 BITMAP_FREE (reexamine
);
564 EXECUTE_IF_SET_IN_BITMAP (osi
.reexamine
, 0, i
, bi
)
565 bitmap_set_bit (computed
[object_size_type
], i
);
567 /* Debugging dumps. */
570 EXECUTE_IF_SET_IN_BITMAP (osi
.visited
, 0, i
, bi
)
571 if (object_sizes
[object_size_type
][i
]
572 != unknown
[object_size_type
])
574 print_generic_expr (dump_file
, ssa_name (i
),
577 ": %s %sobject size "
578 HOST_WIDE_INT_PRINT_UNSIGNED
"\n",
579 (object_size_type
& 2) ? "minimum" : "maximum",
580 (object_size_type
& 1) ? "sub" : "",
581 object_sizes
[object_size_type
][i
]);
585 BITMAP_FREE (osi
.reexamine
);
586 BITMAP_FREE (osi
.visited
);
589 return object_sizes
[object_size_type
][SSA_NAME_VERSION (ptr
)];
592 return unknown
[object_size_type
];
595 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */
598 expr_object_size (struct object_size_info
*osi
, tree ptr
, tree value
)
600 int object_size_type
= osi
->object_size_type
;
601 unsigned int varno
= SSA_NAME_VERSION (ptr
);
602 unsigned HOST_WIDE_INT bytes
;
604 gcc_assert (object_sizes
[object_size_type
][varno
]
605 != unknown
[object_size_type
]);
606 gcc_assert (osi
->pass
== 0);
608 if (TREE_CODE (value
) == WITH_SIZE_EXPR
)
609 value
= TREE_OPERAND (value
, 0);
611 /* Pointer variables should have been handled by merge_object_sizes. */
612 gcc_assert (TREE_CODE (value
) != SSA_NAME
613 || !POINTER_TYPE_P (TREE_TYPE (value
)));
615 if (TREE_CODE (value
) == ADDR_EXPR
)
616 bytes
= addr_object_size (osi
, value
, object_size_type
);
618 bytes
= unknown
[object_size_type
];
620 if ((object_size_type
& 2) == 0)
622 if (object_sizes
[object_size_type
][varno
] < bytes
)
623 object_sizes
[object_size_type
][varno
] = bytes
;
627 if (object_sizes
[object_size_type
][varno
] > bytes
)
628 object_sizes
[object_size_type
][varno
] = bytes
;
633 /* Compute object_sizes for PTR, defined to the result of a call. */
636 call_object_size (struct object_size_info
*osi
, tree ptr
, gimple call
)
638 int object_size_type
= osi
->object_size_type
;
639 unsigned int varno
= SSA_NAME_VERSION (ptr
);
640 unsigned HOST_WIDE_INT bytes
;
642 gcc_assert (is_gimple_call (call
));
644 gcc_assert (object_sizes
[object_size_type
][varno
]
645 != unknown
[object_size_type
]);
646 gcc_assert (osi
->pass
== 0);
648 bytes
= alloc_object_size (call
, object_size_type
);
650 if ((object_size_type
& 2) == 0)
652 if (object_sizes
[object_size_type
][varno
] < bytes
)
653 object_sizes
[object_size_type
][varno
] = bytes
;
657 if (object_sizes
[object_size_type
][varno
] > bytes
)
658 object_sizes
[object_size_type
][varno
] = bytes
;
663 /* Compute object_sizes for PTR, defined to an unknown value. */
666 unknown_object_size (struct object_size_info
*osi
, tree ptr
)
668 int object_size_type
= osi
->object_size_type
;
669 unsigned int varno
= SSA_NAME_VERSION (ptr
);
670 unsigned HOST_WIDE_INT bytes
;
672 gcc_assert (object_sizes
[object_size_type
][varno
]
673 != unknown
[object_size_type
]);
674 gcc_assert (osi
->pass
== 0);
676 bytes
= unknown
[object_size_type
];
678 if ((object_size_type
& 2) == 0)
680 if (object_sizes
[object_size_type
][varno
] < bytes
)
681 object_sizes
[object_size_type
][varno
] = bytes
;
685 if (object_sizes
[object_size_type
][varno
] > bytes
)
686 object_sizes
[object_size_type
][varno
] = bytes
;
691 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
692 the object size might need reexamination later. */
695 merge_object_sizes (struct object_size_info
*osi
, tree dest
, tree orig
,
696 unsigned HOST_WIDE_INT offset
)
698 int object_size_type
= osi
->object_size_type
;
699 unsigned int varno
= SSA_NAME_VERSION (dest
);
700 unsigned HOST_WIDE_INT orig_bytes
;
702 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
704 if (offset
>= offset_limit
)
706 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
711 collect_object_sizes_for (osi
, orig
);
713 orig_bytes
= object_sizes
[object_size_type
][SSA_NAME_VERSION (orig
)];
714 if (orig_bytes
!= unknown
[object_size_type
])
715 orig_bytes
= (offset
> orig_bytes
)
716 ? (unsigned HOST_WIDE_INT
) 0 : orig_bytes
- offset
;
718 if ((object_size_type
& 2) == 0)
720 if (object_sizes
[object_size_type
][varno
] < orig_bytes
)
722 object_sizes
[object_size_type
][varno
] = orig_bytes
;
728 if (object_sizes
[object_size_type
][varno
] > orig_bytes
)
730 object_sizes
[object_size_type
][varno
] = orig_bytes
;
734 return bitmap_bit_p (osi
->reexamine
, SSA_NAME_VERSION (orig
));
738 /* Compute object_sizes for VAR, defined to the result of an assignment
739 with operator POINTER_PLUS_EXPR. Return true if the object size might
740 need reexamination later. */
743 plus_stmt_object_size (struct object_size_info
*osi
, tree var
, gimple stmt
)
745 int object_size_type
= osi
->object_size_type
;
746 unsigned int varno
= SSA_NAME_VERSION (var
);
747 unsigned HOST_WIDE_INT bytes
;
750 gcc_assert (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
);
752 op0
= gimple_assign_rhs1 (stmt
);
753 op1
= gimple_assign_rhs2 (stmt
);
755 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
758 /* Handle PTR + OFFSET here. */
759 if (TREE_CODE (op1
) == INTEGER_CST
760 && (TREE_CODE (op0
) == SSA_NAME
761 || TREE_CODE (op0
) == ADDR_EXPR
))
763 if (! host_integerp (op1
, 1))
764 bytes
= unknown
[object_size_type
];
765 else if (TREE_CODE (op0
) == SSA_NAME
)
766 return merge_object_sizes (osi
, var
, op0
, tree_low_cst (op1
, 1));
769 unsigned HOST_WIDE_INT off
= tree_low_cst (op1
, 1);
771 /* op0 will be ADDR_EXPR here. */
772 bytes
= addr_object_size (osi
, op0
, object_size_type
);
773 if (bytes
== unknown
[object_size_type
])
775 else if (off
> offset_limit
)
776 bytes
= unknown
[object_size_type
];
777 else if (off
> bytes
)
784 bytes
= unknown
[object_size_type
];
786 if ((object_size_type
& 2) == 0)
788 if (object_sizes
[object_size_type
][varno
] < bytes
)
789 object_sizes
[object_size_type
][varno
] = bytes
;
793 if (object_sizes
[object_size_type
][varno
] > bytes
)
794 object_sizes
[object_size_type
][varno
] = bytes
;
800 /* Compute object_sizes for VAR, defined to VALUE, which is
801 a COND_EXPR. Return true if the object size might need reexamination
805 cond_expr_object_size (struct object_size_info
*osi
, tree var
, tree value
)
808 int object_size_type
= osi
->object_size_type
;
809 unsigned int varno
= SSA_NAME_VERSION (var
);
810 bool reexamine
= false;
812 gcc_assert (TREE_CODE (value
) == COND_EXPR
);
814 if (object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
817 then_
= COND_EXPR_THEN (value
);
818 else_
= COND_EXPR_ELSE (value
);
820 if (TREE_CODE (then_
) == SSA_NAME
)
821 reexamine
|= merge_object_sizes (osi
, var
, then_
, 0);
823 expr_object_size (osi
, var
, then_
);
825 if (TREE_CODE (else_
) == SSA_NAME
)
826 reexamine
|= merge_object_sizes (osi
, var
, else_
, 0);
828 expr_object_size (osi
, var
, else_
);
833 /* Compute object sizes for VAR.
834 For ADDR_EXPR an object size is the number of remaining bytes
835 to the end of the object (where what is considered an object depends on
836 OSI->object_size_type).
837 For allocation GIMPLE_CALL like malloc or calloc object size is the size
839 For POINTER_PLUS_EXPR where second operand is a constant integer,
840 object size is object size of the first operand minus the constant.
841 If the constant is bigger than the number of remaining bytes until the
842 end of the object, object size is 0, but if it is instead a pointer
843 subtraction, object size is unknown[object_size_type].
844 To differentiate addition from subtraction, ADDR_EXPR returns
845 unknown[object_size_type] for all objects bigger than half of the address
846 space, and constants less than half of the address space are considered
847 addition, while bigger constants subtraction.
848 For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
849 object size is object size of that argument.
850 Otherwise, object size is the maximum of object sizes of variables
851 that it might be set to. */
854 collect_object_sizes_for (struct object_size_info
*osi
, tree var
)
856 int object_size_type
= osi
->object_size_type
;
857 unsigned int varno
= SSA_NAME_VERSION (var
);
861 if (bitmap_bit_p (computed
[object_size_type
], varno
))
866 if (! bitmap_bit_p (osi
->visited
, varno
))
868 bitmap_set_bit (osi
->visited
, varno
);
869 object_sizes
[object_size_type
][varno
]
870 = (object_size_type
& 2) ? -1 : 0;
874 /* Found a dependency loop. Mark the variable for later
876 bitmap_set_bit (osi
->reexamine
, varno
);
877 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
879 fprintf (dump_file
, "Found a dependency loop at ");
880 print_generic_expr (dump_file
, var
, dump_flags
);
881 fprintf (dump_file
, "\n");
887 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
889 fprintf (dump_file
, "Visiting use-def links for ");
890 print_generic_expr (dump_file
, var
, dump_flags
);
891 fprintf (dump_file
, "\n");
894 stmt
= SSA_NAME_DEF_STMT (var
);
897 switch (gimple_code (stmt
))
901 if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
902 reexamine
= plus_stmt_object_size (osi
, var
, stmt
);
903 else if (gimple_assign_single_p (stmt
)
904 || gimple_assign_unary_nop_p (stmt
))
906 tree rhs
= gimple_assign_rhs1 (stmt
);
908 if (TREE_CODE (rhs
) == SSA_NAME
909 && POINTER_TYPE_P (TREE_TYPE (rhs
)))
910 reexamine
= merge_object_sizes (osi
, var
, rhs
, 0);
911 else if (TREE_CODE (rhs
) == COND_EXPR
)
912 reexamine
= cond_expr_object_size (osi
, var
, rhs
);
914 expr_object_size (osi
, var
, rhs
);
917 unknown_object_size (osi
, var
);
923 tree arg
= pass_through_call (stmt
);
926 if (TREE_CODE (arg
) == SSA_NAME
927 && POINTER_TYPE_P (TREE_TYPE (arg
)))
928 reexamine
= merge_object_sizes (osi
, var
, arg
, 0);
929 else if (TREE_CODE (arg
) == COND_EXPR
)
930 reexamine
= cond_expr_object_size (osi
, var
, arg
);
932 expr_object_size (osi
, var
, arg
);
935 call_object_size (osi
, var
, stmt
);
940 /* Pointers defined by __asm__ statements can point anywhere. */
941 object_sizes
[object_size_type
][varno
] = unknown
[object_size_type
];
946 tree decl
= SSA_NAME_VAR (var
);
948 if (TREE_CODE (decl
) != PARM_DECL
&& DECL_INITIAL (decl
))
949 expr_object_size (osi
, var
, DECL_INITIAL (decl
));
951 expr_object_size (osi
, var
, decl
);
959 for (i
= 0; i
< gimple_phi_num_args (stmt
); i
++)
961 tree rhs
= gimple_phi_arg (stmt
, i
)->def
;
963 if (object_sizes
[object_size_type
][varno
]
964 == unknown
[object_size_type
])
967 if (TREE_CODE (rhs
) == SSA_NAME
)
968 reexamine
|= merge_object_sizes (osi
, var
, rhs
, 0);
969 else if (osi
->pass
== 0)
970 expr_object_size (osi
, var
, rhs
);
980 || object_sizes
[object_size_type
][varno
] == unknown
[object_size_type
])
982 bitmap_set_bit (computed
[object_size_type
], varno
);
983 bitmap_clear_bit (osi
->reexamine
, varno
);
987 bitmap_set_bit (osi
->reexamine
, varno
);
988 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
990 fprintf (dump_file
, "Need to reexamine ");
991 print_generic_expr (dump_file
, var
, dump_flags
);
992 fprintf (dump_file
, "\n");
998 /* Helper function for check_for_plus_in_loops. Called recursively
1002 check_for_plus_in_loops_1 (struct object_size_info
*osi
, tree var
,
1005 gimple stmt
= SSA_NAME_DEF_STMT (var
);
1006 unsigned int varno
= SSA_NAME_VERSION (var
);
1008 if (osi
->depths
[varno
])
1010 if (osi
->depths
[varno
] != depth
)
1014 /* Found a loop involving pointer addition. */
1015 for (sp
= osi
->tos
; sp
> osi
->stack
; )
1018 bitmap_clear_bit (osi
->reexamine
, *sp
);
1019 bitmap_set_bit (computed
[osi
->object_size_type
], *sp
);
1020 object_sizes
[osi
->object_size_type
][*sp
] = 0;
1027 else if (! bitmap_bit_p (osi
->reexamine
, varno
))
1030 osi
->depths
[varno
] = depth
;
1031 *osi
->tos
++ = varno
;
1033 switch (gimple_code (stmt
))
1038 if ((gimple_assign_single_p (stmt
)
1039 || gimple_assign_unary_nop_p (stmt
))
1040 && TREE_CODE (gimple_assign_rhs1 (stmt
)) == SSA_NAME
)
1042 tree rhs
= gimple_assign_rhs1 (stmt
);
1044 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
1046 else if (gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
1048 tree basevar
= gimple_assign_rhs1 (stmt
);
1049 tree cst
= gimple_assign_rhs2 (stmt
);
1051 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
1053 check_for_plus_in_loops_1 (osi
, basevar
,
1054 depth
+ !integer_zerop (cst
));
1063 tree arg
= pass_through_call (stmt
);
1066 if (TREE_CODE (arg
) == SSA_NAME
)
1067 check_for_plus_in_loops_1 (osi
, arg
, depth
);
1078 for (i
= 0; i
< gimple_phi_num_args (stmt
); i
++)
1080 tree rhs
= gimple_phi_arg (stmt
, i
)->def
;
1082 if (TREE_CODE (rhs
) == SSA_NAME
)
1083 check_for_plus_in_loops_1 (osi
, rhs
, depth
);
1092 osi
->depths
[varno
] = 0;
1097 /* Check if some pointer we are computing object size of is being increased
1098 within a loop. If yes, assume all the SSA variables participating in
1099 that loop have minimum object sizes 0. */
1102 check_for_plus_in_loops (struct object_size_info
*osi
, tree var
)
1104 gimple stmt
= SSA_NAME_DEF_STMT (var
);
1106 /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
1107 and looked for a POINTER_PLUS_EXPR in the pass-through
1108 argument, if any. In GIMPLE, however, such an expression
1109 is not a valid call operand. */
1111 if (is_gimple_assign (stmt
)
1112 && gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
1114 tree basevar
= gimple_assign_rhs1 (stmt
);
1115 tree cst
= gimple_assign_rhs2 (stmt
);
1117 gcc_assert (TREE_CODE (cst
) == INTEGER_CST
);
1119 if (integer_zerop (cst
))
1122 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 1;
1123 *osi
->tos
++ = SSA_NAME_VERSION (basevar
);
1124 check_for_plus_in_loops_1 (osi
, var
, 2);
1125 osi
->depths
[SSA_NAME_VERSION (basevar
)] = 0;
1131 /* Initialize data structures for the object size computation. */
1134 init_object_sizes (void)
1136 int object_size_type
;
1138 if (object_sizes
[0])
1141 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
1143 object_sizes
[object_size_type
] = XNEWVEC (unsigned HOST_WIDE_INT
, num_ssa_names
);
1144 computed
[object_size_type
] = BITMAP_ALLOC (NULL
);
1147 init_offset_limit ();
1151 /* Destroy data structures after the object size computation. */
1154 fini_object_sizes (void)
1156 int object_size_type
;
1158 for (object_size_type
= 0; object_size_type
<= 3; object_size_type
++)
1160 free (object_sizes
[object_size_type
]);
1161 BITMAP_FREE (computed
[object_size_type
]);
1162 object_sizes
[object_size_type
] = NULL
;
1167 /* Simple pass to optimize all __builtin_object_size () builtins. */
1170 compute_object_sizes (void)
1175 gimple_stmt_iterator i
;
1176 for (i
= gsi_start_bb (bb
); !gsi_end_p (i
); gsi_next (&i
))
1178 tree callee
, result
;
1179 gimple call
= gsi_stmt (i
);
1181 if (gimple_code (call
) != GIMPLE_CALL
)
1184 callee
= gimple_call_fndecl (call
);
1186 || DECL_BUILT_IN_CLASS (callee
) != BUILT_IN_NORMAL
1187 || DECL_FUNCTION_CODE (callee
) != BUILT_IN_OBJECT_SIZE
)
1190 init_object_sizes ();
1191 result
= fold_call_stmt (call
, false);
1194 if (gimple_call_num_args (call
) == 2
1195 && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call
, 0))))
1197 tree ost
= gimple_call_arg (call
, 1);
1199 if (host_integerp (ost
, 1))
1201 unsigned HOST_WIDE_INT object_size_type
1202 = tree_low_cst (ost
, 1);
1204 if (object_size_type
< 2)
1205 result
= fold_convert (size_type_node
,
1206 integer_minus_one_node
);
1207 else if (object_size_type
< 4)
1208 result
= fold_convert (size_type_node
,
1217 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1219 fprintf (dump_file
, "Simplified\n ");
1220 print_gimple_stmt (dump_file
, call
, 0, dump_flags
);
1223 if (!update_call_from_tree (&i
, result
))
1226 /* NOTE: In the pre-tuples code, we called update_stmt here. This is
1227 now handled by gsi_replace, called from update_call_from_tree. */
1229 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1231 fprintf (dump_file
, "to\n ");
1232 print_gimple_stmt (dump_file
, call
, 0, dump_flags
);
1233 fprintf (dump_file
, "\n");
1238 fini_object_sizes ();
1242 struct gimple_opt_pass pass_object_sizes
=
1248 compute_object_sizes
, /* execute */
1251 0, /* static_pass_number */
1252 TV_NONE
, /* tv_id */
1253 PROP_cfg
| PROP_ssa
, /* properties_required */
1254 0, /* properties_provided */
1255 0, /* properties_destroyed */
1256 0, /* todo_flags_start */
1257 TODO_dump_func
| TODO_verify_ssa
/* todo_flags_finish */