2007-03-01 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / tree-object-size.c
blobf1852ca5a7ba7357cad581cf2bc3232ea8e122ea
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, bytes = NULL_TREE;
233 gcc_assert (TREE_CODE (call) == CALL_EXPR);
235 callee = get_callee_fndecl (call);
236 if (callee
237 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
238 switch (DECL_FUNCTION_CODE (callee))
240 case BUILT_IN_MALLOC:
241 case BUILT_IN_ALLOCA:
242 if (call_expr_nargs (call) == 1
243 && TREE_CODE (CALL_EXPR_ARG (call, 0)) == INTEGER_CST)
244 bytes = fold_convert (sizetype, CALL_EXPR_ARG (call, 0));
245 break;
247 case BUILT_IN_REALLOC:
248 if (call_expr_nargs (call) == 2
249 && TREE_CODE (CALL_EXPR_ARG (call, 1)) == INTEGER_CST)
250 bytes = fold_convert (sizetype, CALL_EXPR_ARG (call, 1));
251 break;
253 case BUILT_IN_CALLOC:
254 if (call_expr_nargs (call) == 2
255 && TREE_CODE (CALL_EXPR_ARG (call, 0)) == INTEGER_CST
256 && TREE_CODE (CALL_EXPR_ARG (call, 1)) == INTEGER_CST)
257 bytes = size_binop (MULT_EXPR,
258 fold_convert (sizetype, CALL_EXPR_ARG (call, 0)),
259 fold_convert (sizetype, CALL_EXPR_ARG (call, 1)));
260 break;
261 default:
262 break;
265 if (bytes && host_integerp (bytes, 1))
266 return tree_low_cst (bytes, 1);
268 return unknown[object_size_type];
272 /* If object size is propagated from one of function's arguments directly
273 to its return value, return that argument for CALL_EXPR CALL.
274 Otherwise return NULL. */
276 static tree
277 pass_through_call (tree call)
279 tree callee = get_callee_fndecl (call);
281 if (callee
282 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
283 switch (DECL_FUNCTION_CODE (callee))
285 case BUILT_IN_MEMCPY:
286 case BUILT_IN_MEMMOVE:
287 case BUILT_IN_MEMSET:
288 case BUILT_IN_STRCPY:
289 case BUILT_IN_STRNCPY:
290 case BUILT_IN_STRCAT:
291 case BUILT_IN_STRNCAT:
292 case BUILT_IN_MEMCPY_CHK:
293 case BUILT_IN_MEMMOVE_CHK:
294 case BUILT_IN_MEMSET_CHK:
295 case BUILT_IN_STRCPY_CHK:
296 case BUILT_IN_STRNCPY_CHK:
297 case BUILT_IN_STRCAT_CHK:
298 case BUILT_IN_STRNCAT_CHK:
299 if (call_expr_nargs (call) >= 1)
300 return CALL_EXPR_ARG (call, 0);
301 break;
302 default:
303 break;
306 return NULL_TREE;
310 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
311 second argument from __builtin_object_size. */
313 unsigned HOST_WIDE_INT
314 compute_builtin_object_size (tree ptr, int object_size_type)
316 gcc_assert (object_size_type >= 0 && object_size_type <= 3);
318 if (! offset_limit)
319 init_offset_limit ();
321 if (TREE_CODE (ptr) == ADDR_EXPR)
322 return addr_object_size (ptr, object_size_type);
323 else if (TREE_CODE (ptr) == CALL_EXPR)
325 tree arg = pass_through_call (ptr);
327 if (arg)
328 return compute_builtin_object_size (arg, object_size_type);
329 else
330 return alloc_object_size (ptr, object_size_type);
332 else if (TREE_CODE (ptr) == SSA_NAME
333 && POINTER_TYPE_P (TREE_TYPE (ptr))
334 && object_sizes[object_size_type] != NULL)
336 if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
338 struct object_size_info osi;
339 bitmap_iterator bi;
340 unsigned int i;
342 if (dump_file)
344 fprintf (dump_file, "Computing %s %sobject size for ",
345 (object_size_type & 2) ? "minimum" : "maximum",
346 (object_size_type & 1) ? "sub" : "");
347 print_generic_expr (dump_file, ptr, dump_flags);
348 fprintf (dump_file, ":\n");
351 osi.visited = BITMAP_ALLOC (NULL);
352 osi.reexamine = BITMAP_ALLOC (NULL);
353 osi.object_size_type = object_size_type;
354 osi.depths = NULL;
355 osi.stack = NULL;
356 osi.tos = NULL;
358 /* First pass: walk UD chains, compute object sizes that
359 can be computed. osi.reexamine bitmap at the end will
360 contain what variables were found in dependency cycles
361 and therefore need to be reexamined. */
362 osi.pass = 0;
363 osi.changed = false;
364 collect_object_sizes_for (&osi, ptr);
366 /* Second pass: keep recomputing object sizes of variables
367 that need reexamination, until no object sizes are
368 increased or all object sizes are computed. */
369 if (! bitmap_empty_p (osi.reexamine))
371 bitmap reexamine = BITMAP_ALLOC (NULL);
373 /* If looking for minimum instead of maximum object size,
374 detect cases where a pointer is increased in a loop.
375 Although even without this detection pass 2 would eventually
376 terminate, it could take a long time. If a pointer is
377 increasing this way, we need to assume 0 object size.
378 E.g. p = &buf[0]; while (cond) p = p + 4; */
379 if (object_size_type & 2)
381 osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
382 osi.stack = XNEWVEC (unsigned int, num_ssa_names);
383 osi.tos = osi.stack;
384 osi.pass = 1;
385 /* collect_object_sizes_for is changing
386 osi.reexamine bitmap, so iterate over a copy. */
387 bitmap_copy (reexamine, osi.reexamine);
388 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
389 if (bitmap_bit_p (osi.reexamine, i))
390 check_for_plus_in_loops (&osi, ssa_name (i));
392 free (osi.depths);
393 osi.depths = NULL;
394 free (osi.stack);
395 osi.stack = NULL;
396 osi.tos = NULL;
401 osi.pass = 2;
402 osi.changed = false;
403 /* collect_object_sizes_for is changing
404 osi.reexamine bitmap, so iterate over a copy. */
405 bitmap_copy (reexamine, osi.reexamine);
406 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
407 if (bitmap_bit_p (osi.reexamine, i))
409 collect_object_sizes_for (&osi, ssa_name (i));
410 if (dump_file && (dump_flags & TDF_DETAILS))
412 fprintf (dump_file, "Reexamining ");
413 print_generic_expr (dump_file, ssa_name (i),
414 dump_flags);
415 fprintf (dump_file, "\n");
419 while (osi.changed);
421 BITMAP_FREE (reexamine);
423 EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
424 bitmap_set_bit (computed[object_size_type], i);
426 /* Debugging dumps. */
427 if (dump_file)
429 EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
430 if (object_sizes[object_size_type][i]
431 != unknown[object_size_type])
433 print_generic_expr (dump_file, ssa_name (i),
434 dump_flags);
435 fprintf (dump_file,
436 ": %s %sobject size "
437 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
438 (object_size_type & 2) ? "minimum" : "maximum",
439 (object_size_type & 1) ? "sub" : "",
440 object_sizes[object_size_type][i]);
444 BITMAP_FREE (osi.reexamine);
445 BITMAP_FREE (osi.visited);
448 return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
451 return unknown[object_size_type];
455 /* Compute object_sizes for PTR, defined to VALUE, which is not
456 a SSA_NAME. */
458 static void
459 expr_object_size (struct object_size_info *osi, tree ptr, tree value)
461 int object_size_type = osi->object_size_type;
462 unsigned int varno = SSA_NAME_VERSION (ptr);
463 unsigned HOST_WIDE_INT bytes;
465 gcc_assert (object_sizes[object_size_type][varno]
466 != unknown[object_size_type]);
467 gcc_assert (osi->pass == 0);
469 if (TREE_CODE (value) == WITH_SIZE_EXPR)
470 value = TREE_OPERAND (value, 0);
472 /* Pointer variables should have been handled by merge_object_sizes. */
473 gcc_assert (TREE_CODE (value) != SSA_NAME
474 || !POINTER_TYPE_P (TREE_TYPE (value)));
476 if (TREE_CODE (value) == ADDR_EXPR)
477 bytes = addr_object_size (value, object_size_type);
478 else if (TREE_CODE (value) == CALL_EXPR)
479 bytes = alloc_object_size (value, object_size_type);
480 else
481 bytes = unknown[object_size_type];
483 if ((object_size_type & 2) == 0)
485 if (object_sizes[object_size_type][varno] < bytes)
486 object_sizes[object_size_type][varno] = bytes;
488 else
490 if (object_sizes[object_size_type][varno] > bytes)
491 object_sizes[object_size_type][varno] = bytes;
496 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
497 the object size might need reexamination later. */
499 static bool
500 merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
501 unsigned HOST_WIDE_INT offset)
503 int object_size_type = osi->object_size_type;
504 unsigned int varno = SSA_NAME_VERSION (dest);
505 unsigned HOST_WIDE_INT orig_bytes;
507 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
508 return false;
509 if (offset >= offset_limit)
511 object_sizes[object_size_type][varno] = unknown[object_size_type];
512 return false;
515 if (osi->pass == 0)
516 collect_object_sizes_for (osi, orig);
518 orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
519 if (orig_bytes != unknown[object_size_type])
520 orig_bytes = (offset > orig_bytes)
521 ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset;
523 if ((object_size_type & 2) == 0)
525 if (object_sizes[object_size_type][varno] < orig_bytes)
527 object_sizes[object_size_type][varno] = orig_bytes;
528 osi->changed = true;
531 else
533 if (object_sizes[object_size_type][varno] > orig_bytes)
535 object_sizes[object_size_type][varno] = orig_bytes;
536 osi->changed = true;
539 return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
543 /* Compute object_sizes for PTR, defined to VALUE, which is
544 a PLUS_EXPR. Return true if the object size might need reexamination
545 later. */
547 static bool
548 plus_expr_object_size (struct object_size_info *osi, tree var, tree value)
550 tree op0 = TREE_OPERAND (value, 0);
551 tree op1 = TREE_OPERAND (value, 1);
552 bool ptr1_p = POINTER_TYPE_P (TREE_TYPE (op0))
553 && TREE_CODE (op0) != INTEGER_CST;
554 bool ptr2_p = POINTER_TYPE_P (TREE_TYPE (op1))
555 && TREE_CODE (op1) != INTEGER_CST;
556 int object_size_type = osi->object_size_type;
557 unsigned int varno = SSA_NAME_VERSION (var);
558 unsigned HOST_WIDE_INT bytes;
560 gcc_assert (TREE_CODE (value) == PLUS_EXPR);
562 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
563 return false;
565 /* Swap operands if needed. */
566 if (ptr2_p && !ptr1_p)
568 tree tem = op0;
569 op0 = op1;
570 op1 = tem;
571 ptr1_p = true;
572 ptr2_p = false;
575 /* Handle PTR + OFFSET here. */
576 if (ptr1_p
577 && !ptr2_p
578 && TREE_CODE (op1) == INTEGER_CST
579 && (TREE_CODE (op0) == SSA_NAME
580 || TREE_CODE (op0) == ADDR_EXPR))
582 if (! host_integerp (op1, 1))
583 bytes = unknown[object_size_type];
584 else if (TREE_CODE (op0) == SSA_NAME)
585 return merge_object_sizes (osi, var, op0, tree_low_cst (op1, 1));
586 else
588 unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
590 bytes = compute_builtin_object_size (op0, object_size_type);
591 if (off > offset_limit)
592 bytes = unknown[object_size_type];
593 else if (off > bytes)
594 bytes = 0;
595 else
596 bytes -= off;
599 else
600 bytes = unknown[object_size_type];
602 if ((object_size_type & 2) == 0)
604 if (object_sizes[object_size_type][varno] < bytes)
605 object_sizes[object_size_type][varno] = bytes;
607 else
609 if (object_sizes[object_size_type][varno] > bytes)
610 object_sizes[object_size_type][varno] = bytes;
612 return false;
616 /* Compute object_sizes for PTR, defined to VALUE, which is
617 a COND_EXPR. Return true if the object size might need reexamination
618 later. */
620 static bool
621 cond_expr_object_size (struct object_size_info *osi, tree var, tree value)
623 tree then_, else_;
624 int object_size_type = osi->object_size_type;
625 unsigned int varno = SSA_NAME_VERSION (var);
626 bool reexamine = false;
628 gcc_assert (TREE_CODE (value) == COND_EXPR);
630 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
631 return false;
633 then_ = COND_EXPR_THEN (value);
634 else_ = COND_EXPR_ELSE (value);
636 if (TREE_CODE (then_) == SSA_NAME)
637 reexamine |= merge_object_sizes (osi, var, then_, 0);
638 else
639 expr_object_size (osi, var, then_);
641 if (TREE_CODE (else_) == SSA_NAME)
642 reexamine |= merge_object_sizes (osi, var, else_, 0);
643 else
644 expr_object_size (osi, var, else_);
646 return reexamine;
650 /* Compute object sizes for VAR.
651 For ADDR_EXPR an object size is the number of remaining bytes
652 to the end of the object (where what is considered an object depends on
653 OSI->object_size_type).
654 For allocation CALL_EXPR like malloc or calloc object size is the size
655 of the allocation.
656 For pointer PLUS_EXPR where second operand is a constant integer,
657 object size is object size of the first operand minus the constant.
658 If the constant is bigger than the number of remaining bytes until the
659 end of the object, object size is 0, but if it is instead a pointer
660 subtraction, object size is unknown[object_size_type].
661 To differentiate addition from subtraction, ADDR_EXPR returns
662 unknown[object_size_type] for all objects bigger than half of the address
663 space, and constants less than half of the address space are considered
664 addition, while bigger constants subtraction.
665 For a memcpy like CALL_EXPR that always returns one of its arguments, the
666 object size is object size of that argument.
667 Otherwise, object size is the maximum of object sizes of variables
668 that it might be set to. */
670 static void
671 collect_object_sizes_for (struct object_size_info *osi, tree var)
673 int object_size_type = osi->object_size_type;
674 unsigned int varno = SSA_NAME_VERSION (var);
675 tree stmt;
676 bool reexamine;
678 if (bitmap_bit_p (computed[object_size_type], varno))
679 return;
681 if (osi->pass == 0)
683 if (! bitmap_bit_p (osi->visited, varno))
685 bitmap_set_bit (osi->visited, varno);
686 object_sizes[object_size_type][varno]
687 = (object_size_type & 2) ? -1 : 0;
689 else
691 /* Found a dependency loop. Mark the variable for later
692 re-examination. */
693 bitmap_set_bit (osi->reexamine, varno);
694 if (dump_file && (dump_flags & TDF_DETAILS))
696 fprintf (dump_file, "Found a dependency loop at ");
697 print_generic_expr (dump_file, var, dump_flags);
698 fprintf (dump_file, "\n");
700 return;
704 if (dump_file && (dump_flags & TDF_DETAILS))
706 fprintf (dump_file, "Visiting use-def links for ");
707 print_generic_expr (dump_file, var, dump_flags);
708 fprintf (dump_file, "\n");
711 stmt = SSA_NAME_DEF_STMT (var);
712 reexamine = false;
714 switch (TREE_CODE (stmt))
716 case RETURN_EXPR:
717 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
718 stmt = TREE_OPERAND (stmt, 0);
719 /* FALLTHRU */
721 case GIMPLE_MODIFY_STMT:
723 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
724 STRIP_NOPS (rhs);
726 if (TREE_CODE (rhs) == CALL_EXPR)
728 arg = pass_through_call (rhs);
729 if (arg)
730 rhs = arg;
733 if (TREE_CODE (rhs) == SSA_NAME
734 && POINTER_TYPE_P (TREE_TYPE (rhs)))
735 reexamine = merge_object_sizes (osi, var, rhs, 0);
737 else if (TREE_CODE (rhs) == PLUS_EXPR)
738 reexamine = plus_expr_object_size (osi, var, rhs);
740 else if (TREE_CODE (rhs) == COND_EXPR)
741 reexamine = cond_expr_object_size (osi, var, rhs);
743 else
744 expr_object_size (osi, var, rhs);
745 break;
748 case ASM_EXPR:
749 /* Pointers defined by __asm__ statements can point anywhere. */
750 object_sizes[object_size_type][varno] = unknown[object_size_type];
751 break;
753 case NOP_EXPR:
755 tree decl = SSA_NAME_VAR (var);
757 gcc_assert (IS_EMPTY_STMT (stmt));
759 if (TREE_CODE (decl) != PARM_DECL && DECL_INITIAL (decl))
760 expr_object_size (osi, var, DECL_INITIAL (decl));
761 else
762 expr_object_size (osi, var, decl);
764 break;
766 case PHI_NODE:
768 int i;
770 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
772 tree rhs = PHI_ARG_DEF (stmt, i);
774 if (object_sizes[object_size_type][varno]
775 == unknown[object_size_type])
776 break;
778 if (TREE_CODE (rhs) == SSA_NAME)
779 reexamine |= merge_object_sizes (osi, var, rhs, 0);
780 else if (osi->pass == 0)
781 expr_object_size (osi, var, rhs);
783 break;
785 default:
786 gcc_unreachable ();
789 if (! reexamine
790 || object_sizes[object_size_type][varno] == unknown[object_size_type])
792 bitmap_set_bit (computed[object_size_type], varno);
793 bitmap_clear_bit (osi->reexamine, varno);
795 else
797 bitmap_set_bit (osi->reexamine, varno);
798 if (dump_file && (dump_flags & TDF_DETAILS))
800 fprintf (dump_file, "Need to reexamine ");
801 print_generic_expr (dump_file, var, dump_flags);
802 fprintf (dump_file, "\n");
808 /* Helper function for check_for_plus_in_loops. Called recursively
809 to detect loops. */
811 static void
812 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
813 unsigned int depth)
815 tree stmt = SSA_NAME_DEF_STMT (var);
816 unsigned int varno = SSA_NAME_VERSION (var);
818 if (osi->depths[varno])
820 if (osi->depths[varno] != depth)
822 unsigned int *sp;
824 /* Found a loop involving pointer addition. */
825 for (sp = osi->tos; sp > osi->stack; )
827 --sp;
828 bitmap_clear_bit (osi->reexamine, *sp);
829 bitmap_set_bit (computed[osi->object_size_type], *sp);
830 object_sizes[osi->object_size_type][*sp] = 0;
831 if (*sp == varno)
832 break;
835 return;
837 else if (! bitmap_bit_p (osi->reexamine, varno))
838 return;
840 osi->depths[varno] = depth;
841 *osi->tos++ = varno;
843 switch (TREE_CODE (stmt))
845 case RETURN_EXPR:
846 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
847 stmt = TREE_OPERAND (stmt, 0);
848 /* FALLTHRU */
850 case GIMPLE_MODIFY_STMT:
852 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
853 STRIP_NOPS (rhs);
855 if (TREE_CODE (rhs) == CALL_EXPR)
857 arg = pass_through_call (rhs);
858 if (arg)
859 rhs = arg;
862 if (TREE_CODE (rhs) == SSA_NAME)
863 check_for_plus_in_loops_1 (osi, rhs, depth);
864 else if (TREE_CODE (rhs) == PLUS_EXPR)
866 tree op0 = TREE_OPERAND (rhs, 0);
867 tree op1 = TREE_OPERAND (rhs, 1);
868 tree cst, basevar;
870 if (TREE_CODE (op0) == SSA_NAME)
872 basevar = op0;
873 cst = op1;
875 else
877 basevar = op1;
878 cst = op0;
879 gcc_assert (TREE_CODE (basevar) == SSA_NAME);
881 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
883 check_for_plus_in_loops_1 (osi, basevar,
884 depth + !integer_zerop (cst));
886 else
887 gcc_unreachable ();
888 break;
890 case PHI_NODE:
892 int i;
894 for (i = 0; i < PHI_NUM_ARGS (stmt); i++)
896 tree rhs = PHI_ARG_DEF (stmt, i);
898 if (TREE_CODE (rhs) == SSA_NAME)
899 check_for_plus_in_loops_1 (osi, rhs, depth);
901 break;
903 default:
904 gcc_unreachable ();
907 osi->depths[varno] = 0;
908 osi->tos--;
912 /* Check if some pointer we are computing object size of is being increased
913 within a loop. If yes, assume all the SSA variables participating in
914 that loop have minimum object sizes 0. */
916 static void
917 check_for_plus_in_loops (struct object_size_info *osi, tree var)
919 tree stmt = SSA_NAME_DEF_STMT (var);
921 switch (TREE_CODE (stmt))
923 case RETURN_EXPR:
924 gcc_assert (TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT);
925 stmt = TREE_OPERAND (stmt, 0);
926 /* FALLTHRU */
928 case GIMPLE_MODIFY_STMT:
930 tree rhs = GIMPLE_STMT_OPERAND (stmt, 1), arg;
931 STRIP_NOPS (rhs);
933 if (TREE_CODE (rhs) == CALL_EXPR)
935 arg = pass_through_call (rhs);
936 if (arg)
937 rhs = arg;
940 if (TREE_CODE (rhs) == PLUS_EXPR)
942 tree op0 = TREE_OPERAND (rhs, 0);
943 tree op1 = TREE_OPERAND (rhs, 1);
944 tree cst, basevar;
946 if (TREE_CODE (op0) == SSA_NAME)
948 basevar = op0;
949 cst = op1;
951 else
953 basevar = op1;
954 cst = op0;
955 gcc_assert (TREE_CODE (basevar) == SSA_NAME);
957 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
959 if (integer_zerop (cst))
960 break;
962 osi->depths[SSA_NAME_VERSION (basevar)] = 1;
963 *osi->tos++ = SSA_NAME_VERSION (basevar);
964 check_for_plus_in_loops_1 (osi, var, 2);
965 osi->depths[SSA_NAME_VERSION (basevar)] = 0;
966 osi->tos--;
968 break;
970 default:
971 break;
976 /* Initialize data structures for the object size computation. */
978 void
979 init_object_sizes (void)
981 int object_size_type;
983 if (object_sizes[0])
984 return;
986 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
988 object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names);
989 computed[object_size_type] = BITMAP_ALLOC (NULL);
992 init_offset_limit ();
996 /* Destroy data structures after the object size computation. */
998 void
999 fini_object_sizes (void)
1001 int object_size_type;
1003 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1005 free (object_sizes[object_size_type]);
1006 BITMAP_FREE (computed[object_size_type]);
1007 object_sizes[object_size_type] = NULL;
1012 /* Simple pass to optimize all __builtin_object_size () builtins. */
1014 static unsigned int
1015 compute_object_sizes (void)
1017 basic_block bb;
1018 FOR_EACH_BB (bb)
1020 block_stmt_iterator i;
1021 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
1023 tree *stmtp = bsi_stmt_ptr (i);
1024 tree call = get_rhs (*stmtp);
1025 tree callee, result;
1027 if (!call || TREE_CODE (call) != CALL_EXPR)
1028 continue;
1030 callee = get_callee_fndecl (call);
1031 if (!callee
1032 || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
1033 || DECL_FUNCTION_CODE (callee) != BUILT_IN_OBJECT_SIZE)
1034 continue;
1036 init_object_sizes ();
1037 result = fold_call_expr (call, false);
1038 if (!result)
1040 if (call_expr_nargs (call) == 2
1041 && POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (call, 0))))
1043 tree ost = CALL_EXPR_ARG (call, 1);
1045 if (host_integerp (ost, 1))
1047 unsigned HOST_WIDE_INT object_size_type
1048 = tree_low_cst (ost, 1);
1050 if (object_size_type < 2)
1051 result = fold_convert (size_type_node,
1052 integer_minus_one_node);
1053 else if (object_size_type < 4)
1054 result = size_zero_node;
1058 if (!result)
1059 continue;
1062 if (dump_file && (dump_flags & TDF_DETAILS))
1064 fprintf (dump_file, "Simplified\n ");
1065 print_generic_stmt (dump_file, *stmtp, dump_flags);
1068 if (!set_rhs (stmtp, result))
1069 gcc_unreachable ();
1070 update_stmt (*stmtp);
1072 if (dump_file && (dump_flags & TDF_DETAILS))
1074 fprintf (dump_file, "to\n ");
1075 print_generic_stmt (dump_file, *stmtp, dump_flags);
1076 fprintf (dump_file, "\n");
1081 fini_object_sizes ();
1082 return 0;
1085 struct tree_opt_pass pass_object_sizes =
1087 "objsz", /* name */
1088 NULL, /* gate */
1089 compute_object_sizes, /* execute */
1090 NULL, /* sub */
1091 NULL, /* next */
1092 0, /* static_pass_number */
1093 0, /* tv_id */
1094 PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */
1095 0, /* properties_provided */
1096 0, /* properties_destroyed */
1097 0, /* todo_flags_start */
1098 TODO_dump_func | TODO_verify_ssa, /* todo_flags_finish */
1099 0 /* letter */