PR tree-optimization/27639
[official-gcc.git] / gcc / tree-object-size.c
blob7a3d77571864e837719b94b4b4635012e6f6b401
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 unsigned int 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 = fold_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 = XCNEWVEC (unsigned int, num_ssa_names);
390 osi.stack = XNEWVEC (unsigned int, num_ssa_names);
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 (op0, 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 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR);
692 stmt = TREE_OPERAND (stmt, 0);
693 /* FALLTHRU */
695 case MODIFY_EXPR:
697 tree rhs = TREE_OPERAND (stmt, 1), arg;
698 STRIP_NOPS (rhs);
700 if (TREE_CODE (rhs) == CALL_EXPR)
702 arg = pass_through_call (rhs);
703 if (arg)
704 rhs = arg;
707 if (TREE_CODE (rhs) == SSA_NAME
708 && POINTER_TYPE_P (TREE_TYPE (rhs)))
709 reexamine = merge_object_sizes (osi, var, rhs, 0);
711 else if (TREE_CODE (rhs) == PLUS_EXPR)
712 reexamine = plus_expr_object_size (osi, var, rhs);
714 else
715 expr_object_size (osi, var, rhs);
716 break;
719 case ASM_EXPR:
720 /* Pointers defined by __asm__ statements can point anywhere. */
721 object_sizes[object_size_type][varno] = unknown[object_size_type];
722 break;
724 case NOP_EXPR:
726 tree decl = SSA_NAME_VAR (var);
728 gcc_assert (IS_EMPTY_STMT (stmt));
730 if (TREE_CODE (decl) != PARM_DECL && DECL_INITIAL (decl))
731 expr_object_size (osi, var, DECL_INITIAL (decl));
732 else
733 expr_object_size (osi, var, decl);
735 break;
737 case PHI_NODE:
739 int i;
741 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
743 tree rhs = PHI_ARG_DEF (stmt, i);
745 if (object_sizes[object_size_type][varno]
746 == unknown[object_size_type])
747 break;
749 if (TREE_CODE (rhs) == SSA_NAME)
750 reexamine |= merge_object_sizes (osi, var, rhs, 0);
751 else if (osi->pass == 0)
752 expr_object_size (osi, var, rhs);
754 break;
756 default:
757 gcc_unreachable ();
760 if (! reexamine
761 || object_sizes[object_size_type][varno] == unknown[object_size_type])
763 bitmap_set_bit (computed[object_size_type], varno);
764 bitmap_clear_bit (osi->reexamine, varno);
766 else
768 bitmap_set_bit (osi->reexamine, varno);
769 if (dump_file && (dump_flags & TDF_DETAILS))
771 fprintf (dump_file, "Need to reexamine ");
772 print_generic_expr (dump_file, var, dump_flags);
773 fprintf (dump_file, "\n");
779 /* Helper function for check_for_plus_in_loops. Called recursively
780 to detect loops. */
782 static void
783 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
784 unsigned int depth)
786 tree stmt = SSA_NAME_DEF_STMT (var);
787 unsigned int varno = SSA_NAME_VERSION (var);
789 if (osi->depths[varno])
791 if (osi->depths[varno] != depth)
793 unsigned int *sp;
795 /* Found a loop involving pointer addition. */
796 for (sp = osi->tos; sp > osi->stack; )
798 --sp;
799 bitmap_clear_bit (osi->reexamine, *sp);
800 bitmap_set_bit (computed[osi->object_size_type], *sp);
801 object_sizes[osi->object_size_type][*sp] = 0;
802 if (*sp == varno)
803 break;
806 return;
808 else if (! bitmap_bit_p (osi->reexamine, varno))
809 return;
811 osi->depths[varno] = depth;
812 *osi->tos++ = varno;
814 switch (TREE_CODE (stmt))
816 case RETURN_EXPR:
817 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR);
818 stmt = TREE_OPERAND (stmt, 0);
819 /* FALLTHRU */
821 case MODIFY_EXPR:
823 tree rhs = TREE_OPERAND (stmt, 1), arg;
824 STRIP_NOPS (rhs);
826 if (TREE_CODE (rhs) == CALL_EXPR)
828 arg = pass_through_call (rhs);
829 if (arg)
830 rhs = arg;
833 if (TREE_CODE (rhs) == SSA_NAME)
834 check_for_plus_in_loops_1 (osi, rhs, depth);
835 else if (TREE_CODE (rhs) == PLUS_EXPR)
837 tree op0 = TREE_OPERAND (rhs, 0);
838 tree op1 = TREE_OPERAND (rhs, 1);
839 tree cst, basevar;
841 if (TREE_CODE (op0) == SSA_NAME)
843 basevar = op0;
844 cst = op1;
846 else
848 basevar = op1;
849 cst = op0;
850 gcc_assert (TREE_CODE (basevar) == SSA_NAME);
852 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
854 check_for_plus_in_loops_1 (osi, basevar,
855 depth + !integer_zerop (cst));
857 else
858 gcc_unreachable ();
859 break;
861 case PHI_NODE:
863 int i;
865 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
867 tree rhs = PHI_ARG_DEF (stmt, i);
869 if (TREE_CODE (rhs) == SSA_NAME)
870 check_for_plus_in_loops_1 (osi, rhs, depth);
872 break;
874 default:
875 gcc_unreachable ();
878 osi->depths[varno] = 0;
879 osi->tos--;
883 /* Check if some pointer we are computing object size of is being increased
884 within a loop. If yes, assume all the SSA variables participating in
885 that loop have minimum object sizes 0. */
887 static void
888 check_for_plus_in_loops (struct object_size_info *osi, tree var)
890 tree stmt = SSA_NAME_DEF_STMT (var);
892 switch (TREE_CODE (stmt))
894 case RETURN_EXPR:
895 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR);
896 stmt = TREE_OPERAND (stmt, 0);
897 /* FALLTHRU */
899 case MODIFY_EXPR:
901 tree rhs = TREE_OPERAND (stmt, 1), arg;
902 STRIP_NOPS (rhs);
904 if (TREE_CODE (rhs) == CALL_EXPR)
906 arg = pass_through_call (rhs);
907 if (arg)
908 rhs = arg;
911 if (TREE_CODE (rhs) == PLUS_EXPR)
913 tree op0 = TREE_OPERAND (rhs, 0);
914 tree op1 = TREE_OPERAND (rhs, 1);
915 tree cst, basevar;
917 if (TREE_CODE (op0) == SSA_NAME)
919 basevar = op0;
920 cst = op1;
922 else
924 basevar = op1;
925 cst = op0;
926 gcc_assert (TREE_CODE (basevar) == SSA_NAME);
928 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
930 if (integer_zerop (cst))
931 break;
933 osi->depths[SSA_NAME_VERSION (basevar)] = 1;
934 *osi->tos++ = SSA_NAME_VERSION (basevar);
935 check_for_plus_in_loops_1 (osi, var, 2);
936 osi->depths[SSA_NAME_VERSION (basevar)] = 0;
937 osi->tos--;
939 break;
941 default:
942 break;
947 /* Initialize data structures for the object size computation. */
949 void
950 init_object_sizes (void)
952 int object_size_type;
954 if (object_sizes[0])
955 return;
957 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
959 object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names);
960 computed[object_size_type] = BITMAP_ALLOC (NULL);
963 init_offset_limit ();
967 /* Destroy data structures after the object size computation. */
969 void
970 fini_object_sizes (void)
972 int object_size_type;
974 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
976 free (object_sizes[object_size_type]);
977 BITMAP_FREE (computed[object_size_type]);
978 object_sizes[object_size_type] = NULL;
983 /* Simple pass to optimize all __builtin_object_size () builtins. */
985 static unsigned int
986 compute_object_sizes (void)
988 basic_block bb;
989 FOR_EACH_BB (bb)
991 block_stmt_iterator i;
992 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
994 tree *stmtp = bsi_stmt_ptr (i);
995 tree call = get_rhs (*stmtp);
996 tree callee, result;
998 if (!call || TREE_CODE (call) != CALL_EXPR)
999 continue;
1001 callee = get_callee_fndecl (call);
1002 if (!callee
1003 || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
1004 || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE)
1005 continue;
1007 init_object_sizes ();
1008 result = fold_builtin (callee, TREE_OPERAND (call, 1), false);
1009 if (!result)
1011 tree arglist = TREE_OPERAND (call, 1);
1013 if (arglist != NULL
1014 && POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
1015 && TREE_CHAIN (arglist) != NULL
1016 && TREE_CHAIN (TREE_CHAIN (arglist)) == NULL)
1018 tree ost = TREE_VALUE (TREE_CHAIN (arglist));
1020 if (host_integerp (ost, 1))
1022 unsigned HOST_WIDE_INT object_size_type
1023 = tree_low_cst (ost, 1);
1025 if (object_size_type < 2)
1026 result = fold_convert (size_type_node,
1027 integer_minus_one_node);
1028 else if (object_size_type < 4)
1029 result = size_zero_node;
1033 if (!result)
1034 continue;
1037 if (dump_file && (dump_flags & TDF_DETAILS))
1039 fprintf (dump_file, "Simplified\n ");
1040 print_generic_stmt (dump_file, *stmtp, dump_flags);
1043 if (!set_rhs (stmtp, result))
1044 gcc_unreachable ();
1045 update_stmt (*stmtp);
1047 if (dump_file && (dump_flags & TDF_DETAILS))
1049 fprintf (dump_file, "to\n ");
1050 print_generic_stmt (dump_file, *stmtp, dump_flags);
1051 fprintf (dump_file, "\n");
1056 fini_object_sizes ();
1057 return 0;
1060 struct tree_opt_pass pass_object_sizes =
1062 "objsz", /* name */
1063 NULL, /* gate */
1064 compute_object_sizes, /* execute */
1065 NULL, /* sub */
1066 NULL, /* next */
1067 0, /* static_pass_number */
1068 0, /* tv_id */
1069 PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */
1070 0, /* properties_provided */
1071 0, /* properties_destroyed */
1072 0, /* todo_flags_start */
1073 TODO_dump_func | TODO_verify_ssa, /* todo_flags_finish */
1074 0 /* letter */