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