* jump.c: Remove prototypes for delete_computation and
[official-gcc.git] / gcc / tree-object-size.c
bloba93464b22fa73f0cc4fbc9bc6542ddfa466484ad
1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to
19 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "diagnostic.h"
28 #include "tree-flow.h"
29 #include "tree-pass.h"
30 #include "tree-ssa-propagate.h"
32 struct object_size_info
34 int object_size_type;
35 bitmap visited, reexamine;
36 int pass;
37 bool changed;
38 unsigned int *depths;
39 unsigned int *stack, *tos;
42 static unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 };
44 static tree compute_object_offset (tree, tree);
45 static unsigned HOST_WIDE_INT addr_object_size (tree, int);
46 static unsigned HOST_WIDE_INT alloc_object_size (tree, int);
47 static tree pass_through_call (tree);
48 static void collect_object_sizes_for (struct object_size_info *, tree);
49 static void expr_object_size (struct object_size_info *, tree, tree);
50 static bool merge_object_sizes (struct object_size_info *, tree, tree,
51 unsigned HOST_WIDE_INT);
52 static bool plus_expr_object_size (struct object_size_info *, tree, tree);
53 static bool cond_expr_object_size (struct object_size_info *, tree, tree);
54 static unsigned int compute_object_sizes (void);
55 static void init_offset_limit (void);
56 static void check_for_plus_in_loops (struct object_size_info *, tree);
57 static void check_for_plus_in_loops_1 (struct object_size_info *, tree,
58 unsigned int);
60 /* object_sizes[0] is upper bound for number of bytes till the end of
61 the object.
62 object_sizes[1] is upper bound for number of bytes till the end of
63 the subobject (innermost array or field with address taken).
64 object_sizes[2] is lower bound for number of bytes till the end of
65 the object and object_sizes[3] lower bound for subobject. */
66 static unsigned HOST_WIDE_INT *object_sizes[4];
68 /* Bitmaps what object sizes have been computed already. */
69 static bitmap computed[4];
71 /* Maximum value of offset we consider to be addition. */
72 static unsigned HOST_WIDE_INT offset_limit;
75 /* Initialize OFFSET_LIMIT variable. */
76 static void
77 init_offset_limit (void)
79 if (host_integerp (TYPE_MAX_VALUE (sizetype), 1))
80 offset_limit = tree_low_cst (TYPE_MAX_VALUE (sizetype), 1);
81 else
82 offset_limit = -1;
83 offset_limit /= 2;
87 /* Compute offset of EXPR within VAR. Return error_mark_node
88 if unknown. */
90 static tree
91 compute_object_offset (tree expr, tree var)
93 enum tree_code code = PLUS_EXPR;
94 tree base, off, t;
96 if (expr == var)
97 return size_zero_node;
99 switch (TREE_CODE (expr))
101 case COMPONENT_REF:
102 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
103 if (base == error_mark_node)
104 return base;
106 t = TREE_OPERAND (expr, 1);
107 off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
108 size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
109 / BITS_PER_UNIT));
110 break;
112 case REALPART_EXPR:
113 case NOP_EXPR:
114 case CONVERT_EXPR:
115 case VIEW_CONVERT_EXPR:
116 case NON_LVALUE_EXPR:
117 return compute_object_offset (TREE_OPERAND (expr, 0), var);
119 case IMAGPART_EXPR:
120 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
121 if (base == error_mark_node)
122 return base;
124 off = TYPE_SIZE_UNIT (TREE_TYPE (expr));
125 break;
127 case ARRAY_REF:
128 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
129 if (base == error_mark_node)
130 return base;
132 t = TREE_OPERAND (expr, 1);
133 if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
135 code = MINUS_EXPR;
136 t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
138 t = fold_convert (sizetype, t);
139 off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
140 break;
142 default:
143 return error_mark_node;
146 return size_binop (code, base, off);
150 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
151 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
152 If unknown, return unknown[object_size_type]. */
154 static unsigned HOST_WIDE_INT
155 addr_object_size (tree ptr, int object_size_type)
157 tree pt_var;
159 gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
161 pt_var = TREE_OPERAND (ptr, 0);
162 if (REFERENCE_CLASS_P (pt_var))
163 pt_var = get_base_address (pt_var);
165 if (pt_var
166 && (SSA_VAR_P (pt_var) || TREE_CODE (pt_var) == STRING_CST)
167 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
168 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
169 && (unsigned HOST_WIDE_INT)
170 tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1) < offset_limit)
172 tree bytes;
174 if (pt_var != TREE_OPERAND (ptr, 0))
176 tree var;
178 if (object_size_type & 1)
180 var = TREE_OPERAND (ptr, 0);
182 while (var != pt_var
183 && TREE_CODE (var) != BIT_FIELD_REF
184 && TREE_CODE (var) != COMPONENT_REF
185 && TREE_CODE (var) != ARRAY_REF
186 && TREE_CODE (var) != ARRAY_RANGE_REF
187 && TREE_CODE (var) != REALPART_EXPR
188 && TREE_CODE (var) != IMAGPART_EXPR)
189 var = TREE_OPERAND (var, 0);
190 if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
191 var = TREE_OPERAND (var, 0);
192 if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
193 || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
194 || tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)),
195 TYPE_SIZE_UNIT (TREE_TYPE (var))))
196 var = pt_var;
198 else
199 var = pt_var;
201 bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
202 if (bytes != error_mark_node)
204 if (TREE_CODE (bytes) == INTEGER_CST
205 && tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes))
206 bytes = size_zero_node;
207 else
208 bytes = size_binop (MINUS_EXPR,
209 TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes);
212 else
213 bytes = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
215 if (host_integerp (bytes, 1))
216 return tree_low_cst (bytes, 1);
219 return unknown[object_size_type];
223 /* Compute __builtin_object_size for CALL, which is a CALL_EXPR.
224 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
225 argument from __builtin_object_size. If unknown, return
226 unknown[object_size_type]. */
228 static unsigned HOST_WIDE_INT
229 alloc_object_size (tree call, int object_size_type)
231 tree callee, arglist, a, bytes = NULL_TREE;
232 unsigned int arg_mask = 0;
234 gcc_assert (TREE_CODE (call) == CALL_EXPR);
236 callee = get_callee_fndecl (call);
237 arglist = TREE_OPERAND (call, 1);
238 if (callee
239 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
240 switch (DECL_FUNCTION_CODE (callee))
242 case BUILT_IN_MALLOC:
243 case BUILT_IN_ALLOCA:
244 arg_mask = 1;
245 break;
247 case BUILT_IN_REALLOC:
248 arg_mask = 2;
249 break;
251 case BUILT_IN_CALLOC:
252 arg_mask = 3;
253 break;
254 default:
255 break;
258 for (a = arglist; arg_mask && a; arg_mask >>= 1, a = TREE_CHAIN (a))
259 if (arg_mask & 1)
261 tree arg = TREE_VALUE (a);
263 if (TREE_CODE (arg) != INTEGER_CST)
264 break;
266 if (! bytes)
267 bytes = fold_convert (sizetype, arg);
268 else
269 bytes = size_binop (MULT_EXPR, bytes,
270 fold_convert (sizetype, arg));
273 if (! arg_mask && bytes && host_integerp (bytes, 1))
274 return tree_low_cst (bytes, 1);
276 return unknown[object_size_type];
280 /* If object size is propagated from one of function's arguments directly
281 to its return value, return that argument for CALL_EXPR CALL.
282 Otherwise return NULL. */
284 static tree
285 pass_through_call (tree call)
287 tree callee = get_callee_fndecl (call);
288 tree arglist = TREE_OPERAND (call, 1);
290 if (callee
291 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
292 switch (DECL_FUNCTION_CODE (callee))
294 case BUILT_IN_MEMCPY:
295 case BUILT_IN_MEMMOVE:
296 case BUILT_IN_MEMSET:
297 case BUILT_IN_STRCPY:
298 case BUILT_IN_STRNCPY:
299 case BUILT_IN_STRCAT:
300 case BUILT_IN_STRNCAT:
301 case BUILT_IN_MEMCPY_CHK:
302 case BUILT_IN_MEMMOVE_CHK:
303 case BUILT_IN_MEMSET_CHK:
304 case BUILT_IN_STRCPY_CHK:
305 case BUILT_IN_STRNCPY_CHK:
306 case BUILT_IN_STRCAT_CHK:
307 case BUILT_IN_STRNCAT_CHK:
308 if (arglist)
309 return TREE_VALUE (arglist);
310 break;
311 default:
312 break;
315 return NULL_TREE;
319 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
320 second argument from __builtin_object_size. */
322 unsigned HOST_WIDE_INT
323 compute_builtin_object_size (tree ptr, int object_size_type)
325 gcc_assert (object_size_type >= 0 && object_size_type <= 3);
327 if (! offset_limit)
328 init_offset_limit ();
330 if (TREE_CODE (ptr) == ADDR_EXPR)
331 return addr_object_size (ptr, object_size_type);
332 else if (TREE_CODE (ptr) == CALL_EXPR)
334 tree arg = pass_through_call (ptr);
336 if (arg)
337 return compute_builtin_object_size (arg, object_size_type);
338 else
339 return alloc_object_size (ptr, object_size_type);
341 else if (TREE_CODE (ptr) == SSA_NAME
342 && POINTER_TYPE_P (TREE_TYPE (ptr))
343 && object_sizes[object_size_type] != NULL)
345 if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
347 struct object_size_info osi;
348 bitmap_iterator bi;
349 unsigned int i;
351 if (dump_file)
353 fprintf (dump_file, "Computing %s %sobject size for ",
354 (object_size_type & 2) ? "minimum" : "maximum",
355 (object_size_type & 1) ? "sub" : "");
356 print_generic_expr (dump_file, ptr, dump_flags);
357 fprintf (dump_file, ":\n");
360 osi.visited = BITMAP_ALLOC (NULL);
361 osi.reexamine = BITMAP_ALLOC (NULL);
362 osi.object_size_type = object_size_type;
363 osi.depths = NULL;
364 osi.stack = NULL;
365 osi.tos = NULL;
367 /* First pass: walk UD chains, compute object sizes that
368 can be computed. osi.reexamine bitmap at the end will
369 contain what variables were found in dependency cycles
370 and therefore need to be reexamined. */
371 osi.pass = 0;
372 osi.changed = false;
373 collect_object_sizes_for (&osi, ptr);
375 /* Second pass: keep recomputing object sizes of variables
376 that need reexamination, until no object sizes are
377 increased or all object sizes are computed. */
378 if (! bitmap_empty_p (osi.reexamine))
380 bitmap reexamine = BITMAP_ALLOC (NULL);
382 /* If looking for minimum instead of maximum object size,
383 detect cases where a pointer is increased in a loop.
384 Although even without this detection pass 2 would eventually
385 terminate, it could take a long time. If a pointer is
386 increasing this way, we need to assume 0 object size.
387 E.g. p = &buf[0]; while (cond) p = p + 4; */
388 if (object_size_type & 2)
390 osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
391 osi.stack = XNEWVEC (unsigned int, num_ssa_names);
392 osi.tos = osi.stack;
393 osi.pass = 1;
394 /* collect_object_sizes_for is changing
395 osi.reexamine bitmap, so iterate over a copy. */
396 bitmap_copy (reexamine, osi.reexamine);
397 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
398 if (bitmap_bit_p (osi.reexamine, i))
399 check_for_plus_in_loops (&osi, ssa_name (i));
401 free (osi.depths);
402 osi.depths = NULL;
403 free (osi.stack);
404 osi.stack = NULL;
405 osi.tos = NULL;
410 osi.pass = 2;
411 osi.changed = false;
412 /* collect_object_sizes_for is changing
413 osi.reexamine bitmap, so iterate over a copy. */
414 bitmap_copy (reexamine, osi.reexamine);
415 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
416 if (bitmap_bit_p (osi.reexamine, i))
418 collect_object_sizes_for (&osi, ssa_name (i));
419 if (dump_file && (dump_flags & TDF_DETAILS))
421 fprintf (dump_file, "Reexamining ");
422 print_generic_expr (dump_file, ssa_name (i),
423 dump_flags);
424 fprintf (dump_file, "\n");
428 while (osi.changed);
430 BITMAP_FREE (reexamine);
432 EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
433 bitmap_set_bit (computed[object_size_type], i);
435 /* Debugging dumps. */
436 if (dump_file)
438 EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
439 if (object_sizes[object_size_type][i]
440 != unknown[object_size_type])
442 print_generic_expr (dump_file, ssa_name (i),
443 dump_flags);
444 fprintf (dump_file,
445 ": %s %sobject size "
446 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
447 (object_size_type & 2) ? "minimum" : "maximum",
448 (object_size_type & 1) ? "sub" : "",
449 object_sizes[object_size_type][i]);
453 BITMAP_FREE (osi.reexamine);
454 BITMAP_FREE (osi.visited);
457 return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
460 return unknown[object_size_type];
464 /* Compute object_sizes for PTR, defined to VALUE, which is not
465 a SSA_NAME. */
467 static void
468 expr_object_size (struct object_size_info *osi, tree ptr, tree value)
470 int object_size_type = osi->object_size_type;
471 unsigned int varno = SSA_NAME_VERSION (ptr);
472 unsigned HOST_WIDE_INT bytes;
474 gcc_assert (object_sizes[object_size_type][varno]
475 != unknown[object_size_type]);
476 gcc_assert (osi->pass == 0);
478 if (TREE_CODE (value) == WITH_SIZE_EXPR)
479 value = TREE_OPERAND (value, 0);
481 /* Pointer variables should have been handled by merge_object_sizes. */
482 gcc_assert (TREE_CODE (value) != SSA_NAME
483 || !POINTER_TYPE_P (TREE_TYPE (value)));
485 if (TREE_CODE (value) == ADDR_EXPR)
486 bytes = addr_object_size (value, object_size_type);
487 else if (TREE_CODE (value) == CALL_EXPR)
488 bytes = alloc_object_size (value, object_size_type);
489 else
490 bytes = unknown[object_size_type];
492 if ((object_size_type & 2) == 0)
494 if (object_sizes[object_size_type][varno] < bytes)
495 object_sizes[object_size_type][varno] = bytes;
497 else
499 if (object_sizes[object_size_type][varno] > bytes)
500 object_sizes[object_size_type][varno] = bytes;
505 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
506 the object size might need reexamination later. */
508 static bool
509 merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
510 unsigned HOST_WIDE_INT offset)
512 int object_size_type = osi->object_size_type;
513 unsigned int varno = SSA_NAME_VERSION (dest);
514 unsigned HOST_WIDE_INT orig_bytes;
516 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
517 return false;
518 if (offset >= offset_limit)
520 object_sizes[object_size_type][varno] = unknown[object_size_type];
521 return false;
524 if (osi->pass == 0)
525 collect_object_sizes_for (osi, orig);
527 orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
528 if (orig_bytes != unknown[object_size_type])
529 orig_bytes = (offset > orig_bytes)
530 ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset;
532 if ((object_size_type & 2) == 0)
534 if (object_sizes[object_size_type][varno] < orig_bytes)
536 object_sizes[object_size_type][varno] = orig_bytes;
537 osi->changed = true;
540 else
542 if (object_sizes[object_size_type][varno] > orig_bytes)
544 object_sizes[object_size_type][varno] = orig_bytes;
545 osi->changed = true;
548 return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
552 /* Compute object_sizes for PTR, defined to VALUE, which is
553 a PLUS_EXPR. Return true if the object size might need reexamination
554 later. */
556 static bool
557 plus_expr_object_size (struct object_size_info *osi, tree var, tree value)
559 tree op0 = TREE_OPERAND (value, 0);
560 tree op1 = TREE_OPERAND (value, 1);
561 bool ptr1_p = POINTER_TYPE_P (TREE_TYPE (op0))
562 && TREE_CODE (op0) != INTEGER_CST;
563 bool ptr2_p = POINTER_TYPE_P (TREE_TYPE (op1))
564 && TREE_CODE (op1) != INTEGER_CST;
565 int object_size_type = osi->object_size_type;
566 unsigned int varno = SSA_NAME_VERSION (var);
567 unsigned HOST_WIDE_INT bytes;
569 gcc_assert (TREE_CODE (value) == PLUS_EXPR);
571 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
572 return false;
574 /* Swap operands if needed. */
575 if (ptr2_p && !ptr1_p)
577 tree tem = op0;
578 op0 = op1;
579 op1 = tem;
580 ptr1_p = true;
581 ptr2_p = false;
584 /* Handle PTR + OFFSET here. */
585 if (ptr1_p
586 && !ptr2_p
587 && TREE_CODE (op1) == INTEGER_CST
588 && (TREE_CODE (op0) == SSA_NAME
589 || TREE_CODE (op0) == ADDR_EXPR))
591 if (! host_integerp (op1, 1))
592 bytes = unknown[object_size_type];
593 else if (TREE_CODE (op0) == SSA_NAME)
594 return merge_object_sizes (osi, var, op0, tree_low_cst (op1, 1));
595 else
597 unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
599 bytes = compute_builtin_object_size (op0, object_size_type);
600 if (off > offset_limit)
601 bytes = unknown[object_size_type];
602 else if (off > bytes)
603 bytes = 0;
604 else
605 bytes -= off;
608 else
609 bytes = unknown[object_size_type];
611 if ((object_size_type & 2) == 0)
613 if (object_sizes[object_size_type][varno] < bytes)
614 object_sizes[object_size_type][varno] = bytes;
616 else
618 if (object_sizes[object_size_type][varno] > bytes)
619 object_sizes[object_size_type][varno] = bytes;
621 return false;
625 /* Compute object_sizes for PTR, defined to VALUE, which is
626 a COND_EXPR. Return true if the object size might need reexamination
627 later. */
629 static bool
630 cond_expr_object_size (struct object_size_info *osi, tree var, tree value)
632 tree then_, else_;
633 int object_size_type = osi->object_size_type;
634 unsigned int varno = SSA_NAME_VERSION (var);
635 bool reexamine = false;
637 gcc_assert (TREE_CODE (value) == COND_EXPR);
639 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
640 return false;
642 then_ = COND_EXPR_THEN (value);
643 else_ = COND_EXPR_ELSE (value);
645 if (TREE_CODE (then_) == SSA_NAME)
646 reexamine |= merge_object_sizes (osi, var, then_, 0);
647 else
648 expr_object_size (osi, var, then_);
650 if (TREE_CODE (else_) == SSA_NAME)
651 reexamine |= merge_object_sizes (osi, var, else_, 0);
652 else
653 expr_object_size (osi, var, else_);
655 return reexamine;
659 /* Compute object sizes for VAR.
660 For ADDR_EXPR an object size is the number of remaining bytes
661 to the end of the object (where what is considered an object depends on
662 OSI->object_size_type).
663 For allocation CALL_EXPR like malloc or calloc object size is the size
664 of the allocation.
665 For pointer PLUS_EXPR where second operand is a constant integer,
666 object size is object size of the first operand minus the constant.
667 If the constant is bigger than the number of remaining bytes until the
668 end of the object, object size is 0, but if it is instead a pointer
669 subtraction, object size is unknown[object_size_type].
670 To differentiate addition from subtraction, ADDR_EXPR returns
671 unknown[object_size_type] for all objects bigger than half of the address
672 space, and constants less than half of the address space are considered
673 addition, while bigger constants subtraction.
674 For a memcpy like CALL_EXPR that always returns one of its arguments, the
675 object size is object size of that argument.
676 Otherwise, object size is the maximum of object sizes of variables
677 that it might be set to. */
679 static void
680 collect_object_sizes_for (struct object_size_info *osi, tree var)
682 int object_size_type = osi->object_size_type;
683 unsigned int varno = SSA_NAME_VERSION (var);
684 tree stmt;
685 bool reexamine;
687 if (bitmap_bit_p (computed[object_size_type], varno))
688 return;
690 if (osi->pass == 0)
692 if (! bitmap_bit_p (osi->visited, varno))
694 bitmap_set_bit (osi->visited, varno);
695 object_sizes[object_size_type][varno]
696 = (object_size_type & 2) ? -1 : 0;
698 else
700 /* Found a dependency loop. Mark the variable for later
701 re-examination. */
702 bitmap_set_bit (osi->reexamine, varno);
703 if (dump_file && (dump_flags & TDF_DETAILS))
705 fprintf (dump_file, "Found a dependency loop at ");
706 print_generic_expr (dump_file, var, dump_flags);
707 fprintf (dump_file, "\n");
709 return;
713 if (dump_file && (dump_flags & TDF_DETAILS))
715 fprintf (dump_file, "Visiting use-def links for ");
716 print_generic_expr (dump_file, var, dump_flags);
717 fprintf (dump_file, "\n");
720 stmt = SSA_NAME_DEF_STMT (var);
721 reexamine = false;
723 switch (TREE_CODE (stmt))
725 case RETURN_EXPR:
726 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
727 stmt = TREE_OPERAND (stmt, 0);
728 /* FALLTHRU */
730 case GIMPLE_MODIFY_STMT:
732 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
733 STRIP_NOPS (rhs);
735 if (TREE_CODE (rhs) == CALL_EXPR)
737 arg = pass_through_call (rhs);
738 if (arg)
739 rhs = arg;
742 if (TREE_CODE (rhs) == SSA_NAME
743 && POINTER_TYPE_P (TREE_TYPE (rhs)))
744 reexamine = merge_object_sizes (osi, var, rhs, 0);
746 else if (TREE_CODE (rhs) == PLUS_EXPR)
747 reexamine = plus_expr_object_size (osi, var, rhs);
749 else if (TREE_CODE (rhs) == COND_EXPR)
750 reexamine = cond_expr_object_size (osi, var, rhs);
752 else
753 expr_object_size (osi, var, rhs);
754 break;
757 case ASM_EXPR:
758 /* Pointers defined by __asm__ statements can point anywhere. */
759 object_sizes[object_size_type][varno] = unknown[object_size_type];
760 break;
762 case NOP_EXPR:
764 tree decl = SSA_NAME_VAR (var);
766 gcc_assert (IS_EMPTY_STMT (stmt));
768 if (TREE_CODE (decl) != PARM_DECL && DECL_INITIAL (decl))
769 expr_object_size (osi, var, DECL_INITIAL (decl));
770 else
771 expr_object_size (osi, var, decl);
773 break;
775 case PHI_NODE:
777 int i;
779 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
781 tree rhs = PHI_ARG_DEF (stmt, i);
783 if (object_sizes[object_size_type][varno]
784 == unknown[object_size_type])
785 break;
787 if (TREE_CODE (rhs) == SSA_NAME)
788 reexamine |= merge_object_sizes (osi, var, rhs, 0);
789 else if (osi->pass == 0)
790 expr_object_size (osi, var, rhs);
792 break;
794 default:
795 gcc_unreachable ();
798 if (! reexamine
799 || object_sizes[object_size_type][varno] == unknown[object_size_type])
801 bitmap_set_bit (computed[object_size_type], varno);
802 bitmap_clear_bit (osi->reexamine, varno);
804 else
806 bitmap_set_bit (osi->reexamine, varno);
807 if (dump_file && (dump_flags & TDF_DETAILS))
809 fprintf (dump_file, "Need to reexamine ");
810 print_generic_expr (dump_file, var, dump_flags);
811 fprintf (dump_file, "\n");
817 /* Helper function for check_for_plus_in_loops. Called recursively
818 to detect loops. */
820 static void
821 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
822 unsigned int depth)
824 tree stmt = SSA_NAME_DEF_STMT (var);
825 unsigned int varno = SSA_NAME_VERSION (var);
827 if (osi->depths[varno])
829 if (osi->depths[varno] != depth)
831 unsigned int *sp;
833 /* Found a loop involving pointer addition. */
834 for (sp = osi->tos; sp > osi->stack; )
836 --sp;
837 bitmap_clear_bit (osi->reexamine, *sp);
838 bitmap_set_bit (computed[osi->object_size_type], *sp);
839 object_sizes[osi->object_size_type][*sp] = 0;
840 if (*sp == varno)
841 break;
844 return;
846 else if (! bitmap_bit_p (osi->reexamine, varno))
847 return;
849 osi->depths[varno] = depth;
850 *osi->tos++ = varno;
852 switch (TREE_CODE (stmt))
854 case RETURN_EXPR:
855 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
856 stmt = TREE_OPERAND (stmt, 0);
857 /* FALLTHRU */
859 case GIMPLE_MODIFY_STMT:
861 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
862 STRIP_NOPS (rhs);
864 if (TREE_CODE (rhs) == CALL_EXPR)
866 arg = pass_through_call (rhs);
867 if (arg)
868 rhs = arg;
871 if (TREE_CODE (rhs) == SSA_NAME)
872 check_for_plus_in_loops_1 (osi, rhs, depth);
873 else if (TREE_CODE (rhs) == PLUS_EXPR)
875 tree op0 = TREE_OPERAND (rhs, 0);
876 tree op1 = TREE_OPERAND (rhs, 1);
877 tree cst, basevar;
879 if (TREE_CODE (op0) == SSA_NAME)
881 basevar = op0;
882 cst = op1;
884 else
886 basevar = op1;
887 cst = op0;
888 gcc_assert (TREE_CODE (basevar) == SSA_NAME);
890 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
892 check_for_plus_in_loops_1 (osi, basevar,
893 depth + !integer_zerop (cst));
895 else
896 gcc_unreachable ();
897 break;
899 case PHI_NODE:
901 int i;
903 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
905 tree rhs = PHI_ARG_DEF (stmt, i);
907 if (TREE_CODE (rhs) == SSA_NAME)
908 check_for_plus_in_loops_1 (osi, rhs, depth);
910 break;
912 default:
913 gcc_unreachable ();
916 osi->depths[varno] = 0;
917 osi->tos--;
921 /* Check if some pointer we are computing object size of is being increased
922 within a loop. If yes, assume all the SSA variables participating in
923 that loop have minimum object sizes 0. */
925 static void
926 check_for_plus_in_loops (struct object_size_info *osi, tree var)
928 tree stmt = SSA_NAME_DEF_STMT (var);
930 switch (TREE_CODE (stmt))
932 case RETURN_EXPR:
933 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
934 stmt = TREE_OPERAND (stmt, 0);
935 /* FALLTHRU */
937 case GIMPLE_MODIFY_STMT:
939 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
940 STRIP_NOPS (rhs);
942 if (TREE_CODE (rhs) == CALL_EXPR)
944 arg = pass_through_call (rhs);
945 if (arg)
946 rhs = arg;
949 if (TREE_CODE (rhs) == PLUS_EXPR)
951 tree op0 = TREE_OPERAND (rhs, 0);
952 tree op1 = TREE_OPERAND (rhs, 1);
953 tree cst, basevar;
955 if (TREE_CODE (op0) == SSA_NAME)
957 basevar = op0;
958 cst = op1;
960 else
962 basevar = op1;
963 cst = op0;
964 gcc_assert (TREE_CODE (basevar) == SSA_NAME);
966 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
968 if (integer_zerop (cst))
969 break;
971 osi->depths[SSA_NAME_VERSION (basevar)] = 1;
972 *osi->tos++ = SSA_NAME_VERSION (basevar);
973 check_for_plus_in_loops_1 (osi, var, 2);
974 osi->depths[SSA_NAME_VERSION (basevar)] = 0;
975 osi->tos--;
977 break;
979 default:
980 break;
985 /* Initialize data structures for the object size computation. */
987 void
988 init_object_sizes (void)
990 int object_size_type;
992 if (object_sizes[0])
993 return;
995 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
997 object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names);
998 computed[object_size_type] = BITMAP_ALLOC (NULL);
1001 init_offset_limit ();
1005 /* Destroy data structures after the object size computation. */
1007 void
1008 fini_object_sizes (void)
1010 int object_size_type;
1012 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1014 free (object_sizes[object_size_type]);
1015 BITMAP_FREE (computed[object_size_type]);
1016 object_sizes[object_size_type] = NULL;
1021 /* Simple pass to optimize all __builtin_object_size () builtins. */
1023 static unsigned int
1024 compute_object_sizes (void)
1026 basic_block bb;
1027 FOR_EACH_BB (bb)
1029 block_stmt_iterator i;
1030 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
1032 tree *stmtp = bsi_stmt_ptr (i);
1033 tree call = get_rhs (*stmtp);
1034 tree callee, result;
1036 if (!call || TREE_CODE (call) != CALL_EXPR)
1037 continue;
1039 callee = get_callee_fndecl (call);
1040 if (!callee
1041 || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
1042 || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE)
1043 continue;
1045 init_object_sizes ();
1046 result = fold_builtin (callee, TREE_OPERAND (call, 1), false);
1047 if (!result)
1049 tree arglist = TREE_OPERAND (call, 1);
1051 if (arglist != NULL
1052 && POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
1053 && TREE_CHAIN (arglist) != NULL
1054 && TREE_CHAIN (TREE_CHAIN (arglist)) == NULL)
1056 tree ost = TREE_VALUE (TREE_CHAIN (arglist));
1058 if (host_integerp (ost, 1))
1060 unsigned HOST_WIDE_INT object_size_type
1061 = tree_low_cst (ost, 1);
1063 if (object_size_type < 2)
1064 result = fold_convert (size_type_node,
1065 integer_minus_one_node);
1066 else if (object_size_type < 4)
1067 result = size_zero_node;
1071 if (!result)
1072 continue;
1075 if (dump_file && (dump_flags & TDF_DETAILS))
1077 fprintf (dump_file, "Simplified\n ");
1078 print_generic_stmt (dump_file, *stmtp, dump_flags);
1081 if (!set_rhs (stmtp, result))
1082 gcc_unreachable ();
1083 update_stmt (*stmtp);
1085 if (dump_file && (dump_flags & TDF_DETAILS))
1087 fprintf (dump_file, "to\n ");
1088 print_generic_stmt (dump_file, *stmtp, dump_flags);
1089 fprintf (dump_file, "\n");
1094 fini_object_sizes ();
1095 return 0;
1098 struct tree_opt_pass pass_object_sizes =
1100 "objsz", /* name */
1101 NULL, /* gate */
1102 compute_object_sizes, /* execute */
1103 NULL, /* sub */
1104 NULL, /* next */
1105 0, /* static_pass_number */
1106 0, /* tv_id */
1107 PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */
1108 0, /* properties_provided */
1109 0, /* properties_destroyed */
1110 0, /* todo_flags_start */
1111 TODO_dump_func | TODO_verify_ssa, /* todo_flags_finish */
1112 0 /* letter */