]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tree-object-size.c
Factor unrelated declarations out of tree.h.
[thirdparty/gcc.git] / gcc / tree-object-size.c
1 /* __builtin_object_size (ptr, object_size_type) computation
2 Copyright (C) 2004-2013 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "tree-object-size.h"
27 #include "diagnostic-core.h"
28 #include "gimple-pretty-print.h"
29 #include "bitmap.h"
30 #include "gimple.h"
31 #include "gimple-iterator.h"
32 #include "gimple-ssa.h"
33 #include "stringpool.h"
34 #include "tree-ssanames.h"
35 #include "tree-pass.h"
36 #include "tree-ssa-propagate.h"
37 #include "tree-phinodes.h"
38 #include "ssa-iterators.h"
39
40 struct object_size_info
41 {
42 int object_size_type;
43 bitmap visited, reexamine;
44 int pass;
45 bool changed;
46 unsigned int *depths;
47 unsigned int *stack, *tos;
48 };
49
50 static const unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 };
51
52 static tree compute_object_offset (const_tree, const_tree);
53 static unsigned HOST_WIDE_INT addr_object_size (struct object_size_info *,
54 const_tree, int);
55 static unsigned HOST_WIDE_INT alloc_object_size (const_gimple, int);
56 static tree pass_through_call (const_gimple);
57 static void collect_object_sizes_for (struct object_size_info *, tree);
58 static void expr_object_size (struct object_size_info *, tree, tree);
59 static bool merge_object_sizes (struct object_size_info *, tree, tree,
60 unsigned HOST_WIDE_INT);
61 static bool plus_stmt_object_size (struct object_size_info *, tree, gimple);
62 static bool cond_expr_object_size (struct object_size_info *, tree, gimple);
63 static unsigned int compute_object_sizes (void);
64 static void init_offset_limit (void);
65 static void check_for_plus_in_loops (struct object_size_info *, tree);
66 static void check_for_plus_in_loops_1 (struct object_size_info *, tree,
67 unsigned int);
68
69 /* object_sizes[0] is upper bound for number of bytes till the end of
70 the object.
71 object_sizes[1] is upper bound for number of bytes till the end of
72 the subobject (innermost array or field with address taken).
73 object_sizes[2] is lower bound for number of bytes till the end of
74 the object and object_sizes[3] lower bound for subobject. */
75 static unsigned HOST_WIDE_INT *object_sizes[4];
76
77 /* Bitmaps what object sizes have been computed already. */
78 static bitmap computed[4];
79
80 /* Maximum value of offset we consider to be addition. */
81 static unsigned HOST_WIDE_INT offset_limit;
82
83
84 /* Initialize OFFSET_LIMIT variable. */
85 static void
86 init_offset_limit (void)
87 {
88 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (sizetype)))
89 offset_limit = tree_to_uhwi (TYPE_MAX_VALUE (sizetype));
90 else
91 offset_limit = -1;
92 offset_limit /= 2;
93 }
94
95
96 /* Compute offset of EXPR within VAR. Return error_mark_node
97 if unknown. */
98
99 static tree
100 compute_object_offset (const_tree expr, const_tree var)
101 {
102 enum tree_code code = PLUS_EXPR;
103 tree base, off, t;
104
105 if (expr == var)
106 return size_zero_node;
107
108 switch (TREE_CODE (expr))
109 {
110 case COMPONENT_REF:
111 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
112 if (base == error_mark_node)
113 return base;
114
115 t = TREE_OPERAND (expr, 1);
116 off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
117 size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
118 / BITS_PER_UNIT));
119 break;
120
121 case REALPART_EXPR:
122 CASE_CONVERT:
123 case VIEW_CONVERT_EXPR:
124 case NON_LVALUE_EXPR:
125 return compute_object_offset (TREE_OPERAND (expr, 0), var);
126
127 case IMAGPART_EXPR:
128 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
129 if (base == error_mark_node)
130 return base;
131
132 off = TYPE_SIZE_UNIT (TREE_TYPE (expr));
133 break;
134
135 case ARRAY_REF:
136 base = compute_object_offset (TREE_OPERAND (expr, 0), var);
137 if (base == error_mark_node)
138 return base;
139
140 t = TREE_OPERAND (expr, 1);
141 if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
142 {
143 code = MINUS_EXPR;
144 t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
145 }
146 t = fold_convert (sizetype, t);
147 off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
148 break;
149
150 case MEM_REF:
151 gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR);
152 return double_int_to_tree (sizetype, mem_ref_offset (expr));
153
154 default:
155 return error_mark_node;
156 }
157
158 return size_binop (code, base, off);
159 }
160
161
162 /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR.
163 OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
164 If unknown, return unknown[object_size_type]. */
165
166 static unsigned HOST_WIDE_INT
167 addr_object_size (struct object_size_info *osi, const_tree ptr,
168 int object_size_type)
169 {
170 tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
171
172 gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
173
174 pt_var = TREE_OPERAND (ptr, 0);
175 while (handled_component_p (pt_var))
176 pt_var = TREE_OPERAND (pt_var, 0);
177
178 if (pt_var
179 && TREE_CODE (pt_var) == MEM_REF)
180 {
181 unsigned HOST_WIDE_INT sz;
182
183 if (!osi || (object_size_type & 1) != 0
184 || TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
185 {
186 sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
187 object_size_type & ~1);
188 }
189 else
190 {
191 tree var = TREE_OPERAND (pt_var, 0);
192 if (osi->pass == 0)
193 collect_object_sizes_for (osi, var);
194 if (bitmap_bit_p (computed[object_size_type],
195 SSA_NAME_VERSION (var)))
196 sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)];
197 else
198 sz = unknown[object_size_type];
199 }
200 if (sz != unknown[object_size_type])
201 {
202 double_int dsz = double_int::from_uhwi (sz) - mem_ref_offset (pt_var);
203 if (dsz.is_negative ())
204 sz = 0;
205 else if (dsz.fits_uhwi ())
206 sz = dsz.to_uhwi ();
207 else
208 sz = unknown[object_size_type];
209 }
210
211 if (sz != unknown[object_size_type] && sz < offset_limit)
212 pt_var_size = size_int (sz);
213 }
214 else if (pt_var
215 && DECL_P (pt_var)
216 && tree_fits_uhwi_p (DECL_SIZE_UNIT (pt_var))
217 && tree_to_uhwi (DECL_SIZE_UNIT (pt_var)) < offset_limit)
218 pt_var_size = DECL_SIZE_UNIT (pt_var);
219 else if (pt_var
220 && TREE_CODE (pt_var) == STRING_CST
221 && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
222 && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)))
223 && tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)))
224 < offset_limit)
225 pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
226 else
227 return unknown[object_size_type];
228
229 if (pt_var != TREE_OPERAND (ptr, 0))
230 {
231 tree var;
232
233 if (object_size_type & 1)
234 {
235 var = TREE_OPERAND (ptr, 0);
236
237 while (var != pt_var
238 && TREE_CODE (var) != BIT_FIELD_REF
239 && TREE_CODE (var) != COMPONENT_REF
240 && TREE_CODE (var) != ARRAY_REF
241 && TREE_CODE (var) != ARRAY_RANGE_REF
242 && TREE_CODE (var) != REALPART_EXPR
243 && TREE_CODE (var) != IMAGPART_EXPR)
244 var = TREE_OPERAND (var, 0);
245 if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
246 var = TREE_OPERAND (var, 0);
247 if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
248 || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var)))
249 || (pt_var_size
250 && tree_int_cst_lt (pt_var_size,
251 TYPE_SIZE_UNIT (TREE_TYPE (var)))))
252 var = pt_var;
253 else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF)
254 {
255 tree v = var;
256 /* For &X->fld, compute object size only if fld isn't the last
257 field, as struct { int i; char c[1]; } is often used instead
258 of flexible array member. */
259 while (v && v != pt_var)
260 switch (TREE_CODE (v))
261 {
262 case ARRAY_REF:
263 if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))
264 && TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST)
265 {
266 tree domain
267 = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0)));
268 if (domain
269 && TYPE_MAX_VALUE (domain)
270 && TREE_CODE (TYPE_MAX_VALUE (domain))
271 == INTEGER_CST
272 && tree_int_cst_lt (TREE_OPERAND (v, 1),
273 TYPE_MAX_VALUE (domain)))
274 {
275 v = NULL_TREE;
276 break;
277 }
278 }
279 v = TREE_OPERAND (v, 0);
280 break;
281 case REALPART_EXPR:
282 case IMAGPART_EXPR:
283 v = NULL_TREE;
284 break;
285 case COMPONENT_REF:
286 if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
287 {
288 v = NULL_TREE;
289 break;
290 }
291 while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
292 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
293 != UNION_TYPE
294 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
295 != QUAL_UNION_TYPE)
296 break;
297 else
298 v = TREE_OPERAND (v, 0);
299 if (TREE_CODE (v) == COMPONENT_REF
300 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
301 == RECORD_TYPE)
302 {
303 tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1));
304 for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain))
305 if (TREE_CODE (fld_chain) == FIELD_DECL)
306 break;
307
308 if (fld_chain)
309 {
310 v = NULL_TREE;
311 break;
312 }
313 v = TREE_OPERAND (v, 0);
314 }
315 while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
316 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
317 != UNION_TYPE
318 && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
319 != QUAL_UNION_TYPE)
320 break;
321 else
322 v = TREE_OPERAND (v, 0);
323 if (v != pt_var)
324 v = NULL_TREE;
325 else
326 v = pt_var;
327 break;
328 default:
329 v = pt_var;
330 break;
331 }
332 if (v == pt_var)
333 var = pt_var;
334 }
335 }
336 else
337 var = pt_var;
338
339 if (var != pt_var)
340 var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
341 else if (!pt_var_size)
342 return unknown[object_size_type];
343 else
344 var_size = pt_var_size;
345 bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
346 if (bytes != error_mark_node)
347 {
348 if (TREE_CODE (bytes) == INTEGER_CST
349 && tree_int_cst_lt (var_size, bytes))
350 bytes = size_zero_node;
351 else
352 bytes = size_binop (MINUS_EXPR, var_size, bytes);
353 }
354 if (var != pt_var
355 && pt_var_size
356 && TREE_CODE (pt_var) == MEM_REF
357 && bytes != error_mark_node)
358 {
359 tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var);
360 if (bytes2 != error_mark_node)
361 {
362 if (TREE_CODE (bytes2) == INTEGER_CST
363 && tree_int_cst_lt (pt_var_size, bytes2))
364 bytes2 = size_zero_node;
365 else
366 bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
367 bytes = size_binop (MIN_EXPR, bytes, bytes2);
368 }
369 }
370 }
371 else if (!pt_var_size)
372 return unknown[object_size_type];
373 else
374 bytes = pt_var_size;
375
376 if (tree_fits_uhwi_p (bytes))
377 return tree_to_uhwi (bytes);
378
379 return unknown[object_size_type];
380 }
381
382
383 /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL.
384 Handles various allocation calls. OBJECT_SIZE_TYPE is the second
385 argument from __builtin_object_size. If unknown, return
386 unknown[object_size_type]. */
387
388 static unsigned HOST_WIDE_INT
389 alloc_object_size (const_gimple call, int object_size_type)
390 {
391 tree callee, bytes = NULL_TREE;
392 tree alloc_size;
393 int arg1 = -1, arg2 = -1;
394
395 gcc_assert (is_gimple_call (call));
396
397 callee = gimple_call_fndecl (call);
398 if (!callee)
399 return unknown[object_size_type];
400
401 alloc_size = lookup_attribute ("alloc_size",
402 TYPE_ATTRIBUTES (TREE_TYPE (callee)));
403 if (alloc_size && TREE_VALUE (alloc_size))
404 {
405 tree p = TREE_VALUE (alloc_size);
406
407 arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1;
408 if (TREE_CHAIN (p))
409 arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
410 }
411
412 if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
413 switch (DECL_FUNCTION_CODE (callee))
414 {
415 case BUILT_IN_CALLOC:
416 arg2 = 1;
417 /* fall through */
418 case BUILT_IN_MALLOC:
419 case BUILT_IN_ALLOCA:
420 case BUILT_IN_ALLOCA_WITH_ALIGN:
421 arg1 = 0;
422 default:
423 break;
424 }
425
426 if (arg1 < 0 || arg1 >= (int)gimple_call_num_args (call)
427 || TREE_CODE (gimple_call_arg (call, arg1)) != INTEGER_CST
428 || (arg2 >= 0
429 && (arg2 >= (int)gimple_call_num_args (call)
430 || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST)))
431 return unknown[object_size_type];
432
433 if (arg2 >= 0)
434 bytes = size_binop (MULT_EXPR,
435 fold_convert (sizetype, gimple_call_arg (call, arg1)),
436 fold_convert (sizetype, gimple_call_arg (call, arg2)));
437 else if (arg1 >= 0)
438 bytes = fold_convert (sizetype, gimple_call_arg (call, arg1));
439
440 if (bytes && tree_fits_uhwi_p (bytes))
441 return tree_to_uhwi (bytes);
442
443 return unknown[object_size_type];
444 }
445
446
447 /* If object size is propagated from one of function's arguments directly
448 to its return value, return that argument for GIMPLE_CALL statement CALL.
449 Otherwise return NULL. */
450
451 static tree
452 pass_through_call (const_gimple call)
453 {
454 tree callee = gimple_call_fndecl (call);
455
456 if (callee
457 && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
458 switch (DECL_FUNCTION_CODE (callee))
459 {
460 case BUILT_IN_MEMCPY:
461 case BUILT_IN_MEMMOVE:
462 case BUILT_IN_MEMSET:
463 case BUILT_IN_STRCPY:
464 case BUILT_IN_STRNCPY:
465 case BUILT_IN_STRCAT:
466 case BUILT_IN_STRNCAT:
467 case BUILT_IN_MEMCPY_CHK:
468 case BUILT_IN_MEMMOVE_CHK:
469 case BUILT_IN_MEMSET_CHK:
470 case BUILT_IN_STRCPY_CHK:
471 case BUILT_IN_STRNCPY_CHK:
472 case BUILT_IN_STPNCPY_CHK:
473 case BUILT_IN_STRCAT_CHK:
474 case BUILT_IN_STRNCAT_CHK:
475 case BUILT_IN_ASSUME_ALIGNED:
476 if (gimple_call_num_args (call) >= 1)
477 return gimple_call_arg (call, 0);
478 break;
479 default:
480 break;
481 }
482
483 return NULL_TREE;
484 }
485
486
487 /* Compute __builtin_object_size value for PTR. OBJECT_SIZE_TYPE is the
488 second argument from __builtin_object_size. */
489
490 unsigned HOST_WIDE_INT
491 compute_builtin_object_size (tree ptr, int object_size_type)
492 {
493 gcc_assert (object_size_type >= 0 && object_size_type <= 3);
494
495 if (! offset_limit)
496 init_offset_limit ();
497
498 if (TREE_CODE (ptr) == ADDR_EXPR)
499 return addr_object_size (NULL, ptr, object_size_type);
500
501 if (TREE_CODE (ptr) == SSA_NAME
502 && POINTER_TYPE_P (TREE_TYPE (ptr))
503 && object_sizes[object_size_type] != NULL)
504 {
505 if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
506 {
507 struct object_size_info osi;
508 bitmap_iterator bi;
509 unsigned int i;
510
511 if (dump_file)
512 {
513 fprintf (dump_file, "Computing %s %sobject size for ",
514 (object_size_type & 2) ? "minimum" : "maximum",
515 (object_size_type & 1) ? "sub" : "");
516 print_generic_expr (dump_file, ptr, dump_flags);
517 fprintf (dump_file, ":\n");
518 }
519
520 osi.visited = BITMAP_ALLOC (NULL);
521 osi.reexamine = BITMAP_ALLOC (NULL);
522 osi.object_size_type = object_size_type;
523 osi.depths = NULL;
524 osi.stack = NULL;
525 osi.tos = NULL;
526
527 /* First pass: walk UD chains, compute object sizes that
528 can be computed. osi.reexamine bitmap at the end will
529 contain what variables were found in dependency cycles
530 and therefore need to be reexamined. */
531 osi.pass = 0;
532 osi.changed = false;
533 collect_object_sizes_for (&osi, ptr);
534
535 /* Second pass: keep recomputing object sizes of variables
536 that need reexamination, until no object sizes are
537 increased or all object sizes are computed. */
538 if (! bitmap_empty_p (osi.reexamine))
539 {
540 bitmap reexamine = BITMAP_ALLOC (NULL);
541
542 /* If looking for minimum instead of maximum object size,
543 detect cases where a pointer is increased in a loop.
544 Although even without this detection pass 2 would eventually
545 terminate, it could take a long time. If a pointer is
546 increasing this way, we need to assume 0 object size.
547 E.g. p = &buf[0]; while (cond) p = p + 4; */
548 if (object_size_type & 2)
549 {
550 osi.depths = XCNEWVEC (unsigned int, num_ssa_names);
551 osi.stack = XNEWVEC (unsigned int, num_ssa_names);
552 osi.tos = osi.stack;
553 osi.pass = 1;
554 /* collect_object_sizes_for is changing
555 osi.reexamine bitmap, so iterate over a copy. */
556 bitmap_copy (reexamine, osi.reexamine);
557 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
558 if (bitmap_bit_p (osi.reexamine, i))
559 check_for_plus_in_loops (&osi, ssa_name (i));
560
561 free (osi.depths);
562 osi.depths = NULL;
563 free (osi.stack);
564 osi.stack = NULL;
565 osi.tos = NULL;
566 }
567
568 do
569 {
570 osi.pass = 2;
571 osi.changed = false;
572 /* collect_object_sizes_for is changing
573 osi.reexamine bitmap, so iterate over a copy. */
574 bitmap_copy (reexamine, osi.reexamine);
575 EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)
576 if (bitmap_bit_p (osi.reexamine, i))
577 {
578 collect_object_sizes_for (&osi, ssa_name (i));
579 if (dump_file && (dump_flags & TDF_DETAILS))
580 {
581 fprintf (dump_file, "Reexamining ");
582 print_generic_expr (dump_file, ssa_name (i),
583 dump_flags);
584 fprintf (dump_file, "\n");
585 }
586 }
587 }
588 while (osi.changed);
589
590 BITMAP_FREE (reexamine);
591 }
592 EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)
593 bitmap_set_bit (computed[object_size_type], i);
594
595 /* Debugging dumps. */
596 if (dump_file)
597 {
598 EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)
599 if (object_sizes[object_size_type][i]
600 != unknown[object_size_type])
601 {
602 print_generic_expr (dump_file, ssa_name (i),
603 dump_flags);
604 fprintf (dump_file,
605 ": %s %sobject size "
606 HOST_WIDE_INT_PRINT_UNSIGNED "\n",
607 (object_size_type & 2) ? "minimum" : "maximum",
608 (object_size_type & 1) ? "sub" : "",
609 object_sizes[object_size_type][i]);
610 }
611 }
612
613 BITMAP_FREE (osi.reexamine);
614 BITMAP_FREE (osi.visited);
615 }
616
617 return object_sizes[object_size_type][SSA_NAME_VERSION (ptr)];
618 }
619
620 return unknown[object_size_type];
621 }
622
623 /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */
624
625 static void
626 expr_object_size (struct object_size_info *osi, tree ptr, tree value)
627 {
628 int object_size_type = osi->object_size_type;
629 unsigned int varno = SSA_NAME_VERSION (ptr);
630 unsigned HOST_WIDE_INT bytes;
631
632 gcc_assert (object_sizes[object_size_type][varno]
633 != unknown[object_size_type]);
634 gcc_assert (osi->pass == 0);
635
636 if (TREE_CODE (value) == WITH_SIZE_EXPR)
637 value = TREE_OPERAND (value, 0);
638
639 /* Pointer variables should have been handled by merge_object_sizes. */
640 gcc_assert (TREE_CODE (value) != SSA_NAME
641 || !POINTER_TYPE_P (TREE_TYPE (value)));
642
643 if (TREE_CODE (value) == ADDR_EXPR)
644 bytes = addr_object_size (osi, value, object_size_type);
645 else
646 bytes = unknown[object_size_type];
647
648 if ((object_size_type & 2) == 0)
649 {
650 if (object_sizes[object_size_type][varno] < bytes)
651 object_sizes[object_size_type][varno] = bytes;
652 }
653 else
654 {
655 if (object_sizes[object_size_type][varno] > bytes)
656 object_sizes[object_size_type][varno] = bytes;
657 }
658 }
659
660
661 /* Compute object_sizes for PTR, defined to the result of a call. */
662
663 static void
664 call_object_size (struct object_size_info *osi, tree ptr, gimple call)
665 {
666 int object_size_type = osi->object_size_type;
667 unsigned int varno = SSA_NAME_VERSION (ptr);
668 unsigned HOST_WIDE_INT bytes;
669
670 gcc_assert (is_gimple_call (call));
671
672 gcc_assert (object_sizes[object_size_type][varno]
673 != unknown[object_size_type]);
674 gcc_assert (osi->pass == 0);
675
676 bytes = alloc_object_size (call, object_size_type);
677
678 if ((object_size_type & 2) == 0)
679 {
680 if (object_sizes[object_size_type][varno] < bytes)
681 object_sizes[object_size_type][varno] = bytes;
682 }
683 else
684 {
685 if (object_sizes[object_size_type][varno] > bytes)
686 object_sizes[object_size_type][varno] = bytes;
687 }
688 }
689
690
691 /* Compute object_sizes for PTR, defined to an unknown value. */
692
693 static void
694 unknown_object_size (struct object_size_info *osi, tree ptr)
695 {
696 int object_size_type = osi->object_size_type;
697 unsigned int varno = SSA_NAME_VERSION (ptr);
698 unsigned HOST_WIDE_INT bytes;
699
700 gcc_assert (object_sizes[object_size_type][varno]
701 != unknown[object_size_type]);
702 gcc_assert (osi->pass == 0);
703
704 bytes = unknown[object_size_type];
705
706 if ((object_size_type & 2) == 0)
707 {
708 if (object_sizes[object_size_type][varno] < bytes)
709 object_sizes[object_size_type][varno] = bytes;
710 }
711 else
712 {
713 if (object_sizes[object_size_type][varno] > bytes)
714 object_sizes[object_size_type][varno] = bytes;
715 }
716 }
717
718
719 /* Merge object sizes of ORIG + OFFSET into DEST. Return true if
720 the object size might need reexamination later. */
721
722 static bool
723 merge_object_sizes (struct object_size_info *osi, tree dest, tree orig,
724 unsigned HOST_WIDE_INT offset)
725 {
726 int object_size_type = osi->object_size_type;
727 unsigned int varno = SSA_NAME_VERSION (dest);
728 unsigned HOST_WIDE_INT orig_bytes;
729
730 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
731 return false;
732 if (offset >= offset_limit)
733 {
734 object_sizes[object_size_type][varno] = unknown[object_size_type];
735 return false;
736 }
737
738 if (osi->pass == 0)
739 collect_object_sizes_for (osi, orig);
740
741 orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)];
742 if (orig_bytes != unknown[object_size_type])
743 orig_bytes = (offset > orig_bytes)
744 ? (unsigned HOST_WIDE_INT) 0 : orig_bytes - offset;
745
746 if ((object_size_type & 2) == 0)
747 {
748 if (object_sizes[object_size_type][varno] < orig_bytes)
749 {
750 object_sizes[object_size_type][varno] = orig_bytes;
751 osi->changed = true;
752 }
753 }
754 else
755 {
756 if (object_sizes[object_size_type][varno] > orig_bytes)
757 {
758 object_sizes[object_size_type][varno] = orig_bytes;
759 osi->changed = true;
760 }
761 }
762 return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig));
763 }
764
765
766 /* Compute object_sizes for VAR, defined to the result of an assignment
767 with operator POINTER_PLUS_EXPR. Return true if the object size might
768 need reexamination later. */
769
770 static bool
771 plus_stmt_object_size (struct object_size_info *osi, tree var, gimple stmt)
772 {
773 int object_size_type = osi->object_size_type;
774 unsigned int varno = SSA_NAME_VERSION (var);
775 unsigned HOST_WIDE_INT bytes;
776 tree op0, op1;
777
778 if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
779 {
780 op0 = gimple_assign_rhs1 (stmt);
781 op1 = gimple_assign_rhs2 (stmt);
782 }
783 else if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
784 {
785 tree rhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
786 gcc_assert (TREE_CODE (rhs) == MEM_REF);
787 op0 = TREE_OPERAND (rhs, 0);
788 op1 = TREE_OPERAND (rhs, 1);
789 }
790 else
791 gcc_unreachable ();
792
793 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
794 return false;
795
796 /* Handle PTR + OFFSET here. */
797 if (TREE_CODE (op1) == INTEGER_CST
798 && (TREE_CODE (op0) == SSA_NAME
799 || TREE_CODE (op0) == ADDR_EXPR))
800 {
801 if (! tree_fits_uhwi_p (op1))
802 bytes = unknown[object_size_type];
803 else if (TREE_CODE (op0) == SSA_NAME)
804 return merge_object_sizes (osi, var, op0, tree_to_uhwi (op1));
805 else
806 {
807 unsigned HOST_WIDE_INT off = tree_to_uhwi (op1);
808
809 /* op0 will be ADDR_EXPR here. */
810 bytes = addr_object_size (osi, op0, object_size_type);
811 if (bytes == unknown[object_size_type])
812 ;
813 else if (off > offset_limit)
814 bytes = unknown[object_size_type];
815 else if (off > bytes)
816 bytes = 0;
817 else
818 bytes -= off;
819 }
820 }
821 else
822 bytes = unknown[object_size_type];
823
824 if ((object_size_type & 2) == 0)
825 {
826 if (object_sizes[object_size_type][varno] < bytes)
827 object_sizes[object_size_type][varno] = bytes;
828 }
829 else
830 {
831 if (object_sizes[object_size_type][varno] > bytes)
832 object_sizes[object_size_type][varno] = bytes;
833 }
834 return false;
835 }
836
837
838 /* Compute object_sizes for VAR, defined at STMT, which is
839 a COND_EXPR. Return true if the object size might need reexamination
840 later. */
841
842 static bool
843 cond_expr_object_size (struct object_size_info *osi, tree var, gimple stmt)
844 {
845 tree then_, else_;
846 int object_size_type = osi->object_size_type;
847 unsigned int varno = SSA_NAME_VERSION (var);
848 bool reexamine = false;
849
850 gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR);
851
852 if (object_sizes[object_size_type][varno] == unknown[object_size_type])
853 return false;
854
855 then_ = gimple_assign_rhs2 (stmt);
856 else_ = gimple_assign_rhs3 (stmt);
857
858 if (TREE_CODE (then_) == SSA_NAME)
859 reexamine |= merge_object_sizes (osi, var, then_, 0);
860 else
861 expr_object_size (osi, var, then_);
862
863 if (TREE_CODE (else_) == SSA_NAME)
864 reexamine |= merge_object_sizes (osi, var, else_, 0);
865 else
866 expr_object_size (osi, var, else_);
867
868 return reexamine;
869 }
870
871 /* Compute object sizes for VAR.
872 For ADDR_EXPR an object size is the number of remaining bytes
873 to the end of the object (where what is considered an object depends on
874 OSI->object_size_type).
875 For allocation GIMPLE_CALL like malloc or calloc object size is the size
876 of the allocation.
877 For POINTER_PLUS_EXPR where second operand is a constant integer,
878 object size is object size of the first operand minus the constant.
879 If the constant is bigger than the number of remaining bytes until the
880 end of the object, object size is 0, but if it is instead a pointer
881 subtraction, object size is unknown[object_size_type].
882 To differentiate addition from subtraction, ADDR_EXPR returns
883 unknown[object_size_type] for all objects bigger than half of the address
884 space, and constants less than half of the address space are considered
885 addition, while bigger constants subtraction.
886 For a memcpy like GIMPLE_CALL that always returns one of its arguments, the
887 object size is object size of that argument.
888 Otherwise, object size is the maximum of object sizes of variables
889 that it might be set to. */
890
891 static void
892 collect_object_sizes_for (struct object_size_info *osi, tree var)
893 {
894 int object_size_type = osi->object_size_type;
895 unsigned int varno = SSA_NAME_VERSION (var);
896 gimple stmt;
897 bool reexamine;
898
899 if (bitmap_bit_p (computed[object_size_type], varno))
900 return;
901
902 if (osi->pass == 0)
903 {
904 if (bitmap_set_bit (osi->visited, varno))
905 {
906 object_sizes[object_size_type][varno]
907 = (object_size_type & 2) ? -1 : 0;
908 }
909 else
910 {
911 /* Found a dependency loop. Mark the variable for later
912 re-examination. */
913 bitmap_set_bit (osi->reexamine, varno);
914 if (dump_file && (dump_flags & TDF_DETAILS))
915 {
916 fprintf (dump_file, "Found a dependency loop at ");
917 print_generic_expr (dump_file, var, dump_flags);
918 fprintf (dump_file, "\n");
919 }
920 return;
921 }
922 }
923
924 if (dump_file && (dump_flags & TDF_DETAILS))
925 {
926 fprintf (dump_file, "Visiting use-def links for ");
927 print_generic_expr (dump_file, var, dump_flags);
928 fprintf (dump_file, "\n");
929 }
930
931 stmt = SSA_NAME_DEF_STMT (var);
932 reexamine = false;
933
934 switch (gimple_code (stmt))
935 {
936 case GIMPLE_ASSIGN:
937 {
938 tree rhs = gimple_assign_rhs1 (stmt);
939 if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
940 || (gimple_assign_rhs_code (stmt) == ADDR_EXPR
941 && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF))
942 reexamine = plus_stmt_object_size (osi, var, stmt);
943 else if (gimple_assign_rhs_code (stmt) == COND_EXPR)
944 reexamine = cond_expr_object_size (osi, var, stmt);
945 else if (gimple_assign_single_p (stmt)
946 || gimple_assign_unary_nop_p (stmt))
947 {
948 if (TREE_CODE (rhs) == SSA_NAME
949 && POINTER_TYPE_P (TREE_TYPE (rhs)))
950 reexamine = merge_object_sizes (osi, var, rhs, 0);
951 else
952 expr_object_size (osi, var, rhs);
953 }
954 else
955 unknown_object_size (osi, var);
956 break;
957 }
958
959 case GIMPLE_CALL:
960 {
961 tree arg = pass_through_call (stmt);
962 if (arg)
963 {
964 if (TREE_CODE (arg) == SSA_NAME
965 && POINTER_TYPE_P (TREE_TYPE (arg)))
966 reexamine = merge_object_sizes (osi, var, arg, 0);
967 else
968 expr_object_size (osi, var, arg);
969 }
970 else
971 call_object_size (osi, var, stmt);
972 break;
973 }
974
975 case GIMPLE_ASM:
976 /* Pointers defined by __asm__ statements can point anywhere. */
977 object_sizes[object_size_type][varno] = unknown[object_size_type];
978 break;
979
980 case GIMPLE_NOP:
981 if (SSA_NAME_VAR (var)
982 && TREE_CODE (SSA_NAME_VAR (var)) == PARM_DECL)
983 expr_object_size (osi, var, SSA_NAME_VAR (var));
984 else
985 /* Uninitialized SSA names point nowhere. */
986 object_sizes[object_size_type][varno] = unknown[object_size_type];
987 break;
988
989 case GIMPLE_PHI:
990 {
991 unsigned i;
992
993 for (i = 0; i < gimple_phi_num_args (stmt); i++)
994 {
995 tree rhs = gimple_phi_arg (stmt, i)->def;
996
997 if (object_sizes[object_size_type][varno]
998 == unknown[object_size_type])
999 break;
1000
1001 if (TREE_CODE (rhs) == SSA_NAME)
1002 reexamine |= merge_object_sizes (osi, var, rhs, 0);
1003 else if (osi->pass == 0)
1004 expr_object_size (osi, var, rhs);
1005 }
1006 break;
1007 }
1008
1009 default:
1010 gcc_unreachable ();
1011 }
1012
1013 if (! reexamine
1014 || object_sizes[object_size_type][varno] == unknown[object_size_type])
1015 {
1016 bitmap_set_bit (computed[object_size_type], varno);
1017 bitmap_clear_bit (osi->reexamine, varno);
1018 }
1019 else
1020 {
1021 bitmap_set_bit (osi->reexamine, varno);
1022 if (dump_file && (dump_flags & TDF_DETAILS))
1023 {
1024 fprintf (dump_file, "Need to reexamine ");
1025 print_generic_expr (dump_file, var, dump_flags);
1026 fprintf (dump_file, "\n");
1027 }
1028 }
1029 }
1030
1031
1032 /* Helper function for check_for_plus_in_loops. Called recursively
1033 to detect loops. */
1034
1035 static void
1036 check_for_plus_in_loops_1 (struct object_size_info *osi, tree var,
1037 unsigned int depth)
1038 {
1039 gimple stmt = SSA_NAME_DEF_STMT (var);
1040 unsigned int varno = SSA_NAME_VERSION (var);
1041
1042 if (osi->depths[varno])
1043 {
1044 if (osi->depths[varno] != depth)
1045 {
1046 unsigned int *sp;
1047
1048 /* Found a loop involving pointer addition. */
1049 for (sp = osi->tos; sp > osi->stack; )
1050 {
1051 --sp;
1052 bitmap_clear_bit (osi->reexamine, *sp);
1053 bitmap_set_bit (computed[osi->object_size_type], *sp);
1054 object_sizes[osi->object_size_type][*sp] = 0;
1055 if (*sp == varno)
1056 break;
1057 }
1058 }
1059 return;
1060 }
1061 else if (! bitmap_bit_p (osi->reexamine, varno))
1062 return;
1063
1064 osi->depths[varno] = depth;
1065 *osi->tos++ = varno;
1066
1067 switch (gimple_code (stmt))
1068 {
1069
1070 case GIMPLE_ASSIGN:
1071 {
1072 if ((gimple_assign_single_p (stmt)
1073 || gimple_assign_unary_nop_p (stmt))
1074 && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
1075 {
1076 tree rhs = gimple_assign_rhs1 (stmt);
1077
1078 check_for_plus_in_loops_1 (osi, rhs, depth);
1079 }
1080 else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1081 {
1082 tree basevar = gimple_assign_rhs1 (stmt);
1083 tree cst = gimple_assign_rhs2 (stmt);
1084
1085 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
1086
1087 check_for_plus_in_loops_1 (osi, basevar,
1088 depth + !integer_zerop (cst));
1089 }
1090 else
1091 gcc_unreachable ();
1092 break;
1093 }
1094
1095 case GIMPLE_CALL:
1096 {
1097 tree arg = pass_through_call (stmt);
1098 if (arg)
1099 {
1100 if (TREE_CODE (arg) == SSA_NAME)
1101 check_for_plus_in_loops_1 (osi, arg, depth);
1102 else
1103 gcc_unreachable ();
1104 }
1105 break;
1106 }
1107
1108 case GIMPLE_PHI:
1109 {
1110 unsigned i;
1111
1112 for (i = 0; i < gimple_phi_num_args (stmt); i++)
1113 {
1114 tree rhs = gimple_phi_arg (stmt, i)->def;
1115
1116 if (TREE_CODE (rhs) == SSA_NAME)
1117 check_for_plus_in_loops_1 (osi, rhs, depth);
1118 }
1119 break;
1120 }
1121
1122 default:
1123 gcc_unreachable ();
1124 }
1125
1126 osi->depths[varno] = 0;
1127 osi->tos--;
1128 }
1129
1130
1131 /* Check if some pointer we are computing object size of is being increased
1132 within a loop. If yes, assume all the SSA variables participating in
1133 that loop have minimum object sizes 0. */
1134
1135 static void
1136 check_for_plus_in_loops (struct object_size_info *osi, tree var)
1137 {
1138 gimple stmt = SSA_NAME_DEF_STMT (var);
1139
1140 /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here,
1141 and looked for a POINTER_PLUS_EXPR in the pass-through
1142 argument, if any. In GIMPLE, however, such an expression
1143 is not a valid call operand. */
1144
1145 if (is_gimple_assign (stmt)
1146 && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
1147 {
1148 tree basevar = gimple_assign_rhs1 (stmt);
1149 tree cst = gimple_assign_rhs2 (stmt);
1150
1151 gcc_assert (TREE_CODE (cst) == INTEGER_CST);
1152
1153 if (integer_zerop (cst))
1154 return;
1155
1156 osi->depths[SSA_NAME_VERSION (basevar)] = 1;
1157 *osi->tos++ = SSA_NAME_VERSION (basevar);
1158 check_for_plus_in_loops_1 (osi, var, 2);
1159 osi->depths[SSA_NAME_VERSION (basevar)] = 0;
1160 osi->tos--;
1161 }
1162 }
1163
1164
1165 /* Initialize data structures for the object size computation. */
1166
1167 void
1168 init_object_sizes (void)
1169 {
1170 int object_size_type;
1171
1172 if (object_sizes[0])
1173 return;
1174
1175 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1176 {
1177 object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names);
1178 computed[object_size_type] = BITMAP_ALLOC (NULL);
1179 }
1180
1181 init_offset_limit ();
1182 }
1183
1184
1185 /* Destroy data structures after the object size computation. */
1186
1187 static void
1188 fini_object_sizes (void)
1189 {
1190 int object_size_type;
1191
1192 for (object_size_type = 0; object_size_type <= 3; object_size_type++)
1193 {
1194 free (object_sizes[object_size_type]);
1195 BITMAP_FREE (computed[object_size_type]);
1196 object_sizes[object_size_type] = NULL;
1197 }
1198 }
1199
1200
1201 /* Simple pass to optimize all __builtin_object_size () builtins. */
1202
1203 static unsigned int
1204 compute_object_sizes (void)
1205 {
1206 basic_block bb;
1207 FOR_EACH_BB (bb)
1208 {
1209 gimple_stmt_iterator i;
1210 for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
1211 {
1212 tree result;
1213 gimple call = gsi_stmt (i);
1214 if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE))
1215 continue;
1216
1217 init_object_sizes ();
1218 result = fold_call_stmt (call, false);
1219 if (!result)
1220 {
1221 if (gimple_call_num_args (call) == 2
1222 && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, 0))))
1223 {
1224 tree ost = gimple_call_arg (call, 1);
1225
1226 if (tree_fits_uhwi_p (ost))
1227 {
1228 unsigned HOST_WIDE_INT object_size_type
1229 = tree_to_uhwi (ost);
1230
1231 if (object_size_type < 2)
1232 result = fold_convert (size_type_node,
1233 integer_minus_one_node);
1234 else if (object_size_type < 4)
1235 result = build_zero_cst (size_type_node);
1236 }
1237 }
1238
1239 if (!result)
1240 continue;
1241 }
1242
1243 gcc_assert (TREE_CODE (result) == INTEGER_CST);
1244
1245 if (dump_file && (dump_flags & TDF_DETAILS))
1246 {
1247 fprintf (dump_file, "Simplified\n ");
1248 print_gimple_stmt (dump_file, call, 0, dump_flags);
1249 fprintf (dump_file, " to ");
1250 print_generic_expr (dump_file, result, 0);
1251 fprintf (dump_file, "\n");
1252 }
1253
1254 tree lhs = gimple_call_lhs (call);
1255 if (!lhs)
1256 continue;
1257
1258 /* Propagate into all uses and fold those stmts. */
1259 gimple use_stmt;
1260 imm_use_iterator iter;
1261 FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
1262 {
1263 use_operand_p use_p;
1264 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
1265 SET_USE (use_p, result);
1266 gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
1267 fold_stmt (&gsi);
1268 update_stmt (gsi_stmt (gsi));
1269 }
1270 }
1271 }
1272
1273 fini_object_sizes ();
1274 return 0;
1275 }
1276
1277 namespace {
1278
1279 const pass_data pass_data_object_sizes =
1280 {
1281 GIMPLE_PASS, /* type */
1282 "objsz", /* name */
1283 OPTGROUP_NONE, /* optinfo_flags */
1284 false, /* has_gate */
1285 true, /* has_execute */
1286 TV_NONE, /* tv_id */
1287 ( PROP_cfg | PROP_ssa ), /* properties_required */
1288 0, /* properties_provided */
1289 0, /* properties_destroyed */
1290 0, /* todo_flags_start */
1291 TODO_verify_ssa, /* todo_flags_finish */
1292 };
1293
1294 class pass_object_sizes : public gimple_opt_pass
1295 {
1296 public:
1297 pass_object_sizes (gcc::context *ctxt)
1298 : gimple_opt_pass (pass_data_object_sizes, ctxt)
1299 {}
1300
1301 /* opt_pass methods: */
1302 opt_pass * clone () { return new pass_object_sizes (m_ctxt); }
1303 unsigned int execute () { return compute_object_sizes (); }
1304
1305 }; // class pass_object_sizes
1306
1307 } // anon namespace
1308
1309 gimple_opt_pass *
1310 make_pass_object_sizes (gcc::context *ctxt)
1311 {
1312 return new pass_object_sizes (ctxt);
1313 }