libfuncs.h (LTI_synchronize): New libfunc_index.
[official-gcc.git] / gcc / tree-object-size.c
blobc1b3b5f1264582b9dfb445d968910fd32726f1bd
1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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 COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "toplev.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 (const_tree, const_tree);
45 static unsigned HOST_WIDE_INT addr_object_size (const_tree, int);
46 static unsigned HOST_WIDE_INT alloc_object_size (const_tree, int);
47 static tree pass_through_call (const_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 (const_tree expr, const_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_CONVERT:
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 (const_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 (const_tree call, int object_size_type)
230 tree callee, bytes = NULL_TREE;
231 tree alloc_size;
232 int arg1 = -1, arg2 = -1;
234 gcc_assert (TREE_CODE (call) == CALL_EXPR);
236 callee = get_callee_fndecl (call);
237 if (!callee)
238 return unknown[object_size_type];
240 alloc_size = lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee)));
241 if (alloc_size && TREE_VALUE (alloc_size))
243 tree p = TREE_VALUE (alloc_size);
245 arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1;
246 if (TREE_CHAIN (p))
247 arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
250 if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
251 switch (DECL_FUNCTION_CODE (callee))
253 case BUILT_IN_CALLOC:
254 arg2 = 1;
255 /* fall through */
256 case BUILT_IN_MALLOC:
257 case BUILT_IN_ALLOCA:
258 arg1 = 0;
259 default:
260 break;
263 if (arg1 < 0 || arg1 >= call_expr_nargs (call)
264 || TREE_CODE (CALL_EXPR_ARG (call, arg1)) != INTEGER_CST
265 || (arg2 >= 0
266 && (arg2 >= call_expr_nargs (call)
267 || TREE_CODE (CALL_EXPR_ARG (call, arg2)) != INTEGER_CST)))
268 return unknown[object_size_type];
270 if (arg2 >= 0)
271 bytes = size_binop (MULT_EXPR,
272 fold_convert (sizetype, CALL_EXPR_ARG (call, arg1)),
273 fold_convert (sizetype, CALL_EXPR_ARG (call, arg2)));
274 else if (arg1 >= 0)
275 bytes = fold_convert (sizetype, CALL_EXPR_ARG (call, arg1));
277 if (bytes && host_integerp (bytes, 1))
278 return tree_low_cst (bytes, 1);
280 return unknown[object_size_type];
284 /* If object size is propagated from one of function's arguments directly
285 to its return value, return that argument for CALL_EXPR CALL.
286 Otherwise return NULL. */
288 static tree
289 pass_through_call (const_tree call)
291 tree callee = get_callee_fndecl (call);
293 if (callee
294 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
295 switch (DECL_FUNCTION_CODE (callee))
297 case BUILT_IN_MEMCPY:
298 case BUILT_IN_MEMMOVE:
299 case BUILT_IN_MEMSET:
300 case BUILT_IN_STRCPY:
301 case BUILT_IN_STRNCPY:
302 case BUILT_IN_STRCAT:
303 case BUILT_IN_STRNCAT:
304 case BUILT_IN_MEMCPY_CHK:
305 case BUILT_IN_MEMMOVE_CHK:
306 case BUILT_IN_MEMSET_CHK:
307 case BUILT_IN_STRCPY_CHK:
308 case BUILT_IN_STRNCPY_CHK:
309 case BUILT_IN_STRCAT_CHK:
310 case BUILT_IN_STRNCAT_CHK:
311 if (call_expr_nargs (call) >= 1)
312 return CALL_EXPR_ARG (call, 0);
313 break;
314 default:
315 break;
318 return NULL_TREE;
322 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
323 second argument from __builtin_object_size. */
325 unsigned HOST_WIDE_INT
326 compute_builtin_object_size (tree ptr, int object_size_type)
328 gcc_assert (object_size_type >= 0 && object_size_type <= 3);
330 if (! offset_limit)
331 init_offset_limit ();
333 if (TREE_CODE (ptr) == ADDR_EXPR)
334 return addr_object_size (ptr, object_size_type);
335 else if (TREE_CODE (ptr) == CALL_EXPR)
337 tree arg = pass_through_call (ptr);
339 if (arg)
340 return compute_builtin_object_size (arg, object_size_type);
341 else
342 return alloc_object_size (ptr, object_size_type);
344 else if (TREE_CODE (ptr) == SSA_NAME
345 && POINTER_TYPE_P (TREE_TYPE (ptr))
346 && object_sizes[object_size_type] != NULL)
348 if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
350 struct object_size_info osi;
351 bitmap_iterator bi;
352 unsigned int i;
354 if (dump_file)
356 fprintf (dump_file, "Computing %s %sobject size for ",
357 (object_size_type & 2) ? "minimum" : "maximum",
358 (object_size_type & 1) ? "sub" : "");
359 print_generic_expr (dump_file, ptr, dump_flags);
360 fprintf (dump_file, ":\n");
363 osi.visited = BITMAP_ALLOC (NULL);
364 osi.reexamine = BITMAP_ALLOC (NULL);
365 osi.object_size_type = object_size_type;
366 osi.depths = NULL;
367 osi.stack = NULL;
368 osi.tos = NULL;
370 /* First pass: walk UD chains, compute object sizes that
371 can be computed. osi.reexamine bitmap at the end will
372 contain what variables were found in dependency cycles
373 and therefore need to be reexamined. */
374 osi.pass = 0;
375 osi.changed = false;
376 collect_object_sizes_for (&osi, ptr);
378 /* Second pass: keep recomputing object sizes of variables
379 that need reexamination, until no object sizes are
380 increased or all object sizes are computed. */
381 if (! bitmap_empty_p (osi.reexamine))
383 bitmap reexamine = BITMAP_ALLOC (NULL);
385 /* If looking for minimum instead of maximum object size,
386 detect cases where a pointer is increased in a loop.
387 Although even without this detection pass 2 would eventually
388 terminate, it could take a long time. If a pointer is
389 increasing this way, we need to assume 0 object size.
390 E.g. p = &buf[0]; while (cond) p = p + 4; */
391 if (object_size_type & 2)
393 osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
394 osi.stack = XNEWVEC (unsigned int, num_ssa_names);
395 osi.tos = osi.stack;
396 osi.pass = 1;
397 /* collect_object_sizes_for is changing
398 osi.reexamine bitmap, so iterate over a copy. */
399 bitmap_copy (reexamine, osi.reexamine);
400 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
401 if (bitmap_bit_p (osi.reexamine, i))
402 check_for_plus_in_loops (&osi, ssa_name (i));
404 free (osi.depths);
405 osi.depths = NULL;
406 free (osi.stack);
407 osi.stack = NULL;
408 osi.tos = NULL;
413 osi.pass = 2;
414 osi.changed = false;
415 /* collect_object_sizes_for is changing
416 osi.reexamine bitmap, so iterate over a copy. */
417 bitmap_copy (reexamine, osi.reexamine);
418 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
419 if (bitmap_bit_p (osi.reexamine, i))
421 collect_object_sizes_for (&osi, ssa_name (i));
422 if (dump_file && (dump_flags & TDF_DETAILS))
424 fprintf (dump_file, "Reexamining ");
425 print_generic_expr (dump_file, ssa_name (i),
426 dump_flags);
427 fprintf (dump_file, "\n");
431 while (osi.changed);
433 BITMAP_FREE (reexamine);
435 EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
436 bitmap_set_bit (computed[object_size_type], i);
438 /* Debugging dumps. */
439 if (dump_file)
441 EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
442 if (object_sizes[object_size_type][i]
443 != unknown[object_size_type])
445 print_generic_expr (dump_file, ssa_name (i),
446 dump_flags);
447 fprintf (dump_file,
448 ": %s %sobject size "
449 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
450 (object_size_type & 2) ? "minimum" : "maximum",
451 (object_size_type & 1) ? "sub" : "",
452 object_sizes[object_size_type][i]);
456 BITMAP_FREE (osi.reexamine);
457 BITMAP_FREE (osi.visited);
460 return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
463 return unknown[object_size_type];
467 /* Compute object_sizes for PTR, defined to VALUE, which is not
468 a SSA_NAME. */
470 static void
471 expr_object_size (struct object_size_info *osi, tree ptr, tree value)
473 int object_size_type = osi->object_size_type;
474 unsigned int varno = SSA_NAME_VERSION (ptr);
475 unsigned HOST_WIDE_INT bytes;
477 gcc_assert (object_sizes[object_size_type][varno]
478 != unknown[object_size_type]);
479 gcc_assert (osi->pass == 0);
481 if (TREE_CODE (value) == WITH_SIZE_EXPR)
482 value = TREE_OPERAND (value, 0);
484 /* Pointer variables should have been handled by merge_object_sizes. */
485 gcc_assert (TREE_CODE (value) != SSA_NAME
486 || !POINTER_TYPE_P (TREE_TYPE (value)));
488 if (TREE_CODE (value) == ADDR_EXPR)
489 bytes = addr_object_size (value, object_size_type);
490 else if (TREE_CODE (value) == CALL_EXPR)
491 bytes = alloc_object_size (value, object_size_type);
492 else
493 bytes = unknown[object_size_type];
495 if ((object_size_type & 2) == 0)
497 if (object_sizes[object_size_type][varno] < bytes)
498 object_sizes[object_size_type][varno] = bytes;
500 else
502 if (object_sizes[object_size_type][varno] > bytes)
503 object_sizes[object_size_type][varno] = bytes;
508 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
509 the object size might need reexamination later. */
511 static bool
512 merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
513 unsigned HOST_WIDE_INT offset)
515 int object_size_type = osi->object_size_type;
516 unsigned int varno = SSA_NAME_VERSION (dest);
517 unsigned HOST_WIDE_INT orig_bytes;
519 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
520 return false;
521 if (offset >= offset_limit)
523 object_sizes[object_size_type][varno] = unknown[object_size_type];
524 return false;
527 if (osi->pass == 0)
528 collect_object_sizes_for (osi, orig);
530 orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
531 if (orig_bytes != unknown[object_size_type])
532 orig_bytes = (offset > orig_bytes)
533 ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset;
535 if ((object_size_type & 2) == 0)
537 if (object_sizes[object_size_type][varno] < orig_bytes)
539 object_sizes[object_size_type][varno] = orig_bytes;
540 osi->changed = true;
543 else
545 if (object_sizes[object_size_type][varno] > orig_bytes)
547 object_sizes[object_size_type][varno] = orig_bytes;
548 osi->changed = true;
551 return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
555 /* Compute object_sizes for PTR, defined to VALUE, which is
556 a POINTER_PLUS_EXPR. Return true if the object size might need reexamination
557 later. */
559 static bool
560 plus_expr_object_size (struct object_size_info *osi, tree var, tree value)
562 tree op0 = TREE_OPERAND (value, 0);
563 tree op1 = TREE_OPERAND (value, 1);
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) == POINTER_PLUS_EXPR);
570 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
571 return false;
573 /* Handle PTR + OFFSET here. */
574 if (TREE_CODE (op1) == INTEGER_CST
575 && (TREE_CODE (op0) == SSA_NAME
576 || TREE_CODE (op0) == ADDR_EXPR))
578 if (! host_integerp (op1, 1))
579 bytes = unknown[object_size_type];
580 else if (TREE_CODE (op0) == SSA_NAME)
581 return merge_object_sizes (osi, var, op0, tree_low_cst (op1, 1));
582 else
584 unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
586 bytes = compute_builtin_object_size (op0, object_size_type);
587 if (bytes == unknown[object_size_type])
589 else if (off > offset_limit)
590 bytes = unknown[object_size_type];
591 else if (off > bytes)
592 bytes = 0;
593 else
594 bytes -= off;
597 else
598 bytes = unknown[object_size_type];
600 if ((object_size_type & 2) == 0)
602 if (object_sizes[object_size_type][varno] < bytes)
603 object_sizes[object_size_type][varno] = bytes;
605 else
607 if (object_sizes[object_size_type][varno] > bytes)
608 object_sizes[object_size_type][varno] = bytes;
610 return false;
614 /* Compute object_sizes for PTR, defined to VALUE, which is
615 a COND_EXPR. Return true if the object size might need reexamination
616 later. */
618 static bool
619 cond_expr_object_size (struct object_size_info *osi, tree var, tree value)
621 tree then_, else_;
622 int object_size_type = osi->object_size_type;
623 unsigned int varno = SSA_NAME_VERSION (var);
624 bool reexamine = false;
626 gcc_assert (TREE_CODE (value) == COND_EXPR);
628 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
629 return false;
631 then_ = COND_EXPR_THEN (value);
632 else_ = COND_EXPR_ELSE (value);
634 if (TREE_CODE (then_) == SSA_NAME)
635 reexamine |= merge_object_sizes (osi, var, then_, 0);
636 else
637 expr_object_size (osi, var, then_);
639 if (TREE_CODE (else_) == SSA_NAME)
640 reexamine |= merge_object_sizes (osi, var, else_, 0);
641 else
642 expr_object_size (osi, var, else_);
644 return reexamine;
648 /* Compute object sizes for VAR.
649 For ADDR_EXPR an object size is the number of remaining bytes
650 to the end of the object (where what is considered an object depends on
651 OSI->object_size_type).
652 For allocation CALL_EXPR like malloc or calloc object size is the size
653 of the allocation.
654 For POINTER_PLUS_EXPR where second operand is a constant integer,
655 object size is object size of the first operand minus the constant.
656 If the constant is bigger than the number of remaining bytes until the
657 end of the object, object size is 0, but if it is instead a pointer
658 subtraction, object size is unknown[object_size_type].
659 To differentiate addition from subtraction, ADDR_EXPR returns
660 unknown[object_size_type] for all objects bigger than half of the address
661 space, and constants less than half of the address space are considered
662 addition, while bigger constants subtraction.
663 For a memcpy like CALL_EXPR that always returns one of its arguments, the
664 object size is object size of that argument.
665 Otherwise, object size is the maximum of object sizes of variables
666 that it might be set to. */
668 static void
669 collect_object_sizes_for (struct object_size_info *osi, tree var)
671 int object_size_type = osi->object_size_type;
672 unsigned int varno = SSA_NAME_VERSION (var);
673 tree stmt;
674 bool reexamine;
676 if (bitmap_bit_p (computed[object_size_type], varno))
677 return;
679 if (osi->pass == 0)
681 if (! bitmap_bit_p (osi->visited, varno))
683 bitmap_set_bit (osi->visited, varno);
684 object_sizes[object_size_type][varno]
685 = (object_size_type & 2) ? -1 : 0;
687 else
689 /* Found a dependency loop. Mark the variable for later
690 re-examination. */
691 bitmap_set_bit (osi->reexamine, varno);
692 if (dump_file && (dump_flags & TDF_DETAILS))
694 fprintf (dump_file, "Found a dependency loop at ");
695 print_generic_expr (dump_file, var, dump_flags);
696 fprintf (dump_file, "\n");
698 return;
702 if (dump_file && (dump_flags & TDF_DETAILS))
704 fprintf (dump_file, "Visiting use-def links for ");
705 print_generic_expr (dump_file, var, dump_flags);
706 fprintf (dump_file, "\n");
709 stmt = SSA_NAME_DEF_STMT (var);
710 reexamine = false;
712 switch (TREE_CODE (stmt))
714 case RETURN_EXPR:
715 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
716 stmt = TREE_OPERAND (stmt, 0);
717 /* FALLTHRU */
719 case GIMPLE_MODIFY_STMT:
721 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
722 STRIP_NOPS (rhs);
724 if (TREE_CODE (rhs) == CALL_EXPR)
726 arg = pass_through_call (rhs);
727 if (arg)
728 rhs = arg;
731 if (TREE_CODE (rhs) == SSA_NAME
732 && POINTER_TYPE_P (TREE_TYPE (rhs)))
733 reexamine = merge_object_sizes (osi, var, rhs, 0);
735 else if (TREE_CODE (rhs) == POINTER_PLUS_EXPR)
736 reexamine = plus_expr_object_size (osi, var, rhs);
738 else if (TREE_CODE (rhs) == COND_EXPR)
739 reexamine = cond_expr_object_size (osi, var, rhs);
741 else
742 expr_object_size (osi, var, rhs);
743 break;
746 case ASM_EXPR:
747 /* Pointers defined by __asm__ statements can point anywhere. */
748 object_sizes[object_size_type][varno] = unknown[object_size_type];
749 break;
751 case NOP_EXPR:
753 tree decl = SSA_NAME_VAR (var);
755 gcc_assert (IS_EMPTY_STMT (stmt));
757 if (TREE_CODE (decl) != PARM_DECL && DECL_INITIAL (decl))
758 expr_object_size (osi, var, DECL_INITIAL (decl));
759 else
760 expr_object_size (osi, var, decl);
762 break;
764 case PHI_NODE:
766 int i;
768 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
770 tree rhs = PHI_ARG_DEF (stmt, i);
772 if (object_sizes[object_size_type][varno]
773 == unknown[object_size_type])
774 break;
776 if (TREE_CODE (rhs) == SSA_NAME)
777 reexamine |= merge_object_sizes (osi, var, rhs, 0);
778 else if (osi->pass == 0)
779 expr_object_size (osi, var, rhs);
781 break;
783 default:
784 gcc_unreachable ();
787 if (! reexamine
788 || object_sizes[object_size_type][varno] == unknown[object_size_type])
790 bitmap_set_bit (computed[object_size_type], varno);
791 bitmap_clear_bit (osi->reexamine, varno);
793 else
795 bitmap_set_bit (osi->reexamine, varno);
796 if (dump_file && (dump_flags & TDF_DETAILS))
798 fprintf (dump_file, "Need to reexamine ");
799 print_generic_expr (dump_file, var, dump_flags);
800 fprintf (dump_file, "\n");
806 /* Helper function for check_for_plus_in_loops. Called recursively
807 to detect loops. */
809 static void
810 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
811 unsigned int depth)
813 tree stmt = SSA_NAME_DEF_STMT (var);
814 unsigned int varno = SSA_NAME_VERSION (var);
816 if (osi->depths[varno])
818 if (osi->depths[varno] != depth)
820 unsigned int *sp;
822 /* Found a loop involving pointer addition. */
823 for (sp = osi->tos; sp > osi->stack; )
825 --sp;
826 bitmap_clear_bit (osi->reexamine, *sp);
827 bitmap_set_bit (computed[osi->object_size_type], *sp);
828 object_sizes[osi->object_size_type][*sp] = 0;
829 if (*sp == varno)
830 break;
833 return;
835 else if (! bitmap_bit_p (osi->reexamine, varno))
836 return;
838 osi->depths[varno] = depth;
839 *osi->tos++ = varno;
841 switch (TREE_CODE (stmt))
843 case RETURN_EXPR:
844 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
845 stmt = TREE_OPERAND (stmt, 0);
846 /* FALLTHRU */
848 case GIMPLE_MODIFY_STMT:
850 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
851 STRIP_NOPS (rhs);
853 if (TREE_CODE (rhs) == CALL_EXPR)
855 arg = pass_through_call (rhs);
856 if (arg)
857 rhs = arg;
860 if (TREE_CODE (rhs) == SSA_NAME)
861 check_for_plus_in_loops_1 (osi, rhs, depth);
862 else if (TREE_CODE (rhs) == POINTER_PLUS_EXPR)
864 tree op0 = TREE_OPERAND (rhs, 0);
865 tree op1 = TREE_OPERAND (rhs, 1);
866 tree cst, basevar;
868 basevar = op0;
869 cst = op1;
870 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
872 check_for_plus_in_loops_1 (osi, basevar,
873 depth + !integer_zerop (cst));
875 else
876 gcc_unreachable ();
877 break;
879 case PHI_NODE:
881 int i;
883 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
885 tree rhs = PHI_ARG_DEF (stmt, i);
887 if (TREE_CODE (rhs) == SSA_NAME)
888 check_for_plus_in_loops_1 (osi, rhs, depth);
890 break;
892 default:
893 gcc_unreachable ();
896 osi->depths[varno] = 0;
897 osi->tos--;
901 /* Check if some pointer we are computing object size of is being increased
902 within a loop. If yes, assume all the SSA variables participating in
903 that loop have minimum object sizes 0. */
905 static void
906 check_for_plus_in_loops (struct object_size_info *osi, tree var)
908 tree stmt = SSA_NAME_DEF_STMT (var);
910 switch (TREE_CODE (stmt))
912 case RETURN_EXPR:
913 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
914 stmt = TREE_OPERAND (stmt, 0);
915 /* FALLTHRU */
917 case GIMPLE_MODIFY_STMT:
919 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
920 STRIP_NOPS (rhs);
922 if (TREE_CODE (rhs) == CALL_EXPR)
924 arg = pass_through_call (rhs);
925 if (arg)
926 rhs = arg;
929 if (TREE_CODE (rhs) == POINTER_PLUS_EXPR)
931 tree op0 = TREE_OPERAND (rhs, 0);
932 tree op1 = TREE_OPERAND (rhs, 1);
933 tree cst, basevar;
935 basevar = op0;
936 cst = op1;
937 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
939 if (integer_zerop (cst))
940 break;
942 osi->depths[SSA_NAME_VERSION (basevar)] = 1;
943 *osi->tos++ = SSA_NAME_VERSION (basevar);
944 check_for_plus_in_loops_1 (osi, var, 2);
945 osi->depths[SSA_NAME_VERSION (basevar)] = 0;
946 osi->tos--;
948 break;
950 default:
951 break;
956 /* Initialize data structures for the object size computation. */
958 void
959 init_object_sizes (void)
961 int object_size_type;
963 if (object_sizes[0])
964 return;
966 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
968 object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names);
969 computed[object_size_type] = BITMAP_ALLOC (NULL);
972 init_offset_limit ();
976 /* Destroy data structures after the object size computation. */
978 void
979 fini_object_sizes (void)
981 int object_size_type;
983 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
985 free (object_sizes[object_size_type]);
986 BITMAP_FREE (computed[object_size_type]);
987 object_sizes[object_size_type] = NULL;
992 /* Simple pass to optimize all __builtin_object_size () builtins. */
994 static unsigned int
995 compute_object_sizes (void)
997 basic_block bb;
998 FOR_EACH_BB (bb)
1000 block_stmt_iterator i;
1001 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
1003 tree *stmtp = bsi_stmt_ptr (i);
1004 tree call = get_rhs (*stmtp);
1005 tree callee, result;
1007 if (!call || TREE_CODE (call) != CALL_EXPR)
1008 continue;
1010 callee = get_callee_fndecl (call);
1011 if (!callee
1012 || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
1013 || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE)
1014 continue;
1016 init_object_sizes ();
1017 result = fold_call_expr (call, false);
1018 if (!result)
1020 if (call_expr_nargs (call) == 2
1021 && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (call, 0))))
1023 tree ost = CALL_EXPR_ARG (call, 1);
1025 if (host_integerp (ost, 1))
1027 unsigned HOST_WIDE_INT object_size_type
1028 = tree_low_cst (ost, 1);
1030 if (object_size_type < 2)
1031 result = fold_convert (size_type_node,
1032 integer_minus_one_node);
1033 else if (object_size_type < 4)
1034 result = size_zero_node;
1038 if (!result)
1039 continue;
1042 if (dump_file && (dump_flags & TDF_DETAILS))
1044 fprintf (dump_file, "Simplified\n ");
1045 print_generic_stmt (dump_file, *stmtp, dump_flags);
1048 if (!set_rhs (stmtp, result))
1049 gcc_unreachable ();
1050 update_stmt (*stmtp);
1052 if (dump_file && (dump_flags & TDF_DETAILS))
1054 fprintf (dump_file, "to\n ");
1055 print_generic_stmt (dump_file, *stmtp, dump_flags);
1056 fprintf (dump_file, "\n");
1061 fini_object_sizes ();
1062 return 0;
1065 struct gimple_opt_pass pass_object_sizes =
1068 GIMPLE_PASS,
1069 "objsz", /* name */
1070 NULL, /* gate */
1071 compute_object_sizes, /* execute */
1072 NULL, /* sub */
1073 NULL, /* next */
1074 0, /* static_pass_number */
1075 0, /* tv_id */
1076 PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */
1077 0, /* properties_provided */
1078 0, /* properties_destroyed */
1079 0, /* todo_flags_start */
1080 TODO_dump_func | TODO_verify_ssa /* todo_flags_finish */