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