PR tree-opt/22237
[official-gcc.git] / gcc / tree-object-size.c
blob178dc98d6278805e7b0daa566fedff581f229378
1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004, 2005 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 void compute_object_sizes (void);
54 static void init_offset_limit (void);
55 static void check_for_plus_in_loops (struct object_size_info *, tree);
56 static void check_for_plus_in_loops_1 (struct object_size_info *, tree,
57 unsigned int);
59 /* object_sizes[0] is upper bound for number of bytes till the end of
60 the object.
61 object_sizes[1] is upper bound for number of bytes till the end of
62 the subobject (innermost array or field with address taken).
63 object_sizes[2] is lower bound for number of bytes till the end of
64 the object and object_sizes[3] lower bound for subobject. */
65 static unsigned HOST_WIDE_INT *object_sizes[4];
67 /* Bitmaps what object sizes have been computed already. */
68 static bitmap computed[4];
70 /* Maximum value of offset we consider to be addition. */
71 static unsigned HOST_WIDE_INT offset_limit;
74 /* Initialize OFFSET_LIMIT variable. */
75 static void
76 init_offset_limit (void)
78 if (host_integerp (TYPE_MAX_VALUE (sizetype), 1))
79 offset_limit = tree_low_cst (TYPE_MAX_VALUE (sizetype), 1);
80 else
81 offset_limit = -1;
82 offset_limit /= 2;
86 /* Compute offset of EXPR within VAR. Return error_mark_node
87 if unknown. */
89 static tree
90 compute_object_offset (tree expr, tree var)
92 enum tree_code code = PLUS_EXPR;
93 tree base, off, t;
95 if (expr == var)
96 return size_zero_node;
98 switch (TREE_CODE (expr))
100 case COMPONENT_REF:
101 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
102 if (base == error_mark_node)
103 return base;
105 t = TREE_OPERAND (expr, 1);
106 off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
107 size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
108 / BITS_PER_UNIT));
109 break;
111 case REALPART_EXPR:
112 case NOP_EXPR:
113 case CONVERT_EXPR:
114 case VIEW_CONVERT_EXPR:
115 case NON_LVALUE_EXPR:
116 return compute_object_offset (TREE_OPERAND (expr, 0), var);
118 case IMAGPART_EXPR:
119 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
120 if (base == error_mark_node)
121 return base;
123 off = TYPE_SIZE_UNIT (TREE_TYPE (expr));
124 break;
126 case ARRAY_REF:
127 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
128 if (base == error_mark_node)
129 return base;
131 t = TREE_OPERAND (expr, 1);
132 if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
134 code = MINUS_EXPR;
135 t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
137 t = convert (sizetype, t);
138 off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
139 break;
141 default:
142 return error_mark_node;
145 return size_binop (code, base, off);
149 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
150 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
151 If unknown, return unknown[object_size_type]. */
153 static unsigned HOST_WIDE_INT
154 addr_object_size (tree ptr, int object_size_type)
156 tree pt_var;
158 gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
160 pt_var = TREE_OPERAND (ptr, 0);
161 if (REFERENCE_CLASS_P (pt_var))
162 pt_var = get_base_address (pt_var);
164 if (pt_var
165 && (SSA_VAR_P (pt_var) || TREE_CODE (pt_var) == STRING_CST)
166 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
167 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
168 && (unsigned HOST_WIDE_INT)
169 tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1) < offset_limit)
171 tree bytes;
173 if (pt_var != TREE_OPERAND (ptr, 0))
175 tree var;
177 if (object_size_type & 1)
179 var = TREE_OPERAND (ptr, 0);
181 while (var != pt_var
182 && TREE_CODE (var) != BIT_FIELD_REF
183 && TREE_CODE (var) != COMPONENT_REF
184 && TREE_CODE (var) != ARRAY_REF
185 && TREE_CODE (var) != ARRAY_RANGE_REF
186 && TREE_CODE (var) != REALPART_EXPR
187 && TREE_CODE (var) != IMAGPART_EXPR)
188 var = TREE_OPERAND (var, 0);
189 if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
190 var = TREE_OPERAND (var, 0);
191 if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
192 || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
193 || tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)),
194 TYPE_SIZE_UNIT (TREE_TYPE (var))))
195 var = pt_var;
197 else
198 var = pt_var;
200 bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
201 if (bytes != error_mark_node)
203 if (TREE_CODE (bytes) == INTEGER_CST
204 && tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes))
205 bytes = size_zero_node;
206 else
207 bytes = size_binop (MINUS_EXPR,
208 TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes);
211 else
212 bytes = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
214 if (host_integerp (bytes, 1))
215 return tree_low_cst (bytes, 1);
218 return unknown[object_size_type];
222 /* Compute __builtin_object_size for CALL, which is a CALL_EXPR.
223 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
224 argument from __builtin_object_size. If unknown, return
225 unknown[object_size_type]. */
227 static unsigned HOST_WIDE_INT
228 alloc_object_size (tree call, int object_size_type)
230 tree callee, arglist, a, bytes = NULL_TREE;
231 unsigned int arg_mask = 0;
233 gcc_assert (TREE_CODE (call) == CALL_EXPR);
235 callee = get_callee_fndecl (call);
236 arglist = TREE_OPERAND (call, 1);
237 if (callee
238 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
239 switch (DECL_FUNCTION_CODE (callee))
241 case BUILT_IN_MALLOC:
242 case BUILT_IN_ALLOCA:
243 arg_mask = 1;
244 break;
246 case BUILT_IN_REALLOC:
247 arg_mask = 2;
248 break;
250 case BUILT_IN_CALLOC:
251 arg_mask = 3;
252 break;
253 default:
254 break;
257 for (a = arglist; arg_mask && a; arg_mask >>= 1, a = TREE_CHAIN (a))
258 if (arg_mask & 1)
260 tree arg = TREE_VALUE (a);
262 if (TREE_CODE (arg) != INTEGER_CST)
263 break;
265 if (! bytes)
266 bytes = fold_convert (sizetype, arg);
267 else
268 bytes = size_binop (MULT_EXPR, bytes,
269 fold_convert (sizetype, arg));
272 if (! arg_mask && bytes && host_integerp (bytes, 1))
273 return tree_low_cst (bytes, 1);
275 return unknown[object_size_type];
279 /* If object size is propagated from one of function's arguments directly
280 to its return value, return that argument for CALL_EXPR CALL.
281 Otherwise return NULL. */
283 static tree
284 pass_through_call (tree call)
286 tree callee = get_callee_fndecl (call);
287 tree arglist = TREE_OPERAND (call, 1);
289 if (callee
290 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
291 switch (DECL_FUNCTION_CODE (callee))
293 case BUILT_IN_MEMCPY:
294 case BUILT_IN_MEMMOVE:
295 case BUILT_IN_MEMSET:
296 case BUILT_IN_STRCPY:
297 case BUILT_IN_STRNCPY:
298 case BUILT_IN_STRCAT:
299 case BUILT_IN_STRNCAT:
300 case BUILT_IN_MEMCPY_CHK:
301 case BUILT_IN_MEMMOVE_CHK:
302 case BUILT_IN_MEMSET_CHK:
303 case BUILT_IN_STRCPY_CHK:
304 case BUILT_IN_STRNCPY_CHK:
305 case BUILT_IN_STRCAT_CHK:
306 case BUILT_IN_STRNCAT_CHK:
307 if (arglist)
308 return TREE_VALUE (arglist);
309 break;
310 default:
311 break;
314 return NULL_TREE;
318 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
319 second argument from __builtin_object_size. */
321 unsigned HOST_WIDE_INT
322 compute_builtin_object_size (tree ptr, int object_size_type)
324 gcc_assert (object_size_type >= 0 && object_size_type <= 3);
326 if (! offset_limit)
327 init_offset_limit ();
329 if (TREE_CODE (ptr) == ADDR_EXPR)
330 return addr_object_size (ptr, object_size_type);
331 else if (TREE_CODE (ptr) == CALL_EXPR)
333 tree arg = pass_through_call (ptr);
335 if (arg)
336 return compute_builtin_object_size (arg, object_size_type);
337 else
338 return alloc_object_size (ptr, object_size_type);
340 else if (TREE_CODE (ptr) == SSA_NAME
341 && POINTER_TYPE_P (TREE_TYPE (ptr))
342 && object_sizes[object_size_type] != NULL)
344 if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
346 struct object_size_info osi;
347 bitmap_iterator bi;
348 unsigned int i;
350 if (dump_file)
352 fprintf (dump_file, "Computing %s %sobject size for ",
353 (object_size_type & 2) ? "minimum" : "maximum",
354 (object_size_type & 1) ? "sub" : "");
355 print_generic_expr (dump_file, ptr, dump_flags);
356 fprintf (dump_file, ":\n");
359 osi.visited = BITMAP_ALLOC (NULL);
360 osi.reexamine = BITMAP_ALLOC (NULL);
361 osi.object_size_type = object_size_type;
362 osi.depths = NULL;
363 osi.stack = NULL;
364 osi.tos = NULL;
366 /* First pass: walk UD chains, compute object sizes that
367 can be computed. osi.reexamine bitmap at the end will
368 contain what variables were found in dependency cycles
369 and therefore need to be reexamined. */
370 osi.pass = 0;
371 osi.changed = false;
372 collect_object_sizes_for (&osi, ptr);
374 /* Second pass: keep recomputing object sizes of variables
375 that need reexamination, until no object sizes are
376 increased or all object sizes are computed. */
377 if (! bitmap_empty_p (osi.reexamine))
379 bitmap reexamine = BITMAP_ALLOC (NULL);
381 /* If looking for minimum instead of maximum object size,
382 detect cases where a pointer is increased in a loop.
383 Although even without this detection pass 2 would eventually
384 terminate, it could take a long time. If a pointer is
385 increasing this way, we need to assume 0 object size.
386 E.g. p = &buf[0]; while (cond) p = p + 4; */
387 if (object_size_type & 2)
389 osi.depths = xcalloc (num_ssa_names, sizeof (unsigned int));
390 osi.stack = xmalloc (num_ssa_names * sizeof (unsigned int));
391 osi.tos = osi.stack;
392 osi.pass = 1;
393 /* collect_object_sizes_for is changing
394 osi.reexamine bitmap, so iterate over a copy. */
395 bitmap_copy (reexamine, osi.reexamine);
396 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
397 if (bitmap_bit_p (osi.reexamine, i))
398 check_for_plus_in_loops (&osi, ssa_name (i));
400 free (osi.depths);
401 osi.depths = NULL;
402 free (osi.stack);
403 osi.stack = NULL;
404 osi.tos = NULL;
409 osi.pass = 2;
410 osi.changed = false;
411 /* collect_object_sizes_for is changing
412 osi.reexamine bitmap, so iterate over a copy. */
413 bitmap_copy (reexamine, osi.reexamine);
414 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
415 if (bitmap_bit_p (osi.reexamine, i))
417 collect_object_sizes_for (&osi, ssa_name (i));
418 if (dump_file && (dump_flags & TDF_DETAILS))
420 fprintf (dump_file, "Reexamining ");
421 print_generic_expr (dump_file, ssa_name (i),
422 dump_flags);
423 fprintf (dump_file, "\n");
427 while (osi.changed);
429 BITMAP_FREE (reexamine);
431 EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
432 bitmap_set_bit (computed[object_size_type], i);
434 /* Debugging dumps. */
435 if (dump_file)
437 EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
438 if (object_sizes[object_size_type][i]
439 != unknown[object_size_type])
441 print_generic_expr (dump_file, ssa_name (i),
442 dump_flags);
443 fprintf (dump_file,
444 ": %s %sobject size "
445 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
446 (object_size_type & 2) ? "minimum" : "maximum",
447 (object_size_type & 1) ? "sub" : "",
448 object_sizes[object_size_type][i]);
452 BITMAP_FREE (osi.reexamine);
453 BITMAP_FREE (osi.visited);
456 return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
459 return unknown[object_size_type];
463 /* Compute object_sizes for PTR, defined to VALUE, which is not
464 a SSA_NAME. */
466 static void
467 expr_object_size (struct object_size_info *osi, tree ptr, tree value)
469 int object_size_type = osi->object_size_type;
470 unsigned int varno = SSA_NAME_VERSION (ptr);
471 unsigned HOST_WIDE_INT bytes;
473 gcc_assert (object_sizes[object_size_type][varno]
474 != unknown[object_size_type]);
475 gcc_assert (osi->pass == 0);
477 if (TREE_CODE (value) == WITH_SIZE_EXPR)
478 value = TREE_OPERAND (value, 0);
480 /* Pointer variables should have been handled by merge_object_sizes. */
481 gcc_assert (TREE_CODE (value) != SSA_NAME
482 || !POINTER_TYPE_P (TREE_TYPE (value)));
484 if (TREE_CODE (value) == ADDR_EXPR)
485 bytes = addr_object_size (value, object_size_type);
486 else if (TREE_CODE (value) == CALL_EXPR)
487 bytes = alloc_object_size (value, object_size_type);
488 else
489 bytes = unknown[object_size_type];
491 if ((object_size_type & 2) == 0)
493 if (object_sizes[object_size_type][varno] < bytes)
494 object_sizes[object_size_type][varno] = bytes;
496 else
498 if (object_sizes[object_size_type][varno] > bytes)
499 object_sizes[object_size_type][varno] = bytes;
504 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
505 the object size might need reexamination later. */
507 static bool
508 merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
509 unsigned HOST_WIDE_INT offset)
511 int object_size_type = osi->object_size_type;
512 unsigned int varno = SSA_NAME_VERSION (dest);
513 unsigned HOST_WIDE_INT orig_bytes;
515 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
516 return false;
517 if (offset >= offset_limit)
519 object_sizes[object_size_type][varno] = unknown[object_size_type];
520 return false;
523 if (osi->pass == 0)
524 collect_object_sizes_for (osi, orig);
526 orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
527 if (orig_bytes != unknown[object_size_type])
528 orig_bytes = (offset > orig_bytes)
529 ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset;
531 if ((object_size_type & 2) == 0)
533 if (object_sizes[object_size_type][varno] < orig_bytes)
535 object_sizes[object_size_type][varno] = orig_bytes;
536 osi->changed = true;
539 else
541 if (object_sizes[object_size_type][varno] > orig_bytes)
543 object_sizes[object_size_type][varno] = orig_bytes;
544 osi->changed = true;
547 return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
551 /* Compute object_sizes for PTR, defined to VALUE, which is
552 a PLUS_EXPR. Return true if the object size might need reexamination
553 later. */
555 static bool
556 plus_expr_object_size (struct object_size_info *osi, tree var, tree value)
558 tree op0 = TREE_OPERAND (value, 0);
559 tree op1 = TREE_OPERAND (value, 1);
560 bool ptr1_p = POINTER_TYPE_P (TREE_TYPE (op0))
561 && TREE_CODE (op0) != INTEGER_CST;
562 bool ptr2_p = POINTER_TYPE_P (TREE_TYPE (op1))
563 && TREE_CODE (op1) != INTEGER_CST;
564 int object_size_type = osi->object_size_type;
565 unsigned int varno = SSA_NAME_VERSION (var);
566 unsigned HOST_WIDE_INT bytes;
568 gcc_assert (TREE_CODE (value) == PLUS_EXPR);
570 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
571 return false;
573 /* Swap operands if needed. */
574 if (ptr2_p && !ptr1_p)
576 tree tem = op0;
577 op0 = op1;
578 op1 = tem;
579 ptr1_p = true;
580 ptr2_p = false;
583 /* Handle PTR + OFFSET here. */
584 if (ptr1_p
585 && !ptr2_p
586 && TREE_CODE (op1) == INTEGER_CST
587 && (TREE_CODE (op0) == SSA_NAME
588 || TREE_CODE (op0) == ADDR_EXPR))
590 if (! host_integerp (op1, 1))
591 bytes = unknown[object_size_type];
592 else if (TREE_CODE (op0) == SSA_NAME)
593 return merge_object_sizes (osi, var, op0, tree_low_cst (op1, 1));
594 else
596 unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
598 bytes = compute_builtin_object_size (value, object_size_type);
599 if (off > offset_limit)
600 bytes = unknown[object_size_type];
601 else if (off > bytes)
602 bytes = 0;
603 else
604 bytes -= off;
607 else
608 bytes = unknown[object_size_type];
610 if ((object_size_type & 2) == 0)
612 if (object_sizes[object_size_type][varno] < bytes)
613 object_sizes[object_size_type][varno] = bytes;
615 else
617 if (object_sizes[object_size_type][varno] > bytes)
618 object_sizes[object_size_type][varno] = bytes;
620 return false;
624 /* Compute object sizes for VAR.
625 For ADDR_EXPR an object size is the number of remaining bytes
626 to the end of the object (where what is considered an object depends on
627 OSI->object_size_type).
628 For allocation CALL_EXPR like malloc or calloc object size is the size
629 of the allocation.
630 For pointer PLUS_EXPR where second operand is a constant integer,
631 object size is object size of the first operand minus the constant.
632 If the constant is bigger than the number of remaining bytes until the
633 end of the object, object size is 0, but if it is instead a pointer
634 subtraction, object size is unknown[object_size_type].
635 To differentiate addition from subtraction, ADDR_EXPR returns
636 unknown[object_size_type] for all objects bigger than half of the address
637 space, and constants less than half of the address space are considered
638 addition, while bigger constants subtraction.
639 For a memcpy like CALL_EXPR that always returns one of its arguments, the
640 object size is object size of that argument.
641 Otherwise, object size is the maximum of object sizes of variables
642 that it might be set to. */
644 static void
645 collect_object_sizes_for (struct object_size_info *osi, tree var)
647 int object_size_type = osi->object_size_type;
648 unsigned int varno = SSA_NAME_VERSION (var);
649 tree stmt;
650 bool reexamine;
652 if (bitmap_bit_p (computed[object_size_type], varno))
653 return;
655 if (osi->pass == 0)
657 if (! bitmap_bit_p (osi->visited, varno))
659 bitmap_set_bit (osi->visited, varno);
660 object_sizes[object_size_type][varno]
661 = (object_size_type & 2) ? -1 : 0;
663 else
665 /* Found a dependency loop. Mark the variable for later
666 re-examination. */
667 bitmap_set_bit (osi->reexamine, varno);
668 if (dump_file && (dump_flags & TDF_DETAILS))
670 fprintf (dump_file, "Found a dependency loop at ");
671 print_generic_expr (dump_file, var, dump_flags);
672 fprintf (dump_file, "\n");
674 return;
678 if (dump_file && (dump_flags & TDF_DETAILS))
680 fprintf (dump_file, "Visiting use-def links for ");
681 print_generic_expr (dump_file, var, dump_flags);
682 fprintf (dump_file, "\n");
685 stmt = SSA_NAME_DEF_STMT (var);
686 reexamine = false;
688 switch (TREE_CODE (stmt))
690 case RETURN_EXPR:
691 if (TREE_CODE (TREE_OPERAND (stmt, 0)) != MODIFY_EXPR)
692 abort ();
693 stmt = TREE_OPERAND (stmt, 0);
694 /* FALLTHRU */
696 case MODIFY_EXPR:
698 tree rhs = TREE_OPERAND (stmt, 1), arg;
699 STRIP_NOPS (rhs);
701 if (TREE_CODE (rhs) == CALL_EXPR)
703 arg = pass_through_call (rhs);
704 if (arg)
705 rhs = arg;
708 if (TREE_CODE (rhs) == SSA_NAME
709 && POINTER_TYPE_P (TREE_TYPE (rhs)))
710 reexamine = merge_object_sizes (osi, var, rhs, 0);
712 else if (TREE_CODE (rhs) == PLUS_EXPR)
713 reexamine = plus_expr_object_size (osi, var, rhs);
715 else
716 expr_object_size (osi, var, rhs);
717 break;
720 case ASM_EXPR:
721 /* Pointers defined by __asm__ statements can point anywhere. */
722 object_sizes[object_size_type][varno] = unknown[object_size_type];
723 break;
725 case NOP_EXPR:
727 tree decl = SSA_NAME_VAR (var);
729 gcc_assert (IS_EMPTY_STMT (stmt));
731 if (TREE_CODE (decl) != PARM_DECL && DECL_INITIAL (decl))
732 expr_object_size (osi, var, DECL_INITIAL (decl));
733 else
734 expr_object_size (osi, var, decl);
736 break;
738 case PHI_NODE:
740 int i;
742 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
744 tree rhs = PHI_ARG_DEF (stmt, i);
746 if (object_sizes[object_size_type][varno]
747 == unknown[object_size_type])
748 break;
750 if (TREE_CODE (rhs) == SSA_NAME)
751 reexamine |= merge_object_sizes (osi, var, rhs, 0);
752 else if (osi->pass == 0)
753 expr_object_size (osi, var, rhs);
755 break;
757 default:
758 gcc_unreachable ();
761 if (! reexamine
762 || object_sizes[object_size_type][varno] == unknown[object_size_type])
764 bitmap_set_bit (computed[object_size_type], varno);
765 bitmap_clear_bit (osi->reexamine, varno);
767 else
769 bitmap_set_bit (osi->reexamine, varno);
770 if (dump_file && (dump_flags & TDF_DETAILS))
772 fprintf (dump_file, "Need to reexamine ");
773 print_generic_expr (dump_file, var, dump_flags);
774 fprintf (dump_file, "\n");
780 /* Helper function for check_for_plus_in_loops. Called recursively
781 to detect loops. */
783 static void
784 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
785 unsigned int depth)
787 tree stmt = SSA_NAME_DEF_STMT (var);
788 unsigned int varno = SSA_NAME_VERSION (var);
790 if (osi->depths[varno])
792 if (osi->depths[varno] != depth)
794 unsigned int *sp;
796 /* Found a loop involving pointer addition. */
797 for (sp = osi->tos; sp > osi->stack; )
799 --sp;
800 bitmap_clear_bit (osi->reexamine, *sp);
801 bitmap_set_bit (computed[osi->object_size_type], *sp);
802 object_sizes[osi->object_size_type][*sp] = 0;
803 if (*sp == varno)
804 break;
807 return;
809 else if (! bitmap_bit_p (osi->reexamine, varno))
810 return;
812 osi->depths[varno] = depth;
813 *osi->tos++ = varno;
815 switch (TREE_CODE (stmt))
817 case RETURN_EXPR:
818 if (TREE_CODE (TREE_OPERAND (stmt, 0)) != MODIFY_EXPR)
819 abort ();
820 stmt = TREE_OPERAND (stmt, 0);
821 /* FALLTHRU */
823 case MODIFY_EXPR:
825 tree rhs = TREE_OPERAND (stmt, 1), arg;
826 STRIP_NOPS (rhs);
828 if (TREE_CODE (rhs) == CALL_EXPR)
830 arg = pass_through_call (rhs);
831 if (arg)
832 rhs = arg;
835 if (TREE_CODE (rhs) == SSA_NAME)
836 check_for_plus_in_loops_1 (osi, rhs, depth);
837 else if (TREE_CODE (rhs) == PLUS_EXPR)
839 tree op0 = TREE_OPERAND (rhs, 0);
840 tree op1 = TREE_OPERAND (rhs, 1);
841 tree cst, basevar;
843 if (TREE_CODE (op0) == SSA_NAME)
845 basevar = op0;
846 cst = op1;
848 else
850 basevar = op1;
851 cst = op0;
852 gcc_assert (TREE_CODE (basevar) == SSA_NAME);
854 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
856 check_for_plus_in_loops_1 (osi, basevar,
857 depth + !integer_zerop (cst));
859 else
860 gcc_unreachable ();
861 break;
863 case PHI_NODE:
865 int i;
867 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
869 tree rhs = PHI_ARG_DEF (stmt, i);
871 if (TREE_CODE (rhs) == SSA_NAME)
872 check_for_plus_in_loops_1 (osi, rhs, depth);
874 break;
876 default:
877 gcc_unreachable ();
880 osi->depths[varno] = 0;
881 osi->tos--;
885 /* Check if some pointer we are computing object size of is being increased
886 within a loop. If yes, assume all the SSA variables participating in
887 that loop have minimum object sizes 0. */
889 static void
890 check_for_plus_in_loops (struct object_size_info *osi, tree var)
892 tree stmt = SSA_NAME_DEF_STMT (var);
894 switch (TREE_CODE (stmt))
896 case RETURN_EXPR:
897 if (TREE_CODE (TREE_OPERAND (stmt, 0)) != MODIFY_EXPR)
898 abort ();
899 stmt = TREE_OPERAND (stmt, 0);
900 /* FALLTHRU */
902 case MODIFY_EXPR:
904 tree rhs = TREE_OPERAND (stmt, 1), arg;
905 STRIP_NOPS (rhs);
907 if (TREE_CODE (rhs) == CALL_EXPR)
909 arg = pass_through_call (rhs);
910 if (arg)
911 rhs = arg;
914 if (TREE_CODE (rhs) == PLUS_EXPR)
916 tree op0 = TREE_OPERAND (rhs, 0);
917 tree op1 = TREE_OPERAND (rhs, 1);
918 tree cst, basevar;
920 if (TREE_CODE (op0) == SSA_NAME)
922 basevar = op0;
923 cst = op1;
925 else
927 basevar = op1;
928 cst = op0;
929 gcc_assert (TREE_CODE (basevar) == SSA_NAME);
931 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
933 if (integer_zerop (cst))
934 break;
936 osi->depths[SSA_NAME_VERSION (basevar)] = 1;
937 *osi->tos++ = SSA_NAME_VERSION (basevar);
938 check_for_plus_in_loops_1 (osi, var, 2);
939 osi->depths[SSA_NAME_VERSION (basevar)] = 0;
940 osi->tos--;
942 break;
944 default:
945 break;
950 /* Initialize data structures for the object size computation. */
952 void
953 init_object_sizes (void)
955 int object_size_type;
957 if (object_sizes[0])
958 return;
960 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
962 object_sizes[object_size_type]
963 = xmalloc (num_ssa_names * sizeof (HOST_WIDE_INT));
964 computed[object_size_type] = BITMAP_ALLOC (NULL);
967 init_offset_limit ();
971 /* Destroy data structures after the object size computation. */
973 void
974 fini_object_sizes (void)
976 int object_size_type;
978 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
980 free (object_sizes[object_size_type]);
981 BITMAP_FREE (computed[object_size_type]);
982 object_sizes[object_size_type] = NULL;
987 /* Simple pass to optimize all __builtin_object_size () builtins. */
989 static void
990 compute_object_sizes (void)
992 basic_block bb;
993 FOR_EACH_BB (bb)
995 block_stmt_iterator i;
996 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
998 tree *stmtp = bsi_stmt_ptr (i);
999 tree call = get_rhs (*stmtp);
1000 tree callee, result;
1002 if (!call || TREE_CODE (call) != CALL_EXPR)
1003 continue;
1005 callee = get_callee_fndecl (call);
1006 if (!callee
1007 || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
1008 || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE)
1009 continue;
1011 init_object_sizes ();
1012 result = fold_builtin (callee, TREE_OPERAND (call, 1), false);
1013 if (!result)
1015 tree arglist = TREE_OPERAND (call, 1);
1017 if (arglist != NULL
1018 && POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
1019 && TREE_CHAIN (arglist) != NULL
1020 && TREE_CHAIN (TREE_CHAIN (arglist)) == NULL)
1022 tree ost = TREE_VALUE (TREE_CHAIN (arglist));
1024 if (host_integerp (ost, 1))
1026 unsigned HOST_WIDE_INT object_size_type
1027 = tree_low_cst (ost, 1);
1029 if (object_size_type < 2)
1030 result = fold_convert (size_type_node,
1031 integer_minus_one_node);
1032 else if (object_size_type < 4)
1033 result = size_zero_node;
1037 if (!result)
1038 continue;
1041 if (dump_file && (dump_flags & TDF_DETAILS))
1043 fprintf (dump_file, "Simplified\n ");
1044 print_generic_stmt (dump_file, *stmtp, dump_flags);
1047 if (!set_rhs (stmtp, result))
1048 abort ();
1049 update_stmt (*stmtp);
1051 if (dump_file && (dump_flags & TDF_DETAILS))
1053 fprintf (dump_file, "to\n ");
1054 print_generic_stmt (dump_file, *stmtp, dump_flags);
1055 fprintf (dump_file, "\n");
1060 fini_object_sizes ();
1063 struct tree_opt_pass pass_object_sizes =
1065 "objsz", /* name */
1066 NULL, /* gate */
1067 compute_object_sizes, /* execute */
1068 NULL, /* sub */
1069 NULL, /* next */
1070 0, /* static_pass_number */
1071 0, /* tv_id */
1072 PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */
1073 0, /* properties_provided */
1074 0, /* properties_destroyed */
1075 0, /* todo_flags_start */
1076 TODO_dump_func | TODO_verify_ssa, /* todo_flags_finish */
1077 0 /* letter */