1 /* Exception handling semantics and decomposition for trees. 2 Copyright (C) 2003-2024 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 GCC is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #include "config.h" 21 #include "system.h" 22 #include "coretypes.h" 23 #include "backend.h" 24 #include "rtl.h" 25 #include "tree.h" 26 #include "gimple.h" 27 #include "cfghooks.h" 28 #include "tree-pass.h" 29 #include "ssa.h" 30 #include "cgraph.h" 31 #include "diagnostic-core.h" 32 #include "fold-const.h" 33 #include "calls.h" 34 #include "except.h" 35 #include "cfganal.h" 36 #include "cfgcleanup.h" 37 #include "tree-eh.h" 38 #include "gimple-iterator.h" 39 #include "tree-cfg.h" 40 #include "tree-into-ssa.h" 41 #include "tree-ssa.h" 42 #include "tree-inline.h" 43 #include "langhooks.h" 44 #include "cfgloop.h" 45 #include "gimple-low.h" 46 #include "stringpool.h" 47 #include "attribs.h" 48 #include "asan.h" 49 #include "gimplify.h" 50 51 /* In some instances a tree and a gimple need to be stored in a same table, 52 i.e. in hash tables. This is a structure to do this. */ 53 typedef union {tree *tp; tree t; gimple *g;} treemple; 54 55 /* Misc functions used in this file. */ 56 57 /* Remember and lookup EH landing pad data for arbitrary statements. 58 Really this means any statement that could_throw_p. We could 59 stuff this information into the stmt_ann data structure, but: 60 61 (1) We absolutely rely on this information being kept until 62 we get to rtl. Once we're done with lowering here, if we lose 63 the information there's no way to recover it! 64 65 (2) There are many more statements that *cannot* throw as 66 compared to those that can. We should be saving some amount 67 of space by only allocating memory for those that can throw. */ 68 69 /* Add statement T in function IFUN to landing pad NUM. */ 70 71 static void 72 add_stmt_to_eh_lp_fn (struct function *ifun, gimple *t, int num) 73 { 74 gcc_assert (num != 0); 75 76 if (!get_eh_throw_stmt_table (ifun)) 77 set_eh_throw_stmt_table (ifun, hash_map<gimple *, int>::create_ggc (31)); 78 79 bool existed = get_eh_throw_stmt_table (ifun)->put (t, num); 80 gcc_assert (!existed); 81 } 82 83 /* Add statement T in the current function (cfun) to EH landing pad NUM. */ 84 85 void 86 add_stmt_to_eh_lp (gimple *t, int num) 87 { 88 add_stmt_to_eh_lp_fn (cfun, t, num); 89 } 90 91 /* Add statement T to the single EH landing pad in REGION. */ 92 93 static void 94 record_stmt_eh_region (eh_region region, gimple *t) 95 { 96 if (region == NULL) 97 return; 98 if (region->type == ERT_MUST_NOT_THROW) 99 add_stmt_to_eh_lp_fn (cfun, t, -region->index); 100 else 101 { 102 eh_landing_pad lp = region->landing_pads; 103 if (lp == NULL) 104 lp = gen_eh_landing_pad (region); 105 else 106 gcc_assert (lp->next_lp == NULL); 107 add_stmt_to_eh_lp_fn (cfun, t, lp->index); 108 } 109 } 110 111 112 /* Remove statement T in function IFUN from its EH landing pad. */ 113 114 bool 115 remove_stmt_from_eh_lp_fn (struct function *ifun, gimple *t) 116 { 117 if (!get_eh_throw_stmt_table (ifun)) 118 return false; 119 120 if (!get_eh_throw_stmt_table (ifun)->get (t)) 121 return false; 122 123 get_eh_throw_stmt_table (ifun)->remove (t); 124 return true; 125 } 126 127 128 /* Remove statement T in the current function (cfun) from its 129 EH landing pad. */ 130 131 bool 132 remove_stmt_from_eh_lp (gimple *t) 133 { 134 return remove_stmt_from_eh_lp_fn (cfun, t); 135 } 136 137 /* Determine if statement T is inside an EH region in function IFUN. 138 Positive numbers indicate a landing pad index; negative numbers 139 indicate a MUST_NOT_THROW region index; zero indicates that the 140 statement is not recorded in the region table. */ 141 142 int 143 lookup_stmt_eh_lp_fn (struct function *ifun, const gimple *t) 144 { 145 if (ifun->eh->throw_stmt_table == NULL) 146 return 0; 147 148 int *lp_nr = ifun->eh->throw_stmt_table->get (const_cast <gimple *> (t)); 149 return lp_nr ? *lp_nr : 0; 150 } 151 152 /* Likewise, but always use the current function. */ 153 154 int 155 lookup_stmt_eh_lp (const gimple *t) 156 { 157 /* We can get called from initialized data when -fnon-call-exceptions 158 is on; prevent crash. */ 159 if (!cfun) 160 return 0; 161 return lookup_stmt_eh_lp_fn (cfun, t); 162 } 163 164 /* First pass of EH node decomposition. Build up a tree of GIMPLE_TRY_FINALLY 165 nodes and LABEL_DECL nodes. We will use this during the second phase to 166 determine if a goto leaves the body of a TRY_FINALLY_EXPR node. */ 167 168 struct finally_tree_node 169 { 170 /* When storing a GIMPLE_TRY, we have to record a gimple. However 171 when deciding whether a GOTO to a certain LABEL_DECL (which is a 172 tree) leaves the TRY block, its necessary to record a tree in 173 this field. Thus a treemple is used. */ 174 treemple child; 175 gtry *parent; 176 }; 177 178 /* Hashtable helpers. */ 179 180 struct finally_tree_hasher : free_ptr_hash <finally_tree_node> 181 { 182 static inline hashval_t hash (const finally_tree_node *); 183 static inline bool equal (const finally_tree_node *, 184 const finally_tree_node *); 185 }; 186 187 inline hashval_t 188 finally_tree_hasher::hash (const finally_tree_node *v) 189 { 190 return (intptr_t)v->child.t >> 4; 191 } 192 193 inline bool 194 finally_tree_hasher::equal (const finally_tree_node *v, 195 const finally_tree_node *c) 196 { 197 return v->child.t == c->child.t; 198 } 199 200 /* Note that this table is *not* marked GTY. It is short-lived. */ 201 static hash_table<finally_tree_hasher> *finally_tree; 202 203 static void 204 record_in_finally_tree (treemple child, gtry *parent) 205 { 206 struct finally_tree_node *n; 207 finally_tree_node **slot; 208 209 n = XNEW (struct finally_tree_node); 210 n->child = child; 211 n->parent = parent; 212 213 slot = finally_tree->find_slot (n, INSERT); 214 gcc_assert (!*slot); 215 *slot = n; 216 } 217 218 static void 219 collect_finally_tree (gimple *stmt, gtry *region); 220 221 /* Go through the gimple sequence. Works with collect_finally_tree to 222 record all GIMPLE_LABEL and GIMPLE_TRY statements. */ 223 224 static void 225 collect_finally_tree_1 (gimple_seq seq, gtry *region) 226 { 227 gimple_stmt_iterator gsi; 228 229 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi)) 230 collect_finally_tree (gsi_stmt (gsi), region); 231 } 232 233 static void 234 collect_finally_tree (gimple *stmt, gtry *region) 235 { 236 treemple temp; 237 238 switch (gimple_code (stmt)) 239 { 240 case GIMPLE_LABEL: 241 temp.t = gimple_label_label (as_a <glabel *> (stmt)); 242 record_in_finally_tree (temp, region); 243 break; 244 245 case GIMPLE_TRY: 246 if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY) 247 { 248 temp.g = stmt; 249 record_in_finally_tree (temp, region); 250 collect_finally_tree_1 (gimple_try_eval (stmt), 251 as_a <gtry *> (stmt)); 252 collect_finally_tree_1 (gimple_try_cleanup (stmt), region); 253 } 254 else if (gimple_try_kind (stmt) == GIMPLE_TRY_CATCH) 255 { 256 collect_finally_tree_1 (gimple_try_eval (stmt), region); 257 collect_finally_tree_1 (gimple_try_cleanup (stmt), region); 258 } 259 break; 260 261 case GIMPLE_CATCH: 262 collect_finally_tree_1 (gimple_catch_handler ( 263 as_a <gcatch *> (stmt)), 264 region); 265 break; 266 267 case GIMPLE_EH_FILTER: 268 collect_finally_tree_1 (gimple_eh_filter_failure (stmt), region); 269 break; 270 271 case GIMPLE_EH_ELSE: 272 { 273 geh_else *eh_else_stmt = as_a <geh_else *> (stmt); 274 collect_finally_tree_1 (gimple_eh_else_n_body (eh_else_stmt), region); 275 collect_finally_tree_1 (gimple_eh_else_e_body (eh_else_stmt), region); 276 } 277 break; 278 279 default: 280 /* A type, a decl, or some kind of statement that we're not 281 interested in. Don't walk them. */ 282 break; 283 } 284 } 285 286 287 /* Use the finally tree to determine if a jump from START to TARGET 288 would leave the try_finally node that START lives in. */ 289 290 static bool 291 outside_finally_tree (treemple start, gimple *target) 292 { 293 struct finally_tree_node n, *p; 294 295 do 296 { 297 n.child = start; 298 p = finally_tree->find (&n); 299 if (!p) 300 return true; 301 start.g = p->parent; 302 } 303 while (start.g != target); 304 305 return false; 306 } 307 308 /* Second pass of EH node decomposition. Actually transform the GIMPLE_TRY 309 nodes into a set of gotos, magic labels, and eh regions. 310 The eh region creation is straight-forward, but frobbing all the gotos 311 and such into shape isn't. */ 312 313 /* The sequence into which we record all EH stuff. This will be 314 placed at the end of the function when we're all done. */ 315 static gimple_seq eh_seq; 316 317 /* Record whether an EH region contains something that can throw, 318 indexed by EH region number. */ 319 static bitmap eh_region_may_contain_throw_map; 320 321 /* The GOTO_QUEUE is an array of GIMPLE_GOTO and GIMPLE_RETURN 322 statements that are seen to escape this GIMPLE_TRY_FINALLY node. 323 The idea is to record a gimple statement for everything except for 324 the conditionals, which get their labels recorded. Since labels are 325 of type 'tree', we need this node to store both gimple and tree 326 objects. REPL_STMT is the sequence used to replace the goto/return 327 statement. CONT_STMT is used to store the statement that allows 328 the return/goto to jump to the original destination. */ 329 330 struct goto_queue_node 331 { 332 treemple stmt; 333 location_t location; 334 gimple_seq repl_stmt; 335 gimple *cont_stmt; 336 int index; 337 /* This is used when index >= 0 to indicate that stmt is a label (as 338 opposed to a goto stmt). */ 339 int is_label; 340 }; 341 342 /* State of the world while lowering. */ 343 344 struct leh_state 345 { 346 /* What's "current" while constructing the eh region tree. These 347 correspond to variables of the same name in cfun->eh, which we 348 don't have easy access to. */ 349 eh_region cur_region; 350 351 /* What's "current" for the purposes of __builtin_eh_pointer. For 352 a CATCH, this is the associated TRY. For an EH_FILTER, this is 353 the associated ALLOWED_EXCEPTIONS, etc. */ 354 eh_region ehp_region; 355 356 /* Processing of TRY_FINALLY requires a bit more state. This is 357 split out into a separate structure so that we don't have to 358 copy so much when processing other nodes. */ 359 struct leh_tf_state *tf; 360 361 /* Outer non-clean up region. */ 362 eh_region outer_non_cleanup; 363 }; 364 365 struct leh_tf_state 366 { 367 /* Pointer to the GIMPLE_TRY_FINALLY node under discussion. The 368 try_finally_expr is the original GIMPLE_TRY_FINALLY. We need to retain 369 this so that outside_finally_tree can reliably reference the tree used 370 in the collect_finally_tree data structures. */ 371 gtry *try_finally_expr; 372 gtry *top_p; 373 374 /* While lowering a top_p usually it is expanded into multiple statements, 375 thus we need the following field to store them. */ 376 gimple_seq top_p_seq; 377 378 /* The state outside this try_finally node. */ 379 struct leh_state *outer; 380 381 /* The exception region created for it. */ 382 eh_region region; 383 384 /* The goto queue. */ 385 struct goto_queue_node *goto_queue; 386 size_t goto_queue_size; 387 size_t goto_queue_active; 388 389 /* Pointer map to help in searching goto_queue when it is large. */ 390 hash_map<gimple *, goto_queue_node *> *goto_queue_map; 391 392 /* The set of unique labels seen as entries in the goto queue. */ 393 vec<tree> dest_array; 394 395 /* A label to be added at the end of the completed transformed 396 sequence. It will be set if may_fallthru was true *at one time*, 397 though subsequent transformations may have cleared that flag. */ 398 tree fallthru_label; 399 400 /* True if it is possible to fall out the bottom of the try block. 401 Cleared if the fallthru is converted to a goto. */ 402 bool may_fallthru; 403 404 /* True if any entry in goto_queue is a GIMPLE_RETURN. */ 405 bool may_return; 406 407 /* True if the finally block can receive an exception edge. 408 Cleared if the exception case is handled by code duplication. */ 409 bool may_throw; 410 }; 411 412 static gimple_seq lower_eh_must_not_throw (struct leh_state *, gtry *); 413 414 /* Search for STMT in the goto queue. Return the replacement, 415 or null if the statement isn't in the queue. */ 416 417 #define LARGE_GOTO_QUEUE 20 418 419 static void lower_eh_constructs_1 (struct leh_state *state, gimple_seq *seq); 420 421 static gimple_seq 422 find_goto_replacement (struct leh_tf_state *tf, treemple stmt) 423 { 424 unsigned int i; 425 426 if (tf->goto_queue_active < LARGE_GOTO_QUEUE) 427 { 428 for (i = 0; i < tf->goto_queue_active; i++) 429 if ( tf->goto_queue[i].stmt.g == stmt.g) 430 return tf->goto_queue[i].repl_stmt; 431 return NULL; 432 } 433 434 /* If we have a large number of entries in the goto_queue, create a 435 pointer map and use that for searching. */ 436 437 if (!tf->goto_queue_map) 438 { 439 tf->goto_queue_map = new hash_map<gimple *, goto_queue_node *>; 440 for (i = 0; i < tf->goto_queue_active; i++) 441 { 442 bool existed = tf->goto_queue_map->put (tf->goto_queue[i].stmt.g, 443 &tf->goto_queue[i]); 444 gcc_assert (!existed); 445 } 446 } 447 448 goto_queue_node **slot = tf->goto_queue_map->get (stmt.g); 449 if (slot != NULL) 450 return ((*slot)->repl_stmt); 451 452 return NULL; 453 } 454 455 /* A subroutine of replace_goto_queue_1. Handles the sub-clauses of a 456 lowered GIMPLE_COND. If, by chance, the replacement is a simple goto, 457 then we can just splat it in, otherwise we add the new stmts immediately 458 after the GIMPLE_COND and redirect. */ 459 460 static void 461 replace_goto_queue_cond_clause (tree *tp, struct leh_tf_state *tf, 462 gimple_stmt_iterator *gsi) 463 { 464 tree label; 465 gimple_seq new_seq; 466 treemple temp; 467 location_t loc = gimple_location (gsi_stmt (*gsi)); 468 469 temp.tp = tp; 470 new_seq = find_goto_replacement (tf, temp); 471 if (!new_seq) 472 return; 473 474 if (gimple_seq_singleton_p (new_seq) 475 && gimple_code (gimple_seq_first_stmt (new_seq)) == GIMPLE_GOTO) 476 { 477 *tp = gimple_goto_dest (gimple_seq_first_stmt (new_seq)); 478 return; 479 } 480 481 label = create_artificial_label (loc); 482 /* Set the new label for the GIMPLE_COND */ 483 *tp = label; 484 485 gsi_insert_after (gsi, gimple_build_label (label), GSI_CONTINUE_LINKING); 486 gsi_insert_seq_after (gsi, gimple_seq_copy (new_seq), GSI_CONTINUE_LINKING); 487 } 488 489 /* The real work of replace_goto_queue. Returns with TSI updated to 490 point to the next statement. */ 491 492 static void replace_goto_queue_stmt_list (gimple_seq *, struct leh_tf_state *); 493 494 static void 495 replace_goto_queue_1 (gimple *stmt, struct leh_tf_state *tf, 496 gimple_stmt_iterator *gsi) 497 { 498 gimple_seq seq; 499 treemple temp; 500 temp.g = NULL; 501 502 switch (gimple_code (stmt)) 503 { 504 case GIMPLE_GOTO: 505 case GIMPLE_RETURN: 506 temp.g = stmt; 507 seq = find_goto_replacement (tf, temp); 508 if (seq) 509 { 510 gimple_stmt_iterator i; 511 seq = gimple_seq_copy (seq); 512 for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i)) 513 gimple_set_location (gsi_stmt (i), gimple_location (stmt)); 514 gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT); 515 gsi_remove (gsi, false); 516 return; 517 } 518 break; 519 520 case GIMPLE_COND: 521 replace_goto_queue_cond_clause (gimple_op_ptr (stmt, 2), tf, gsi); 522 replace_goto_queue_cond_clause (gimple_op_ptr (stmt, 3), tf, gsi); 523 break; 524 525 case GIMPLE_TRY: 526 replace_goto_queue_stmt_list (gimple_try_eval_ptr (stmt), tf); 527 replace_goto_queue_stmt_list (gimple_try_cleanup_ptr (stmt), tf); 528 break; 529 case GIMPLE_CATCH: 530 replace_goto_queue_stmt_list (gimple_catch_handler_ptr ( 531 as_a <gcatch *> (stmt)), 532 tf); 533 break; 534 case GIMPLE_EH_FILTER: 535 replace_goto_queue_stmt_list (gimple_eh_filter_failure_ptr (stmt), tf); 536 break; 537 case GIMPLE_EH_ELSE: 538 { 539 geh_else *eh_else_stmt = as_a <geh_else *> (stmt); 540 replace_goto_queue_stmt_list (gimple_eh_else_n_body_ptr (eh_else_stmt), 541 tf); 542 replace_goto_queue_stmt_list (gimple_eh_else_e_body_ptr (eh_else_stmt), 543 tf); 544 } 545 break; 546 547 default: 548 /* These won't have gotos in them. */ 549 break; 550 } 551 552 gsi_next (gsi); 553 } 554 555 /* A subroutine of replace_goto_queue. Handles GIMPLE_SEQ. */ 556 557 static void 558 replace_goto_queue_stmt_list (gimple_seq *seq, struct leh_tf_state *tf) 559 { 560 gimple_stmt_iterator gsi = gsi_start (*seq); 561 562 while (!gsi_end_p (gsi)) 563 replace_goto_queue_1 (gsi_stmt (gsi), tf, &gsi); 564 } 565 566 /* Replace all goto queue members. */ 567 568 static void 569 replace_goto_queue (struct leh_tf_state *tf) 570 { 571 if (tf->goto_queue_active == 0) 572 return; 573 replace_goto_queue_stmt_list (&tf->top_p_seq, tf); 574 replace_goto_queue_stmt_list (&eh_seq, tf); 575 } 576 577 /* Add a new record to the goto queue contained in TF. NEW_STMT is the 578 data to be added, IS_LABEL indicates whether NEW_STMT is a label or 579 a gimple return. */ 580 581 static void 582 record_in_goto_queue (struct leh_tf_state *tf, 583 treemple new_stmt, 584 int index, 585 bool is_label, 586 location_t location) 587 { 588 size_t active, size; 589 struct goto_queue_node *q; 590 591 gcc_assert (!tf->goto_queue_map); 592 593 active = tf->goto_queue_active; 594 size = tf->goto_queue_size; 595 if (active >= size) 596 { 597 size = (size ? size * 2 : 32); 598 tf->goto_queue_size = size; 599 tf->goto_queue 600 = XRESIZEVEC (struct goto_queue_node, tf->goto_queue, size); 601 } 602 603 q = &tf->goto_queue[active]; 604 tf->goto_queue_active = active + 1; 605 606 memset (q, 0, sizeof (*q)); 607 q->stmt = new_stmt; 608 q->index = index; 609 q->location = location; 610 q->is_label = is_label; 611 } 612 613 /* Record the LABEL label in the goto queue contained in TF. 614 TF is not null. */ 615 616 static void 617 record_in_goto_queue_label (struct leh_tf_state *tf, treemple stmt, tree label, 618 location_t location) 619 { 620 int index; 621 treemple temp, new_stmt; 622 623 if (!label) 624 return; 625 626 /* Computed and non-local gotos do not get processed. Given 627 their nature we can neither tell whether we've escaped the 628 finally block nor redirect them if we knew. */ 629 if (TREE_CODE (label) != LABEL_DECL) 630 return; 631 632 /* No need to record gotos that don't leave the try block. */ 633 temp.t = label; 634 if (!outside_finally_tree (temp, tf->try_finally_expr)) 635 return; 636 637 if (! tf->dest_array.exists ()) 638 { 639 tf->dest_array.create (10); 640 tf->dest_array.quick_push (label); 641 index = 0; 642 } 643 else 644 { 645 int n = tf->dest_array.length (); 646 for (index = 0; index < n; ++index) 647 if (tf->dest_array[index] == label) 648 break; 649 if (index == n) 650 tf->dest_array.safe_push (label); 651 } 652 653 /* In the case of a GOTO we want to record the destination label, 654 since with a GIMPLE_COND we have an easy access to the then/else 655 labels. */ 656 new_stmt = stmt; 657 record_in_goto_queue (tf, new_stmt, index, true, location); 658 } 659 660 /* For any GIMPLE_GOTO or GIMPLE_RETURN, decide whether it leaves a try_finally 661 node, and if so record that fact in the goto queue associated with that 662 try_finally node. */ 663 664 static void 665 maybe_record_in_goto_queue (struct leh_state *state, gimple *stmt) 666 { 667 struct leh_tf_state *tf = state->tf; 668 treemple new_stmt; 669 670 if (!tf) 671 return; 672 673 switch (gimple_code (stmt)) 674 { 675 case GIMPLE_COND: 676 { 677 gcond *cond_stmt = as_a <gcond *> (stmt); 678 new_stmt.tp = gimple_op_ptr (cond_stmt, 2); 679 record_in_goto_queue_label (tf, new_stmt, 680 gimple_cond_true_label (cond_stmt), 681 EXPR_LOCATION (*new_stmt.tp)); 682 new_stmt.tp = gimple_op_ptr (cond_stmt, 3); 683 record_in_goto_queue_label (tf, new_stmt, 684 gimple_cond_false_label (cond_stmt), 685 EXPR_LOCATION (*new_stmt.tp)); 686 } 687 break; 688 case GIMPLE_GOTO: 689 new_stmt.g = stmt; 690 record_in_goto_queue_label (tf, new_stmt, gimple_goto_dest (stmt), 691 gimple_location (stmt)); 692 break; 693 694 case GIMPLE_RETURN: 695 tf->may_return = true; 696 new_stmt.g = stmt; 697 record_in_goto_queue (tf, new_stmt, -1, false, gimple_location (stmt)); 698 break; 699 700 default: 701 gcc_unreachable (); 702 } 703 } 704 705 706 #if CHECKING_P 707 /* We do not process GIMPLE_SWITCHes for now. As long as the original source 708 was in fact structured, and we've not yet done jump threading, then none 709 of the labels will leave outer GIMPLE_TRY_FINALLY nodes. Verify this. */ 710 711 static void 712 verify_norecord_switch_expr (struct leh_state *state, 713 gswitch *switch_expr) 714 { 715 struct leh_tf_state *tf = state->tf; 716 size_t i, n; 717 718 if (!tf) 719 return; 720 721 n = gimple_switch_num_labels (switch_expr); 722 723 for (i = 0; i < n; ++i) 724 { 725 treemple temp; 726 tree lab = CASE_LABEL (gimple_switch_label (switch_expr, i)); 727 temp.t = lab; 728 gcc_assert (!outside_finally_tree (temp, tf->try_finally_expr)); 729 } 730 } 731 #else 732 #define verify_norecord_switch_expr(state, switch_expr) 733 #endif 734 735 /* Redirect a RETURN_EXPR pointed to by Q to FINLAB. If MOD is 736 non-null, insert it before the new branch. */ 737 738 static void 739 do_return_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod) 740 { 741 gimple *x; 742 743 /* In the case of a return, the queue node must be a gimple statement. */ 744 gcc_assert (!q->is_label); 745 746 /* Note that the return value may have already been computed, e.g., 747 748 int x; 749 int foo (void) 750 { 751 x = 0; 752 try { 753 return x; 754 } finally { 755 x++; 756 } 757 } 758 759 should return 0, not 1. We don't have to do anything to make 760 this happens because the return value has been placed in the 761 RESULT_DECL already. */ 762 763 q->cont_stmt = q->stmt.g; 764 765 if (mod) 766 gimple_seq_add_seq (&q->repl_stmt, mod); 767 768 x = gimple_build_goto (finlab); 769 gimple_set_location (x, q->location); 770 gimple_seq_add_stmt (&q->repl_stmt, x); 771 } 772 773 /* Similar, but easier, for GIMPLE_GOTO. */ 774 775 static void 776 do_goto_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod, 777 struct leh_tf_state *tf) 778 { 779 ggoto *x; 780 781 gcc_assert (q->is_label); 782 783 q->cont_stmt = gimple_build_goto (tf->dest_array[q->index]); 784 785 if (mod) 786 gimple_seq_add_seq (&q->repl_stmt, mod); 787 788 x = gimple_build_goto (finlab); 789 gimple_set_location (x, q->location); 790 gimple_seq_add_stmt (&q->repl_stmt, x); 791 } 792 793 /* Emit a standard landing pad sequence into SEQ for REGION. */ 794 795 static void 796 emit_post_landing_pad (gimple_seq *seq, eh_region region) 797 { 798 eh_landing_pad lp = region->landing_pads; 799 glabel *x; 800 801 if (lp == NULL) 802 lp = gen_eh_landing_pad (region); 803 804 lp->post_landing_pad = create_artificial_label (UNKNOWN_LOCATION); 805 EH_LANDING_PAD_NR (lp->post_landing_pad) = lp->index; 806 807 x = gimple_build_label (lp->post_landing_pad); 808 gimple_seq_add_stmt (seq, x); 809 } 810 811 /* Emit a RESX statement into SEQ for REGION. */ 812 813 static void 814 emit_resx (gimple_seq *seq, eh_region region) 815 { 816 gresx *x = gimple_build_resx (region->index); 817 gimple_seq_add_stmt (seq, x); 818 if (region->outer) 819 record_stmt_eh_region (region->outer, x); 820 } 821 822 /* Note that the current EH region may contain a throw, or a 823 call to a function which itself may contain a throw. */ 824 825 static void 826 note_eh_region_may_contain_throw (eh_region region) 827 { 828 while (bitmap_set_bit (eh_region_may_contain_throw_map, region->index)) 829 { 830 if (region->type == ERT_MUST_NOT_THROW) 831 break; 832 region = region->outer; 833 if (region == NULL) 834 break; 835 } 836 } 837 838 /* Check if REGION has been marked as containing a throw. If REGION is 839 NULL, this predicate is false. */ 840 841 static inline bool 842 eh_region_may_contain_throw (eh_region r) 843 { 844 return r && bitmap_bit_p (eh_region_may_contain_throw_map, r->index); 845 } 846 847 /* We want to transform 848 try { body; } catch { stuff; } 849 to 850 normal_sequence: 851 body; 852 over: 853 eh_sequence: 854 landing_pad: 855 stuff; 856 goto over; 857 858 TP is a GIMPLE_TRY node. REGION is the region whose post_landing_pad 859 should be placed before the second operand, or NULL. OVER is 860 an existing label that should be put at the exit, or NULL. */ 861 862 static gimple_seq 863 frob_into_branch_around (gtry *tp, eh_region region, tree over) 864 { 865 gimple *x; 866 gimple_seq cleanup, result; 867 location_t loc = gimple_location (tp); 868 869 cleanup = gimple_try_cleanup (tp); 870 result = gimple_try_eval (tp); 871 872 if (region) 873 emit_post_landing_pad (&eh_seq, region); 874 875 if (gimple_seq_may_fallthru (cleanup)) 876 { 877 if (!over) 878 over = create_artificial_label (loc); 879 x = gimple_build_goto (over); 880 gimple_set_location (x, loc); 881 gimple_seq_add_stmt (&cleanup, x); 882 } 883 gimple_seq_add_seq (&eh_seq, cleanup); 884 885 if (over) 886 { 887 x = gimple_build_label (over); 888 gimple_seq_add_stmt (&result, x); 889 } 890 return result; 891 } 892 893 /* A subroutine of lower_try_finally. Duplicate the tree rooted at T. 894 Make sure to record all new labels found. */ 895 896 static gimple_seq 897 lower_try_finally_dup_block (gimple_seq seq, struct leh_state *outer_state, 898 location_t loc) 899 { 900 gtry *region = NULL; 901 gimple_seq new_seq; 902 gimple_stmt_iterator gsi; 903 904 new_seq = copy_gimple_seq_and_replace_locals (seq); 905 906 for (gsi = gsi_start (new_seq); !gsi_end_p (gsi); gsi_next (&gsi)) 907 { 908 gimple *stmt = gsi_stmt (gsi); 909 if (LOCATION_LOCUS (gimple_location (stmt)) == UNKNOWN_LOCATION) 910 { 911 tree block = gimple_block (stmt); 912 gimple_set_location (stmt, loc); 913 gimple_set_block (stmt, block); 914 } 915 } 916 917 if (outer_state->tf) 918 region = outer_state->tf->try_finally_expr; 919 collect_finally_tree_1 (new_seq, region); 920 921 return new_seq; 922 } 923 924 /* A subroutine of lower_try_finally. Create a fallthru label for 925 the given try_finally state. The only tricky bit here is that 926 we have to make sure to record the label in our outer context. */ 927 928 static tree 929 lower_try_finally_fallthru_label (struct leh_tf_state *tf) 930 { 931 tree label = tf->fallthru_label; 932 treemple temp; 933 934 if (!label) 935 { 936 label = create_artificial_label (gimple_location (tf->try_finally_expr)); 937 tf->fallthru_label = label; 938 if (tf->outer->tf) 939 { 940 temp.t = label; 941 record_in_finally_tree (temp, tf->outer->tf->try_finally_expr); 942 } 943 } 944 return label; 945 } 946 947 /* A subroutine of lower_try_finally. If FINALLY consits of a 948 GIMPLE_EH_ELSE node, return it. */ 949 950 static inline geh_else * 951 get_eh_else (gimple_seq finally) 952 { 953 gimple *x = gimple_seq_first_stmt (finally); 954 if (x && gimple_code (x) == GIMPLE_EH_ELSE) 955 { 956 gcc_assert (gimple_seq_singleton_p (finally)); 957 return as_a <geh_else *> (x); 958 } 959 return NULL; 960 } 961 962 /* A subroutine of lower_try_finally. If the eh_protect_cleanup_actions 963 langhook returns non-null, then the language requires that the exception 964 path out of a try_finally be treated specially. To wit: the code within 965 the finally block may not itself throw an exception. We have two choices 966 here. First we can duplicate the finally block and wrap it in a 967 must_not_throw region. Second, we can generate code like 968 969 try { 970 finally_block; 971 } catch { 972 if (fintmp == eh_edge) 973 protect_cleanup_actions; 974 } 975 976 where "fintmp" is the temporary used in the switch statement generation 977 alternative considered below. For the nonce, we always choose the first 978 option. 979 980 THIS_STATE may be null if this is a try-cleanup, not a try-finally. */ 981 982 static void 983 honor_protect_cleanup_actions (struct leh_state *outer_state, 984 struct leh_state *this_state, 985 struct leh_tf_state *tf) 986 { 987 gimple_seq finally = gimple_try_cleanup (tf->top_p); 988 989 /* EH_ELSE doesn't come from user code; only compiler generated stuff. 990 It does need to be handled here, so as to separate the (different) 991 EH path from the normal path. But we should not attempt to wrap 992 it with a must-not-throw node (which indeed gets in the way). */ 993 if (geh_else *eh_else = get_eh_else (finally)) 994 { 995 gimple_try_set_cleanup (tf->top_p, gimple_eh_else_n_body (eh_else)); 996 finally = gimple_eh_else_e_body (eh_else); 997 998 /* Let the ELSE see the exception that's being processed, but 999 since the cleanup is outside the try block, process it with 1000 outer_state, otherwise it may be used as a cleanup for 1001 itself, and Bad Things (TM) ensue. */ 1002 eh_region save_ehp = outer_state->ehp_region; 1003 outer_state->ehp_region = this_state->cur_region; 1004 lower_eh_constructs_1 (outer_state, &finally); 1005 outer_state->ehp_region = save_ehp; 1006 } 1007 else 1008 { 1009 /* First check for nothing to do. */ 1010 if (lang_hooks.eh_protect_cleanup_actions == NULL) 1011 return; 1012 tree actions = lang_hooks.eh_protect_cleanup_actions (); 1013 if (actions == NULL) 1014 return; 1015 1016 if (this_state) 1017 finally = lower_try_finally_dup_block (finally, outer_state, 1018 gimple_location (tf->try_finally_expr)); 1019 1020 /* If this cleanup consists of a TRY_CATCH_EXPR with TRY_CATCH_IS_CLEANUP 1021 set, the handler of the TRY_CATCH_EXPR is another cleanup which ought 1022 to be in an enclosing scope, but needs to be implemented at this level 1023 to avoid a nesting violation (see wrap_temporary_cleanups in 1024 cp/decl.cc). Since it's logically at an outer level, we should call 1025 terminate before we get to it, so strip it away before adding the 1026 MUST_NOT_THROW filter. */ 1027 gimple_stmt_iterator gsi = gsi_start (finally); 1028 gimple *x = !gsi_end_p (gsi) ? gsi_stmt (gsi) : NULL; 1029 if (x 1030 && gimple_code (x) == GIMPLE_TRY 1031 && gimple_try_kind (x) == GIMPLE_TRY_CATCH 1032 && gimple_try_catch_is_cleanup (x)) 1033 { 1034 gsi_insert_seq_before (&gsi, gimple_try_eval (x), GSI_SAME_STMT); 1035 gsi_remove (&gsi, false); 1036 } 1037 1038 /* Wrap the block with protect_cleanup_actions as the action. */ 1039 geh_mnt *eh_mnt = gimple_build_eh_must_not_throw (actions); 1040 gtry *try_stmt = gimple_build_try (finally, 1041 gimple_seq_alloc_with_stmt (eh_mnt), 1042 GIMPLE_TRY_CATCH); 1043 finally = lower_eh_must_not_throw (outer_state, try_stmt); 1044 } 1045 1046 /* Drop all of this into the exception sequence. */ 1047 emit_post_landing_pad (&eh_seq, tf->region); 1048 gimple_seq_add_seq (&eh_seq, finally); 1049 if (gimple_seq_may_fallthru (finally)) 1050 emit_resx (&eh_seq, tf->region); 1051 1052 /* Having now been handled, EH isn't to be considered with 1053 the rest of the outgoing edges. */ 1054 tf->may_throw = false; 1055 } 1056 1057 /* A subroutine of lower_try_finally. We have determined that there is 1058 no fallthru edge out of the finally block. This means that there is 1059 no outgoing edge corresponding to any incoming edge. Restructure the 1060 try_finally node for this special case. */ 1061 1062 static void 1063 lower_try_finally_nofallthru (struct leh_state *state, 1064 struct leh_tf_state *tf) 1065 { 1066 tree lab; 1067 gimple *x; 1068 geh_else *eh_else; 1069 gimple_seq finally; 1070 struct goto_queue_node *q, *qe; 1071 1072 lab = create_artificial_label (gimple_location (tf->try_finally_expr)); 1073 1074 /* We expect that tf->top_p is a GIMPLE_TRY. */ 1075 finally = gimple_try_cleanup (tf->top_p); 1076 tf->top_p_seq = gimple_try_eval (tf->top_p); 1077 1078 x = gimple_build_label (lab); 1079 gimple_seq_add_stmt (&tf->top_p_seq, x); 1080 1081 q = tf->goto_queue; 1082 qe = q + tf->goto_queue_active; 1083 for (; q < qe; ++q) 1084 if (q->index < 0) 1085 do_return_redirection (q, lab, NULL); 1086 else 1087 do_goto_redirection (q, lab, NULL, tf); 1088 1089 replace_goto_queue (tf); 1090 1091 /* Emit the finally block into the stream. Lower EH_ELSE at this time. */ 1092 eh_else = get_eh_else (finally); 1093 if (eh_else) 1094 { 1095 finally = gimple_eh_else_n_body (eh_else); 1096 lower_eh_constructs_1 (state, &finally); 1097 gimple_seq_add_seq (&tf->top_p_seq, finally); 1098 1099 if (tf->may_throw) 1100 { 1101 finally = gimple_eh_else_e_body (eh_else); 1102 lower_eh_constructs_1 (state, &finally); 1103 1104 emit_post_landing_pad (&eh_seq, tf->region); 1105 gimple_seq_add_seq (&eh_seq, finally); 1106 } 1107 } 1108 else 1109 { 1110 lower_eh_constructs_1 (state, &finally); 1111 gimple_seq_add_seq (&tf->top_p_seq, finally); 1112 1113 if (tf->may_throw) 1114 { 1115 emit_post_landing_pad (&eh_seq, tf->region); 1116 1117 x = gimple_build_goto (lab); 1118 gimple_set_location (x, gimple_location (tf->try_finally_expr)); 1119 gimple_seq_add_stmt (&eh_seq, x); 1120 } 1121 } 1122 } 1123 1124 /* A subroutine of lower_try_finally. We have determined that there is 1125 exactly one destination of the finally block. Restructure the 1126 try_finally node for this special case. */ 1127 1128 static void 1129 lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf) 1130 { 1131 struct goto_queue_node *q, *qe; 1132 geh_else *eh_else; 1133 glabel *label_stmt; 1134 gimple *x; 1135 gimple_seq finally; 1136 gimple_stmt_iterator gsi; 1137 tree finally_label; 1138 location_t loc = gimple_location (tf->try_finally_expr); 1139 1140 finally = gimple_try_cleanup (tf->top_p); 1141 tf->top_p_seq = gimple_try_eval (tf->top_p); 1142 1143 /* Since there's only one destination, and the destination edge can only 1144 either be EH or non-EH, that implies that all of our incoming edges 1145 are of the same type. Therefore we can lower EH_ELSE immediately. */ 1146 eh_else = get_eh_else (finally); 1147 if (eh_else) 1148 { 1149 if (tf->may_throw) 1150 finally = gimple_eh_else_e_body (eh_else); 1151 else 1152 finally = gimple_eh_else_n_body (eh_else); 1153 } 1154 1155 lower_eh_constructs_1 (state, &finally); 1156 1157 for (gsi = gsi_start (finally); !gsi_end_p (gsi); gsi_next (&gsi)) 1158 { 1159 gimple *stmt = gsi_stmt (gsi); 1160 if (LOCATION_LOCUS (gimple_location (stmt)) == UNKNOWN_LOCATION) 1161 { 1162 tree block = gimple_block (stmt); 1163 gimple_set_location (stmt, gimple_location (tf->try_finally_expr)); 1164 gimple_set_block (stmt, block); 1165 } 1166 } 1167 1168 if (tf->may_throw) 1169 { 1170 /* Only reachable via the exception edge. Add the given label to 1171 the head of the FINALLY block. Append a RESX at the end. */ 1172 emit_post_landing_pad (&eh_seq, tf->region); 1173 gimple_seq_add_seq (&eh_seq, finally); 1174 emit_resx (&eh_seq, tf->region); 1175 return; 1176 } 1177 1178 if (tf->may_fallthru) 1179 { 1180 /* Only reachable via the fallthru edge. Do nothing but let 1181 the two blocks run together; we'll fall out the bottom. */ 1182 gimple_seq_add_seq (&tf->top_p_seq, finally); 1183 return; 1184 } 1185 1186 finally_label = create_artificial_label (loc); 1187 label_stmt = gimple_build_label (finally_label); 1188 gimple_seq_add_stmt (&tf->top_p_seq, label_stmt); 1189 1190 gimple_seq_add_seq (&tf->top_p_seq, finally); 1191 1192 q = tf->goto_queue; 1193 qe = q + tf->goto_queue_active; 1194 1195 if (tf->may_return) 1196 { 1197 /* Reachable by return expressions only. Redirect them. */ 1198 for (; q < qe; ++q) 1199 do_return_redirection (q, finally_label, NULL); 1200 replace_goto_queue (tf); 1201 } 1202 else 1203 { 1204 /* Reachable by goto expressions only. Redirect them. */ 1205 for (; q < qe; ++q) 1206 do_goto_redirection (q, finally_label, NULL, tf); 1207 replace_goto_queue (tf); 1208 1209 if (tf->dest_array[0] == tf->fallthru_label) 1210 { 1211 /* Reachable by goto to fallthru label only. Redirect it 1212 to the new label (already created, sadly), and do not 1213 emit the final branch out, or the fallthru label. */ 1214 tf->fallthru_label = NULL; 1215 return; 1216 } 1217 } 1218 1219 /* Place the original return/goto to the original destination 1220 immediately after the finally block. */ 1221 x = tf->goto_queue[0].cont_stmt; 1222 gimple_seq_add_stmt (&tf->top_p_seq, x); 1223 maybe_record_in_goto_queue (state, x); 1224 } 1225 1226 /* A subroutine of lower_try_finally. There are multiple edges incoming 1227 and outgoing from the finally block. Implement this by duplicating the 1228 finally block for every destination. */ 1229 1230 static void 1231 lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf) 1232 { 1233 gimple_seq finally; 1234 gimple_seq new_stmt; 1235 gimple_seq seq; 1236 gimple *x; 1237 geh_else *eh_else; 1238 tree tmp; 1239 location_t tf_loc = gimple_location (tf->try_finally_expr); 1240 1241 finally = gimple_try_cleanup (tf->top_p); 1242 1243 /* Notice EH_ELSE, and simplify some of the remaining code 1244 by considering FINALLY to be the normal return path only. */ 1245 eh_else = get_eh_else (finally); 1246 if (eh_else) 1247 finally = gimple_eh_else_n_body (eh_else); 1248 1249 tf->top_p_seq = gimple_try_eval (tf->top_p); 1250 new_stmt = NULL; 1251 1252 if (tf->may_fallthru) 1253 { 1254 seq = lower_try_finally_dup_block (finally, state, tf_loc); 1255 lower_eh_constructs_1 (state, &seq); 1256 gimple_seq_add_seq (&new_stmt, seq); 1257 1258 tmp = lower_try_finally_fallthru_label (tf); 1259 x = gimple_build_goto (tmp); 1260 gimple_set_location (x, tf_loc); 1261 gimple_seq_add_stmt (&new_stmt, x); 1262 } 1263 1264 if (tf->may_throw) 1265 { 1266 /* We don't need to copy the EH path of EH_ELSE, 1267 since it is only emitted once. */ 1268 if (eh_else) 1269 seq = gimple_eh_else_e_body (eh_else); 1270 else 1271 seq = lower_try_finally_dup_block (finally, state, tf_loc); 1272 lower_eh_constructs_1 (state, &seq); 1273 1274 emit_post_landing_pad (&eh_seq, tf->region); 1275 gimple_seq_add_seq (&eh_seq, seq); 1276 emit_resx (&eh_seq, tf->region); 1277 } 1278 1279 if (tf->goto_queue) 1280 { 1281 struct goto_queue_node *q, *qe; 1282 int return_index, index; 1283 struct labels_s 1284 { 1285 struct goto_queue_node *q; 1286 tree label; 1287 } *labels; 1288 1289 return_index = tf->dest_array.length (); 1290 labels = XCNEWVEC (struct labels_s, return_index + 1); 1291 1292 q = tf->goto_queue; 1293 qe = q + tf->goto_queue_active; 1294 for (; q < qe; q++) 1295 { 1296 index = q->index < 0 ? return_index : q->index; 1297 1298 if (!labels[index].q) 1299 labels[index].q = q; 1300 } 1301 1302 for (index = 0; index < return_index + 1; index++) 1303 { 1304 tree lab; 1305 1306 q = labels[index].q; 1307 if (! q) 1308 continue; 1309 1310 lab = labels[index].label 1311 = create_artificial_label (tf_loc); 1312 1313 if (index == return_index) 1314 do_return_redirection (q, lab, NULL); 1315 else 1316 do_goto_redirection (q, lab, NULL, tf); 1317 1318 x = gimple_build_label (lab); 1319 gimple_seq_add_stmt (&new_stmt, x); 1320 1321 seq = lower_try_finally_dup_block (finally, state, q->location); 1322 lower_eh_constructs_1 (state, &seq); 1323 gimple_seq_add_seq (&new_stmt, seq); 1324 1325 gimple_seq_add_stmt (&new_stmt, q->cont_stmt); 1326 maybe_record_in_goto_queue (state, q->cont_stmt); 1327 } 1328 1329 for (q = tf->goto_queue; q < qe; q++) 1330 { 1331 tree lab; 1332 1333 index = q->index < 0 ? return_index : q->index; 1334 1335 if (labels[index].q == q) 1336 continue; 1337 1338 lab = labels[index].label; 1339 1340 if (index == return_index) 1341 do_return_redirection (q, lab, NULL); 1342 else 1343 do_goto_redirection (q, lab, NULL, tf); 1344 } 1345 1346 replace_goto_queue (tf); 1347 free (labels); 1348 } 1349 1350 /* Need to link new stmts after running replace_goto_queue due 1351 to not wanting to process the same goto stmts twice. */ 1352 gimple_seq_add_seq (&tf->top_p_seq, new_stmt); 1353 } 1354 1355 /* A subroutine of lower_try_finally. There are multiple edges incoming 1356 and outgoing from the finally block. Implement this by instrumenting 1357 each incoming edge and creating a switch statement at the end of the 1358 finally block that branches to the appropriate destination. */ 1359 1360 static void 1361 lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf) 1362 { 1363 struct goto_queue_node *q, *qe; 1364 tree finally_tmp, finally_label; 1365 int return_index, eh_index, fallthru_index; 1366 int nlabels, ndests, j, last_case_index; 1367 tree last_case; 1368 auto_vec<tree> case_label_vec; 1369 gimple_seq switch_body = NULL; 1370 gimple *x; 1371 geh_else *eh_else; 1372 tree tmp; 1373 gimple *switch_stmt; 1374 gimple_seq finally; 1375 hash_map<tree, gimple *> *cont_map = NULL; 1376 /* The location of the TRY_FINALLY stmt. */ 1377 location_t tf_loc = gimple_location (tf->try_finally_expr); 1378 /* The location of the finally block. */ 1379 location_t finally_loc; 1380 1381 finally = gimple_try_cleanup (tf->top_p); 1382 eh_else = get_eh_else (finally); 1383 1384 /* Mash the TRY block to the head of the chain. */ 1385 tf->top_p_seq = gimple_try_eval (tf->top_p); 1386 1387 /* The location of the finally is either the last stmt in the finally 1388 block or the location of the TRY_FINALLY itself. */ 1389 x = gimple_seq_last_stmt (finally); 1390 finally_loc = x ? gimple_location (x) : tf_loc; 1391 1392 /* Prepare for switch statement generation. */ 1393 nlabels = tf->dest_array.length (); 1394 return_index = nlabels; 1395 eh_index = return_index + tf->may_return; 1396 fallthru_index = eh_index + (tf->may_throw && !eh_else); 1397 ndests = fallthru_index + tf->may_fallthru; 1398 1399 finally_tmp = create_tmp_var (integer_type_node, "finally_tmp"); 1400 finally_label = create_artificial_label (finally_loc); 1401 1402 /* We use vec::quick_push on case_label_vec throughout this function, 1403 since we know the size in advance and allocate precisely as muce 1404 space as needed. */ 1405 case_label_vec.create (ndests); 1406 last_case = NULL; 1407 last_case_index = 0; 1408 1409 /* Begin inserting code for getting to the finally block. Things 1410 are done in this order to correspond to the sequence the code is 1411 laid out. */ 1412 1413 if (tf->may_fallthru) 1414 { 1415 x = gimple_build_assign (finally_tmp, 1416 build_int_cst (integer_type_node, 1417 fallthru_index)); 1418 gimple_set_location (x, finally_loc); 1419 gimple_seq_add_stmt (&tf->top_p_seq, x); 1420 1421 tmp = build_int_cst (integer_type_node, fallthru_index); 1422 last_case = build_case_label (tmp, NULL, 1423 create_artificial_label (finally_loc)); 1424 case_label_vec.quick_push (last_case); 1425 last_case_index++; 1426 1427 x = gimple_build_label (CASE_LABEL (last_case)); 1428 gimple_seq_add_stmt (&switch_body, x); 1429 1430 tmp = lower_try_finally_fallthru_label (tf); 1431 x = gimple_build_goto (tmp); 1432 gimple_set_location (x, finally_loc); 1433 gimple_seq_add_stmt (&switch_body, x); 1434 } 1435 1436 /* For EH_ELSE, emit the exception path (plus resx) now, then 1437 subsequently we only need consider the normal path. */ 1438 if (eh_else) 1439 { 1440 if (tf->may_throw) 1441 { 1442 finally = gimple_eh_else_e_body (eh_else); 1443 lower_eh_constructs_1 (state, &finally); 1444 1445 emit_post_landing_pad (&eh_seq, tf->region); 1446 gimple_seq_add_seq (&eh_seq, finally); 1447 emit_resx (&eh_seq, tf->region); 1448 } 1449 1450 finally = gimple_eh_else_n_body (eh_else); 1451 } 1452 else if (tf->may_throw) 1453 { 1454 emit_post_landing_pad (&eh_seq, tf->region); 1455 1456 x = gimple_build_assign (finally_tmp, 1457 build_int_cst (integer_type_node, eh_index)); 1458 gimple_seq_add_stmt (&eh_seq, x); 1459 1460 x = gimple_build_goto (finally_label); 1461 gimple_set_location (x, tf_loc); 1462 gimple_seq_add_stmt (&eh_seq, x); 1463 1464 tmp = build_int_cst (integer_type_node, eh_index); 1465 last_case = build_case_label (tmp, NULL, 1466 create_artificial_label (tf_loc)); 1467 case_label_vec.quick_push (last_case); 1468 last_case_index++; 1469 1470 x = gimple_build_label (CASE_LABEL (last_case)); 1471 gimple_seq_add_stmt (&eh_seq, x); 1472 emit_resx (&eh_seq, tf->region); 1473 } 1474 1475 x = gimple_build_label (finally_label); 1476 gimple_seq_add_stmt (&tf->top_p_seq, x); 1477 1478 lower_eh_constructs_1 (state, &finally); 1479 gimple_seq_add_seq (&tf->top_p_seq, finally); 1480 1481 /* Redirect each incoming goto edge. */ 1482 q = tf->goto_queue; 1483 qe = q + tf->goto_queue_active; 1484 j = last_case_index + tf->may_return; 1485 /* Prepare the assignments to finally_tmp that are executed upon the 1486 entrance through a particular edge. */ 1487 for (; q < qe; ++q) 1488 { 1489 gimple_seq mod = NULL; 1490 int switch_id; 1491 unsigned int case_index; 1492 1493 if (q->index < 0) 1494 { 1495 x = gimple_build_assign (finally_tmp, 1496 build_int_cst (integer_type_node, 1497 return_index)); 1498 gimple_seq_add_stmt (&mod, x); 1499 do_return_redirection (q, finally_label, mod); 1500 switch_id = return_index; 1501 } 1502 else 1503 { 1504 x = gimple_build_assign (finally_tmp, 1505 build_int_cst (integer_type_node, q->index)); 1506 gimple_seq_add_stmt (&mod, x); 1507 do_goto_redirection (q, finally_label, mod, tf); 1508 switch_id = q->index; 1509 } 1510 1511 case_index = j + q->index; 1512 if (case_label_vec.length () <= case_index || !case_label_vec[case_index]) 1513 { 1514 tree case_lab; 1515 tmp = build_int_cst (integer_type_node, switch_id); 1516 case_lab = build_case_label (tmp, NULL, 1517 create_artificial_label (tf_loc)); 1518 /* We store the cont_stmt in the pointer map, so that we can recover 1519 it in the loop below. */ 1520 if (!cont_map) 1521 cont_map = new hash_map<tree, gimple *>; 1522 cont_map->put (case_lab, q->cont_stmt); 1523 case_label_vec.quick_push (case_lab); 1524 } 1525 } 1526 for (j = last_case_index; j < last_case_index + nlabels; j++) 1527 { 1528 gimple *cont_stmt; 1529 1530 last_case = case_label_vec[j]; 1531 1532 gcc_assert (last_case); 1533 gcc_assert (cont_map); 1534 1535 cont_stmt = *cont_map->get (last_case); 1536 1537 x = gimple_build_label (CASE_LABEL (last_case)); 1538 gimple_seq_add_stmt (&switch_body, x); 1539 gimple_seq_add_stmt (&switch_body, cont_stmt); 1540 maybe_record_in_goto_queue (state, cont_stmt); 1541 } 1542 if (cont_map) 1543 delete cont_map; 1544 1545 replace_goto_queue (tf); 1546 1547 /* Make sure that the last case is the default label, as one is required. 1548 Then sort the labels, which is also required in GIMPLE. */ 1549 CASE_LOW (last_case) = NULL; 1550 tree tem = case_label_vec.pop (); 1551 gcc_assert (tem == last_case); 1552 sort_case_labels (case_label_vec); 1553 1554 /* Build the switch statement, setting last_case to be the default 1555 label. */ 1556 switch_stmt = gimple_build_switch (finally_tmp, last_case, 1557 case_label_vec); 1558 gimple_set_location (switch_stmt, finally_loc); 1559 1560 /* Need to link SWITCH_STMT after running replace_goto_queue 1561 due to not wanting to process the same goto stmts twice. */ 1562 gimple_seq_add_stmt (&tf->top_p_seq, switch_stmt); 1563 gimple_seq_add_seq (&tf->top_p_seq, switch_body); 1564 } 1565 1566 /* Decide whether or not we are going to duplicate the finally block. 1567 There are several considerations. 1568 1569 Second, we'd like to prevent egregious code growth. One way to 1570 do this is to estimate the size of the finally block, multiply 1571 that by the number of copies we'd need to make, and compare against 1572 the estimate of the size of the switch machinery we'd have to add. */ 1573 1574 static bool 1575 decide_copy_try_finally (int ndests, bool may_throw, gimple_seq finally) 1576 { 1577 int f_estimate, sw_estimate; 1578 geh_else *eh_else; 1579 1580 /* If there's an EH_ELSE involved, the exception path is separate 1581 and really doesn't come into play for this computation. */ 1582 eh_else = get_eh_else (finally); 1583 if (eh_else) 1584 { 1585 ndests -= may_throw; 1586 finally = gimple_eh_else_n_body (eh_else); 1587 } 1588 1589 if (!optimize) 1590 { 1591 gimple_stmt_iterator gsi; 1592 1593 if (ndests == 1) 1594 return true; 1595 1596 for (gsi = gsi_start (finally); !gsi_end_p (gsi); gsi_next (&gsi)) 1597 { 1598 /* Duplicate __builtin_stack_restore in the hope of eliminating it 1599 on the EH paths and, consequently, useless cleanups. */ 1600 gimple *stmt = gsi_stmt (gsi); 1601 if (!is_gimple_debug (stmt) 1602 && !gimple_clobber_p (stmt) 1603 && !gimple_call_builtin_p (stmt, BUILT_IN_STACK_RESTORE)) 1604 return false; 1605 } 1606 return true; 1607 } 1608 1609 /* Finally estimate N times, plus N gotos. */ 1610 f_estimate = estimate_num_insns_seq (finally, &eni_size_weights); 1611 f_estimate = (f_estimate + 1) * ndests; 1612 1613 /* Switch statement (cost 10), N variable assignments, N gotos. */ 1614 sw_estimate = 10 + 2 * ndests; 1615 1616 /* Optimize for size clearly wants our best guess. */ 1617 if (optimize_function_for_size_p (cfun)) 1618 return f_estimate < sw_estimate; 1619 1620 /* ??? These numbers are completely made up so far. */ 1621 if (optimize > 1) 1622 return f_estimate < 100 || f_estimate < sw_estimate * 2; 1623 else 1624 return f_estimate < 40 || f_estimate * 2 < sw_estimate * 3; 1625 } 1626 1627 /* REG is current region of a LEH state. 1628 is the enclosing region for a possible cleanup region, or the region 1629 itself. Returns TRUE if such a region would be unreachable. 1630 1631 Cleanup regions within a must-not-throw region aren't actually reachable 1632 even if there are throwing stmts within them, because the personality 1633 routine will call terminate before unwinding. */ 1634 1635 static bool 1636 cleanup_is_dead_in (leh_state *state) 1637 { 1638 if (flag_checking) 1639 { 1640 eh_region reg = state->cur_region; 1641 while (reg && reg->type == ERT_CLEANUP) 1642 reg = reg->outer; 1643 1644 gcc_assert (reg == state->outer_non_cleanup); 1645 } 1646 1647 eh_region reg = state->outer_non_cleanup; 1648 return (reg && reg->type == ERT_MUST_NOT_THROW); 1649 } 1650 1651 /* A subroutine of lower_eh_constructs_1. Lower a GIMPLE_TRY_FINALLY nodes 1652 to a sequence of labels and blocks, plus the exception region trees 1653 that record all the magic. This is complicated by the need to 1654 arrange for the FINALLY block to be executed on all exits. */ 1655 1656 static gimple_seq 1657 lower_try_finally (struct leh_state *state, gtry *tp) 1658 { 1659 struct leh_tf_state this_tf; 1660 struct leh_state this_state; 1661 int ndests; 1662 gimple_seq old_eh_seq; 1663 1664 /* Process the try block. */ 1665 1666 memset (&this_tf, 0, sizeof (this_tf)); 1667 this_tf.try_finally_expr = tp; 1668 this_tf.top_p = tp; 1669 this_tf.outer = state; 1670 if (using_eh_for_cleanups_p () && !cleanup_is_dead_in (state)) 1671 { 1672 this_tf.region = gen_eh_region_cleanup (state->cur_region); 1673 this_state.cur_region = this_tf.region; 1674 } 1675 else 1676 { 1677 this_tf.region = NULL; 1678 this_state.cur_region = state->cur_region; 1679 } 1680 1681 this_state.outer_non_cleanup = state->outer_non_cleanup; 1682 this_state.ehp_region = state->ehp_region; 1683 this_state.tf = &this_tf; 1684 1685 old_eh_seq = eh_seq; 1686 eh_seq = NULL; 1687 1688 lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp)); 1689 1690 /* Determine if the try block is escaped through the bottom. */ 1691 this_tf.may_fallthru = gimple_seq_may_fallthru (gimple_try_eval (tp)); 1692 1693 /* Determine if any exceptions are possible within the try block. */ 1694 if (this_tf.region) 1695 this_tf.may_throw = eh_region_may_contain_throw (this_tf.region); 1696 if (this_tf.may_throw) 1697 honor_protect_cleanup_actions (state, &this_state, &this_tf); 1698 1699 /* Determine how many edges (still) reach the finally block. Or rather, 1700 how many destinations are reached by the finally block. Use this to 1701 determine how we process the finally block itself. */ 1702 1703 ndests = this_tf.dest_array.length (); 1704 ndests += this_tf.may_fallthru; 1705 ndests += this_tf.may_return; 1706 ndests += this_tf.may_throw; 1707 1708 /* If the FINALLY block is not reachable, dike it out. */ 1709 if (ndests == 0) 1710 { 1711 gimple_seq_add_seq (&this_tf.top_p_seq, gimple_try_eval (tp)); 1712 gimple_try_set_cleanup (tp, NULL); 1713 } 1714 /* If the finally block doesn't fall through, then any destination 1715 we might try to impose there isn't reached either. There may be 1716 some minor amount of cleanup and redirection still needed. */ 1717 else if (!gimple_seq_may_fallthru (gimple_try_cleanup (tp))) 1718 lower_try_finally_nofallthru (state, &this_tf); 1719 1720 /* We can easily special-case redirection to a single destination. */ 1721 else if (ndests == 1) 1722 lower_try_finally_onedest (state, &this_tf); 1723 else if (decide_copy_try_finally (ndests, this_tf.may_throw, 1724 gimple_try_cleanup (tp))) 1725 lower_try_finally_copy (state, &this_tf); 1726 else 1727 lower_try_finally_switch (state, &this_tf); 1728 1729 /* If someone requested we add a label at the end of the transformed 1730 block, do so. */ 1731 if (this_tf.fallthru_label) 1732 { 1733 /* This must be reached only if ndests == 0. */ 1734 gimple *x = gimple_build_label (this_tf.fallthru_label); 1735 gimple_seq_add_stmt (&this_tf.top_p_seq, x); 1736 } 1737 1738 this_tf.dest_array.release (); 1739 free (this_tf.goto_queue); 1740 if (this_tf.goto_queue_map) 1741 delete this_tf.goto_queue_map; 1742 1743 /* If there was an old (aka outer) eh_seq, append the current eh_seq. 1744 If there was no old eh_seq, then the append is trivially already done. */ 1745 if (old_eh_seq) 1746 { 1747 if (eh_seq == NULL) 1748 eh_seq = old_eh_seq; 1749 else 1750 { 1751 gimple_seq new_eh_seq = eh_seq; 1752 eh_seq = old_eh_seq; 1753 gimple_seq_add_seq (&eh_seq, new_eh_seq); 1754 } 1755 } 1756 1757 return this_tf.top_p_seq; 1758 } 1759 1760 /* A subroutine of lower_eh_constructs_1. Lower a GIMPLE_TRY_CATCH with a 1761 list of GIMPLE_CATCH to a sequence of labels and blocks, plus the 1762 exception region trees that records all the magic. */ 1763 1764 static gimple_seq 1765 lower_catch (struct leh_state *state, gtry *tp) 1766 { 1767 eh_region try_region = NULL; 1768 struct leh_state this_state = *state; 1769 gimple_stmt_iterator gsi; 1770 tree out_label; 1771 gimple_seq new_seq, cleanup; 1772 gimple *x; 1773 geh_dispatch *eh_dispatch; 1774 location_t try_catch_loc = gimple_location (tp); 1775 location_t catch_loc = UNKNOWN_LOCATION; 1776 1777 if (flag_exceptions) 1778 { 1779 try_region = gen_eh_region_try (state->cur_region); 1780 this_state.cur_region = try_region; 1781 this_state.outer_non_cleanup = this_state.cur_region; 1782 } 1783 1784 lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp)); 1785 1786 if (!eh_region_may_contain_throw (try_region)) 1787 return gimple_try_eval (tp); 1788 1789 new_seq = NULL; 1790 eh_dispatch = gimple_build_eh_dispatch (try_region->index); 1791 gimple_seq_add_stmt (&new_seq, eh_dispatch); 1792 emit_resx (&new_seq, try_region); 1793 1794 this_state.cur_region = state->cur_region; 1795 this_state.outer_non_cleanup = state->outer_non_cleanup; 1796 this_state.ehp_region = try_region; 1797 1798 /* Add eh_seq from lowering EH in the cleanup sequence after the cleanup 1799 itself, so that e.g. for coverage purposes the nested cleanups don't 1800 appear before the cleanup body. See PR64634 for details. */ 1801 gimple_seq old_eh_seq = eh_seq; 1802 eh_seq = NULL; 1803 1804 out_label = NULL; 1805 cleanup = gimple_try_cleanup (tp); 1806 for (gsi = gsi_start (cleanup); 1807 !gsi_end_p (gsi); 1808 gsi_next (&gsi)) 1809 { 1810 eh_catch c; 1811 gcatch *catch_stmt; 1812 gimple_seq handler; 1813 1814 catch_stmt = as_a <gcatch *> (gsi_stmt (gsi)); 1815 if (catch_loc == UNKNOWN_LOCATION) 1816 catch_loc = gimple_location (catch_stmt); 1817 c = gen_eh_region_catch (try_region, gimple_catch_types (catch_stmt)); 1818 1819 handler = gimple_catch_handler (catch_stmt); 1820 lower_eh_constructs_1 (&this_state, &handler); 1821 1822 c->label = create_artificial_label (UNKNOWN_LOCATION); 1823 x = gimple_build_label (c->label); 1824 gimple_seq_add_stmt (&new_seq, x); 1825 1826 gimple_seq_add_seq (&new_seq, handler); 1827 1828 if (gimple_seq_may_fallthru (new_seq)) 1829 { 1830 if (!out_label) 1831 out_label = create_artificial_label (try_catch_loc); 1832 1833 x = gimple_build_goto (out_label); 1834 gimple_seq_add_stmt (&new_seq, x); 1835 } 1836 if (!c->type_list) 1837 break; 1838 } 1839 1840 /* Try to set a location on the dispatching construct to avoid inheriting 1841 the location of the previous statement. */ 1842 gimple_set_location (eh_dispatch, catch_loc); 1843 1844 gimple_try_set_cleanup (tp, new_seq); 1845 1846 gimple_seq new_eh_seq = eh_seq; 1847 eh_seq = old_eh_seq; 1848 gimple_seq ret_seq = frob_into_branch_around (tp, try_region, out_label); 1849 gimple_seq_add_seq (&eh_seq, new_eh_seq); 1850 return ret_seq; 1851 } 1852 1853 /* A subroutine of lower_eh_constructs_1. Lower a GIMPLE_TRY with a 1854 GIMPLE_EH_FILTER to a sequence of labels and blocks, plus the exception 1855 region trees that record all the magic. */ 1856 1857 static gimple_seq 1858 lower_eh_filter (struct leh_state *state, gtry *tp) 1859 { 1860 struct leh_state this_state = *state; 1861 eh_region this_region = NULL; 1862 gimple *inner, *x; 1863 gimple_seq new_seq; 1864 1865 inner = gimple_seq_first_stmt (gimple_try_cleanup (tp)); 1866 1867 if (flag_exceptions) 1868 { 1869 this_region = gen_eh_region_allowed (state->cur_region, 1870 gimple_eh_filter_types (inner)); 1871 this_state.cur_region = this_region; 1872 this_state.outer_non_cleanup = this_state.cur_region; 1873 } 1874 1875 lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp)); 1876 1877 if (!eh_region_may_contain_throw (this_region)) 1878 return gimple_try_eval (tp); 1879 1880 this_state.cur_region = state->cur_region; 1881 this_state.ehp_region = this_region; 1882 1883 new_seq = NULL; 1884 x = gimple_build_eh_dispatch (this_region->index); 1885 gimple_set_location (x, gimple_location (tp)); 1886 gimple_seq_add_stmt (&new_seq, x); 1887 emit_resx (&new_seq, this_region); 1888 1889 this_region->u.allowed.label = create_artificial_label (UNKNOWN_LOCATION); 1890 x = gimple_build_label (this_region->u.allowed.label); 1891 gimple_seq_add_stmt (&new_seq, x); 1892 1893 lower_eh_constructs_1 (&this_state, gimple_eh_filter_failure_ptr (inner)); 1894 gimple_seq_add_seq (&new_seq, gimple_eh_filter_failure (inner)); 1895 1896 gimple_try_set_cleanup (tp, new_seq); 1897 1898 return frob_into_branch_around (tp, this_region, NULL); 1899 } 1900 1901 /* A subroutine of lower_eh_constructs_1. Lower a GIMPLE_TRY with 1902 an GIMPLE_EH_MUST_NOT_THROW to a sequence of labels and blocks, 1903 plus the exception region trees that record all the magic. */ 1904 1905 static gimple_seq 1906 lower_eh_must_not_throw (struct leh_state *state, gtry *tp) 1907 { 1908 struct leh_state this_state = *state; 1909 1910 if (flag_exceptions) 1911 { 1912 gimple *inner = gimple_seq_first_stmt (gimple_try_cleanup (tp)); 1913 eh_region this_region; 1914 1915 this_region = gen_eh_region_must_not_throw (state->cur_region); 1916 this_region->u.must_not_throw.failure_decl 1917 = gimple_eh_must_not_throw_fndecl ( 1918 as_a <geh_mnt *> (inner)); 1919 this_region->u.must_not_throw.failure_loc 1920 = LOCATION_LOCUS (gimple_location (tp)); 1921 1922 /* In order to get mangling applied to this decl, we must mark it 1923 used now. Otherwise, pass_ipa_free_lang_data won't think it 1924 needs to happen. */ 1925 TREE_USED (this_region->u.must_not_throw.failure_decl) = 1; 1926 1927 this_state.cur_region = this_region; 1928 this_state.outer_non_cleanup = this_state.cur_region; 1929 } 1930 1931 lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp)); 1932 1933 return gimple_try_eval (tp); 1934 } 1935 1936 /* Implement a cleanup expression. This is similar to try-finally, 1937 except that we only execute the cleanup block for exception edges. */ 1938 1939 static gimple_seq 1940 lower_cleanup (struct leh_state *state, gtry *tp) 1941 { 1942 struct leh_state this_state = *state; 1943 eh_region this_region = NULL; 1944 struct leh_tf_state fake_tf; 1945 gimple_seq result; 1946 bool cleanup_dead = cleanup_is_dead_in (state); 1947 1948 if (flag_exceptions && !cleanup_dead) 1949 { 1950 this_region = gen_eh_region_cleanup (state->cur_region); 1951 this_state.cur_region = this_region; 1952 this_state.outer_non_cleanup = state->outer_non_cleanup; 1953 } 1954 1955 lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp)); 1956 1957 if (cleanup_dead || !eh_region_may_contain_throw (this_region)) 1958 return gimple_try_eval (tp); 1959 1960 /* Build enough of a try-finally state so that we can reuse 1961 honor_protect_cleanup_actions. */ 1962 memset (&fake_tf, 0, sizeof (fake_tf)); 1963 fake_tf.top_p = fake_tf.try_finally_expr = tp; 1964 fake_tf.outer = state; 1965 fake_tf.region = this_region; 1966 fake_tf.may_fallthru = gimple_seq_may_fallthru (gimple_try_eval (tp)); 1967 fake_tf.may_throw = true; 1968 1969 honor_protect_cleanup_actions (state, NULL, &fake_tf); 1970 1971 if (fake_tf.may_throw) 1972 { 1973 /* In this case honor_protect_cleanup_actions had nothing to do, 1974 and we should process this normally. */ 1975 lower_eh_constructs_1 (state, gimple_try_cleanup_ptr (tp)); 1976 result = frob_into_branch_around (tp, this_region, 1977 fake_tf.fallthru_label); 1978 } 1979 else 1980 { 1981 /* In this case honor_protect_cleanup_actions did nearly all of 1982 the work. All we have left is to append the fallthru_label. */ 1983 1984 result = gimple_try_eval (tp); 1985 if (fake_tf.fallthru_label) 1986 { 1987 gimple *x = gimple_build_label (fake_tf.fallthru_label); 1988 gimple_seq_add_stmt (&result, x); 1989 } 1990 } 1991 return result; 1992 } 1993 1994 /* Main loop for lowering eh constructs. Also moves gsi to the next 1995 statement. */ 1996 1997 static void 1998 lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi) 1999 { 2000 gimple_seq replace; 2001 gimple *x; 2002 gimple *stmt = gsi_stmt (*gsi); 2003 2004 switch (gimple_code (stmt)) 2005 { 2006 case GIMPLE_CALL: 2007 { 2008 tree fndecl = gimple_call_fndecl (stmt); 2009 tree rhs, lhs; 2010 2011 if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) 2012 switch (DECL_FUNCTION_CODE (fndecl)) 2013 { 2014 case BUILT_IN_EH_POINTER: 2015 /* The front end may have generated a call to 2016 __builtin_eh_pointer (0) within a catch region. Replace 2017 this zero argument with the current catch region number. */ 2018 if (state->ehp_region) 2019 { 2020 tree nr = build_int_cst (integer_type_node, 2021 state->ehp_region->index); 2022 gimple_call_set_arg (stmt, 0, nr); 2023 } 2024 else 2025 { 2026 /* The user has dome something silly. Remove it. */ 2027 rhs = null_pointer_node; 2028 goto do_replace; 2029 } 2030 break; 2031 2032 case BUILT_IN_EH_FILTER: 2033 /* ??? This should never appear, but since it's a builtin it 2034 is accessible to abuse by users. Just remove it and 2035 replace the use with the arbitrary value zero. */ 2036 rhs = build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0); 2037 do_replace: 2038 lhs = gimple_call_lhs (stmt); 2039 x = gimple_build_assign (lhs, rhs); 2040 gsi_insert_before (gsi, x, GSI_SAME_STMT); 2041 /* FALLTHRU */ 2042 2043 case BUILT_IN_EH_COPY_VALUES: 2044 /* Likewise this should not appear. Remove it. */ 2045 gsi_remove (gsi, true); 2046 return; 2047 2048 default: 2049 break; 2050 } 2051 } 2052 /* FALLTHRU */ 2053 2054 case GIMPLE_ASSIGN: 2055 /* If the stmt can throw, use a new temporary for the assignment 2056 to a LHS. This makes sure the old value of the LHS is 2057 available on the EH edge. Only do so for statements that 2058 potentially fall through (no noreturn calls e.g.), otherwise 2059 this new assignment might create fake fallthru regions. */ 2060 if (stmt_could_throw_p (cfun, stmt) 2061 && gimple_has_lhs (stmt) 2062 && gimple_stmt_may_fallthru (stmt) 2063 && !tree_could_throw_p (gimple_get_lhs (stmt)) 2064 && is_gimple_reg_type (TREE_TYPE (gimple_get_lhs (stmt)))) 2065 { 2066 tree lhs = gimple_get_lhs (stmt); 2067 tree tmp = create_tmp_var (TREE_TYPE (lhs)); 2068 gimple *s = gimple_build_assign (lhs, tmp); 2069 gimple_set_location (s, gimple_location (stmt)); 2070 gimple_set_block (s, gimple_block (stmt)); 2071 gimple_set_lhs (stmt, tmp); 2072 gsi_insert_after (gsi, s, GSI_SAME_STMT); 2073 } 2074 /* Look for things that can throw exceptions, and record them. */ 2075 if (state->cur_region && stmt_could_throw_p (cfun, stmt)) 2076 { 2077 record_stmt_eh_region (state->cur_region, stmt); 2078 note_eh_region_may_contain_throw (state->cur_region); 2079 } 2080 break; 2081 2082 case GIMPLE_COND: 2083 case GIMPLE_GOTO: 2084 case GIMPLE_RETURN: 2085 maybe_record_in_goto_queue (state, stmt); 2086 break; 2087 2088 case GIMPLE_SWITCH: 2089 verify_norecord_switch_expr (state, as_a <gswitch *> (stmt)); 2090 break; 2091 2092 case GIMPLE_TRY: 2093 { 2094 gtry *try_stmt = as_a <gtry *> (stmt); 2095 if (gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY) 2096 replace = lower_try_finally (state, try_stmt); 2097 else 2098 { 2099 x = gimple_seq_first_stmt (gimple_try_cleanup (try_stmt)); 2100 if (!x) 2101 { 2102 replace = gimple_try_eval (try_stmt); 2103 lower_eh_constructs_1 (state, &replace); 2104 } 2105 else 2106 switch (gimple_code (x)) 2107 { 2108 case GIMPLE_CATCH: 2109 replace = lower_catch (state, try_stmt); 2110 break; 2111 case GIMPLE_EH_FILTER: 2112 replace = lower_eh_filter (state, try_stmt); 2113 break; 2114 case GIMPLE_EH_MUST_NOT_THROW: 2115 replace = lower_eh_must_not_throw (state, try_stmt); 2116 break; 2117 case GIMPLE_EH_ELSE: 2118 /* This code is only valid with GIMPLE_TRY_FINALLY. */ 2119 gcc_unreachable (); 2120 default: 2121 replace = lower_cleanup (state, try_stmt); 2122 break; 2123 } 2124 } 2125 } 2126 2127 /* Remove the old stmt and insert the transformed sequence 2128 instead. */ 2129 gsi_insert_seq_before (gsi, replace, GSI_SAME_STMT); 2130 gsi_remove (gsi, true); 2131 2132 /* Return since we don't want gsi_next () */ 2133 return; 2134 2135 case GIMPLE_EH_ELSE: 2136 /* We should be eliminating this in lower_try_finally et al. */ 2137 gcc_unreachable (); 2138 2139 default: 2140 /* A type, a decl, or some kind of statement that we're not 2141 interested in. Don't walk them. */ 2142 break; 2143 } 2144 2145 gsi_next (gsi); 2146 } 2147 2148 /* A helper to unwrap a gimple_seq and feed stmts to lower_eh_constructs_2. */ 2149 2150 static void 2151 lower_eh_constructs_1 (struct leh_state *state, gimple_seq *pseq) 2152 { 2153 gimple_stmt_iterator gsi; 2154 for (gsi = gsi_start (*pseq); !gsi_end_p (gsi);) 2155 lower_eh_constructs_2 (state, &gsi); 2156 } 2157 2158 namespace { 2159 2160 const pass_data pass_data_lower_eh = 2161 { 2162 GIMPLE_PASS, /* type */ 2163 "eh", /* name */ 2164 OPTGROUP_NONE, /* optinfo_flags */ 2165 TV_TREE_EH, /* tv_id */ 2166 PROP_gimple_lcf, /* properties_required */ 2167 PROP_gimple_leh, /* properties_provided */ 2168 0, /* properties_destroyed */ 2169 0, /* todo_flags_start */ 2170 0, /* todo_flags_finish */ 2171 }; 2172 2173 class pass_lower_eh : public gimple_opt_pass 2174 { 2175 public: 2176 pass_lower_eh (gcc::context *ctxt) 2177 : gimple_opt_pass (pass_data_lower_eh, ctxt) 2178 {} 2179 2180 /* opt_pass methods: */ 2181 unsigned int execute (function *) final override; 2182 2183 }; // class pass_lower_eh 2184 2185 unsigned int 2186 pass_lower_eh::execute (function *fun) 2187 { 2188 struct leh_state null_state; 2189 gimple_seq bodyp; 2190 2191 bodyp = gimple_body (current_function_decl); 2192 if (bodyp == NULL) 2193 return 0; 2194 2195 finally_tree = new hash_table<finally_tree_hasher> (31); 2196 eh_region_may_contain_throw_map = BITMAP_ALLOC (NULL); 2197 memset (&null_state, 0, sizeof (null_state)); 2198 2199 collect_finally_tree_1 (bodyp, NULL); 2200 lower_eh_constructs_1 (&null_state, &bodyp); 2201 gimple_set_body (current_function_decl, bodyp); 2202 2203 /* We assume there's a return statement, or something, at the end of 2204 the function, and thus ploping the EH sequence afterward won't 2205 change anything. */ 2206 gcc_assert (!gimple_seq_may_fallthru (bodyp)); 2207 gimple_seq_add_seq (&bodyp, eh_seq); 2208 2209 /* We assume that since BODYP already existed, adding EH_SEQ to it 2210 didn't change its value, and we don't have to re-set the function. */ 2211 gcc_assert (bodyp == gimple_body (current_function_decl)); 2212 2213 delete finally_tree; 2214 finally_tree = NULL; 2215 BITMAP_FREE (eh_region_may_contain_throw_map); 2216 eh_seq = NULL; 2217 2218 /* If this function needs a language specific EH personality routine 2219 and the frontend didn't already set one do so now. */ 2220 if (function_needs_eh_personality (fun) == eh_personality_lang 2221 && !DECL_FUNCTION_PERSONALITY (current_function_decl)) 2222 DECL_FUNCTION_PERSONALITY (current_function_decl) 2223 = lang_hooks.eh_personality (); 2224 2225 return 0; 2226 } 2227 2228 } // anon namespace 2229 2230 gimple_opt_pass * 2231 make_pass_lower_eh (gcc::context *ctxt) 2232 { 2233 return new pass_lower_eh (ctxt); 2234 } 2235 2236 /* Create the multiple edges from an EH_DISPATCH statement to all of 2238 the possible handlers for its EH region. Return true if there's 2239 no fallthru edge; false if there is. */ 2240 2241 bool 2242 make_eh_dispatch_edges (geh_dispatch *stmt) 2243 { 2244 eh_region r; 2245 eh_catch c; 2246 basic_block src, dst; 2247 2248 r = get_eh_region_from_number (gimple_eh_dispatch_region (stmt)); 2249 src = gimple_bb (stmt); 2250 2251 switch (r->type) 2252 { 2253 case ERT_TRY: 2254 for (c = r->u.eh_try.first_catch; c ; c = c->next_catch) 2255 { 2256 dst = label_to_block (cfun, c->label); 2257 make_edge (src, dst, 0); 2258 2259 /* A catch-all handler doesn't have a fallthru. */ 2260 if (c->type_list == NULL) 2261 return false; 2262 } 2263 break; 2264 2265 case ERT_ALLOWED_EXCEPTIONS: 2266 dst = label_to_block (cfun, r->u.allowed.label); 2267 make_edge (src, dst, 0); 2268 break; 2269 2270 default: 2271 gcc_unreachable (); 2272 } 2273 2274 return true; 2275 } 2276 2277 /* Create the single EH edge from STMT to its nearest landing pad, 2278 if there is such a landing pad within the current function. */ 2279 2280 edge 2281 make_eh_edge (gimple *stmt) 2282 { 2283 basic_block src, dst; 2284 eh_landing_pad lp; 2285 int lp_nr; 2286 2287 lp_nr = lookup_stmt_eh_lp (stmt); 2288 if (lp_nr <= 0) 2289 return NULL; 2290 2291 lp = get_eh_landing_pad_from_number (lp_nr); 2292 gcc_assert (lp != NULL); 2293 2294 src = gimple_bb (stmt); 2295 dst = label_to_block (cfun, lp->post_landing_pad); 2296 return make_edge (src, dst, EDGE_EH); 2297 } 2298 2299 /* Do the work in redirecting EDGE_IN to NEW_BB within the EH region tree; 2300 do not actually perform the final edge redirection. 2301 2302 CHANGE_REGION is true when we're being called from cleanup_empty_eh and 2303 we intend to change the destination EH region as well; this means 2304 EH_LANDING_PAD_NR must already be set on the destination block label. 2305 If false, we're being called from generic cfg manipulation code and we 2306 should preserve our place within the region tree. */ 2307 2308 static void 2309 redirect_eh_edge_1 (edge edge_in, basic_block new_bb, bool change_region) 2310 { 2311 eh_landing_pad old_lp, new_lp; 2312 basic_block old_bb; 2313 gimple *throw_stmt; 2314 int old_lp_nr, new_lp_nr; 2315 tree old_label, new_label; 2316 edge_iterator ei; 2317 edge e; 2318 2319 old_bb = edge_in->dest; 2320 old_label = gimple_block_label (old_bb); 2321 old_lp_nr = EH_LANDING_PAD_NR (old_label); 2322 gcc_assert (old_lp_nr > 0); 2323 old_lp = get_eh_landing_pad_from_number (old_lp_nr); 2324 2325 throw_stmt = *gsi_last_bb (edge_in->src); 2326 gcc_checking_assert (lookup_stmt_eh_lp (throw_stmt) == old_lp_nr); 2327 2328 new_label = gimple_block_label (new_bb); 2329 2330 /* Look for an existing region that might be using NEW_BB already. */ 2331 new_lp_nr = EH_LANDING_PAD_NR (new_label); 2332 if (new_lp_nr) 2333 { 2334 new_lp = get_eh_landing_pad_from_number (new_lp_nr); 2335 gcc_assert (new_lp); 2336 2337 /* Unless CHANGE_REGION is true, the new and old landing pad 2338 had better be associated with the same EH region. */ 2339 gcc_assert (change_region || new_lp->region == old_lp->region); 2340 } 2341 else 2342 { 2343 new_lp = NULL; 2344 gcc_assert (!change_region); 2345 } 2346 2347 /* Notice when we redirect the last EH edge away from OLD_BB. */ 2348 FOR_EACH_EDGE (e, ei, old_bb->preds) 2349 if (e != edge_in && (e->flags & EDGE_EH)) 2350 break; 2351 2352 if (new_lp) 2353 { 2354 /* NEW_LP already exists. If there are still edges into OLD_LP, 2355 there's nothing to do with the EH tree. If there are no more 2356 edges into OLD_LP, then we want to remove OLD_LP as it is unused. 2357 If CHANGE_REGION is true, then our caller is expecting to remove 2358 the landing pad. */ 2359 if (e == NULL && !change_region) 2360 remove_eh_landing_pad (old_lp); 2361 } 2362 else 2363 { 2364 /* No correct landing pad exists. If there are no more edges 2365 into OLD_LP, then we can simply re-use the existing landing pad. 2366 Otherwise, we have to create a new landing pad. */ 2367 if (e == NULL) 2368 { 2369 EH_LANDING_PAD_NR (old_lp->post_landing_pad) = 0; 2370 new_lp = old_lp; 2371 } 2372 else 2373 new_lp = gen_eh_landing_pad (old_lp->region); 2374 new_lp->post_landing_pad = new_label; 2375 EH_LANDING_PAD_NR (new_label) = new_lp->index; 2376 } 2377 2378 /* Maybe move the throwing statement to the new region. */ 2379 if (old_lp != new_lp) 2380 { 2381 remove_stmt_from_eh_lp (throw_stmt); 2382 add_stmt_to_eh_lp (throw_stmt, new_lp->index); 2383 } 2384 } 2385 2386 /* Redirect EH edge E to NEW_BB. */ 2387 2388 edge 2389 redirect_eh_edge (edge edge_in, basic_block new_bb) 2390 { 2391 redirect_eh_edge_1 (edge_in, new_bb, false); 2392 return ssa_redirect_edge (edge_in, new_bb); 2393 } 2394 2395 /* This is a subroutine of gimple_redirect_edge_and_branch. Update the 2396 labels for redirecting a non-fallthru EH_DISPATCH edge E to NEW_BB. 2397 The actual edge update will happen in the caller. */ 2398 2399 void 2400 redirect_eh_dispatch_edge (geh_dispatch *stmt, edge e, basic_block new_bb) 2401 { 2402 tree new_lab = gimple_block_label (new_bb); 2403 bool any_changed = false; 2404 basic_block old_bb; 2405 eh_region r; 2406 eh_catch c; 2407 2408 r = get_eh_region_from_number (gimple_eh_dispatch_region (stmt)); 2409 switch (r->type) 2410 { 2411 case ERT_TRY: 2412 for (c = r->u.eh_try.first_catch; c ; c = c->next_catch) 2413 { 2414 old_bb = label_to_block (cfun, c->label); 2415 if (old_bb == e->dest) 2416 { 2417 c->label = new_lab; 2418 any_changed = true; 2419 } 2420 } 2421 break; 2422 2423 case ERT_ALLOWED_EXCEPTIONS: 2424 old_bb = label_to_block (cfun, r->u.allowed.label); 2425 gcc_assert (old_bb == e->dest); 2426 r->u.allowed.label = new_lab; 2427 any_changed = true; 2428 break; 2429 2430 default: 2431 gcc_unreachable (); 2432 } 2433 2434 gcc_assert (any_changed); 2435 } 2436 2437 /* Helper function for operation_could_trap_p and stmt_could_throw_p. */ 2439 2440 bool 2441 operation_could_trap_helper_p (enum tree_code op, 2442 bool fp_operation, 2443 bool honor_trapv, 2444 bool honor_nans, 2445 bool honor_snans, 2446 tree divisor, 2447 bool *handled) 2448 { 2449 *handled = true; 2450 switch (op) 2451 { 2452 case TRUNC_DIV_EXPR: 2453 case CEIL_DIV_EXPR: 2454 case FLOOR_DIV_EXPR: 2455 case ROUND_DIV_EXPR: 2456 case EXACT_DIV_EXPR: 2457 case CEIL_MOD_EXPR: 2458 case FLOOR_MOD_EXPR: 2459 case ROUND_MOD_EXPR: 2460 case TRUNC_MOD_EXPR: 2461 if (!TREE_CONSTANT (divisor) || integer_zerop (divisor)) 2462 return true; 2463 if (TREE_CODE (divisor) == VECTOR_CST) 2464 { 2465 /* Inspired by initializer_each_zero_or_onep. */ 2466 unsigned HOST_WIDE_INT nelts = vector_cst_encoded_nelts (divisor); 2467 if (VECTOR_CST_STEPPED_P (divisor) 2468 && !TYPE_VECTOR_SUBPARTS (TREE_TYPE (divisor)) 2469 .is_constant (&nelts)) 2470 return true; 2471 for (unsigned int i = 0; i < nelts; ++i) 2472 { 2473 tree elt = vector_cst_elt (divisor, i); 2474 if (integer_zerop (elt)) 2475 return true; 2476 } 2477 } 2478 return false; 2479 2480 case RDIV_EXPR: 2481 if (fp_operation) 2482 { 2483 if (honor_snans) 2484 return true; 2485 return flag_trapping_math; 2486 } 2487 /* Fixed point operations also use RDIV_EXPR. */ 2488 if (!TREE_CONSTANT (divisor) || fixed_zerop (divisor)) 2489 return true; 2490 return false; 2491 2492 case LT_EXPR: 2493 case LE_EXPR: 2494 case GT_EXPR: 2495 case GE_EXPR: 2496 case LTGT_EXPR: 2497 /* MIN/MAX similar as LT/LE/GT/GE. */ 2498 case MIN_EXPR: 2499 case MAX_EXPR: 2500 /* Some floating point comparisons may trap. */ 2501 return honor_nans; 2502 2503 case EQ_EXPR: 2504 case NE_EXPR: 2505 case UNORDERED_EXPR: 2506 case ORDERED_EXPR: 2507 case UNLT_EXPR: 2508 case UNLE_EXPR: 2509 case UNGT_EXPR: 2510 case UNGE_EXPR: 2511 case UNEQ_EXPR: 2512 return honor_snans; 2513 2514 case NEGATE_EXPR: 2515 case ABS_EXPR: 2516 case CONJ_EXPR: 2517 /* These operations don't trap with floating point. */ 2518 if (honor_trapv) 2519 return true; 2520 return false; 2521 2522 case ABSU_EXPR: 2523 /* ABSU_EXPR never traps. */ 2524 return false; 2525 2526 case PLUS_EXPR: 2527 case MINUS_EXPR: 2528 case MULT_EXPR: 2529 /* Any floating arithmetic may trap. */ 2530 if (fp_operation && flag_trapping_math) 2531 return true; 2532 if (honor_trapv) 2533 return true; 2534 return false; 2535 2536 case COMPLEX_EXPR: 2537 case CONSTRUCTOR: 2538 /* Constructing an object cannot trap. */ 2539 return false; 2540 2541 case COND_EXPR: 2542 case VEC_COND_EXPR: 2543 /* Whether *COND_EXPR can trap depends on whether the 2544 first argument can trap, so signal it as not handled. 2545 Whether lhs is floating or not doesn't matter. */ 2546 *handled = false; 2547 return false; 2548 2549 default: 2550 /* Any floating arithmetic may trap. */ 2551 if (fp_operation && flag_trapping_math) 2552 return true; 2553 2554 *handled = false; 2555 return false; 2556 } 2557 } 2558 2559 /* Return true if operation OP may trap. FP_OPERATION is true if OP is applied 2560 on floating-point values. HONOR_TRAPV is true if OP is applied on integer 2561 type operands that may trap. If OP is a division operator, DIVISOR contains 2562 the value of the divisor. */ 2563 2564 bool 2565 operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv, 2566 tree divisor) 2567 { 2568 bool honor_nans = (fp_operation && flag_trapping_math 2569 && !flag_finite_math_only); 2570 bool honor_snans = fp_operation && flag_signaling_nans != 0; 2571 bool handled; 2572 2573 /* This function cannot tell whether or not COND_EXPR could trap, 2574 because that depends on its condition op. */ 2575 gcc_assert (op != COND_EXPR); 2576 2577 if (TREE_CODE_CLASS (op) != tcc_comparison 2578 && TREE_CODE_CLASS (op) != tcc_unary 2579 && TREE_CODE_CLASS (op) != tcc_binary) 2580 return false; 2581 2582 return operation_could_trap_helper_p (op, fp_operation, honor_trapv, 2583 honor_nans, honor_snans, divisor, 2584 &handled); 2585 } 2586 2587 2588 /* Returns true if it is possible to prove that the index of 2589 an array access REF (an ARRAY_REF expression) falls into the 2590 array bounds. */ 2591 2592 static bool 2593 in_array_bounds_p (tree ref) 2594 { 2595 tree idx = TREE_OPERAND (ref, 1); 2596 tree min, max; 2597 2598 if (TREE_CODE (idx) != INTEGER_CST) 2599 return false; 2600 2601 min = array_ref_low_bound (ref); 2602 max = array_ref_up_bound (ref); 2603 if (!min 2604 || !max 2605 || TREE_CODE (min) != INTEGER_CST 2606 || TREE_CODE (max) != INTEGER_CST) 2607 return false; 2608 2609 if (tree_int_cst_lt (idx, min) 2610 || tree_int_cst_lt (max, idx)) 2611 return false; 2612 2613 return true; 2614 } 2615 2616 /* Returns true if it is possible to prove that the range of 2617 an array access REF (an ARRAY_RANGE_REF expression) falls 2618 into the array bounds. */ 2619 2620 static bool 2621 range_in_array_bounds_p (tree ref) 2622 { 2623 tree domain_type = TYPE_DOMAIN (TREE_TYPE (ref)); 2624 tree range_min, range_max, min, max; 2625 2626 range_min = TYPE_MIN_VALUE (domain_type); 2627 range_max = TYPE_MAX_VALUE (domain_type); 2628 if (!range_min 2629 || !range_max 2630 || TREE_CODE (range_min) != INTEGER_CST 2631 || TREE_CODE (range_max) != INTEGER_CST) 2632 return false; 2633 2634 min = array_ref_low_bound (ref); 2635 max = array_ref_up_bound (ref); 2636 if (!min 2637 || !max 2638 || TREE_CODE (min) != INTEGER_CST 2639 || TREE_CODE (max) != INTEGER_CST) 2640 return false; 2641 2642 if (tree_int_cst_lt (range_min, min) 2643 || tree_int_cst_lt (max, range_max)) 2644 return false; 2645 2646 return true; 2647 } 2648 2649 /* Return true if EXPR can trap, as in dereferencing an invalid pointer 2650 location or floating point arithmetic. C.f. the rtl version, may_trap_p. 2651 This routine expects only GIMPLE lhs or rhs input. */ 2652 2653 bool 2654 tree_could_trap_p (tree expr) 2655 { 2656 enum tree_code code; 2657 bool fp_operation = false; 2658 bool honor_trapv = false; 2659 tree t, base, div = NULL_TREE; 2660 2661 if (!expr) 2662 return false; 2663 2664 /* In COND_EXPR and VEC_COND_EXPR only the condition may trap, but 2665 they won't appear as operands in GIMPLE form, so this is just for the 2666 GENERIC uses where it needs to recurse on the operands and so 2667 *COND_EXPR itself doesn't trap. */ 2668 if (TREE_CODE (expr) == COND_EXPR || TREE_CODE (expr) == VEC_COND_EXPR) 2669 return false; 2670 2671 code = TREE_CODE (expr); 2672 t = TREE_TYPE (expr); 2673 2674 if (t) 2675 { 2676 if (COMPARISON_CLASS_P (expr)) 2677 fp_operation = FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0))); 2678 else 2679 fp_operation = FLOAT_TYPE_P (t); 2680 honor_trapv = INTEGRAL_TYPE_P (t) && TYPE_OVERFLOW_TRAPS (t); 2681 } 2682 2683 if (TREE_CODE_CLASS (code) == tcc_binary) 2684 div = TREE_OPERAND (expr, 1); 2685 if (operation_could_trap_p (code, fp_operation, honor_trapv, div)) 2686 return true; 2687 2688 restart: 2689 switch (code) 2690 { 2691 case COMPONENT_REF: 2692 case REALPART_EXPR: 2693 case IMAGPART_EXPR: 2694 case BIT_FIELD_REF: 2695 case VIEW_CONVERT_EXPR: 2696 case WITH_SIZE_EXPR: 2697 expr = TREE_OPERAND (expr, 0); 2698 code = TREE_CODE (expr); 2699 goto restart; 2700 2701 case ARRAY_RANGE_REF: 2702 base = TREE_OPERAND (expr, 0); 2703 if (tree_could_trap_p (base)) 2704 return true; 2705 if (TREE_THIS_NOTRAP (expr)) 2706 return false; 2707 return !range_in_array_bounds_p (expr); 2708 2709 case ARRAY_REF: 2710 base = TREE_OPERAND (expr, 0); 2711 if (tree_could_trap_p (base)) 2712 return true; 2713 if (TREE_THIS_NOTRAP (expr)) 2714 return false; 2715 return !in_array_bounds_p (expr); 2716 2717 case TARGET_MEM_REF: 2718 case MEM_REF: 2719 if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR 2720 && tree_could_trap_p (TREE_OPERAND (TREE_OPERAND (expr, 0), 0))) 2721 return true; 2722 if (TREE_THIS_NOTRAP (expr)) 2723 return false; 2724 /* We cannot prove that the access is in-bounds when we have 2725 variable-index TARGET_MEM_REFs. */ 2726 if (code == TARGET_MEM_REF 2727 && (TMR_INDEX (expr) || TMR_INDEX2 (expr))) 2728 return true; 2729 if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR) 2730 { 2731 tree base = TREE_OPERAND (TREE_OPERAND (expr, 0), 0); 2732 poly_offset_int off = mem_ref_offset (expr); 2733 if (maybe_lt (off, 0)) 2734 return true; 2735 if (TREE_CODE (base) == STRING_CST) 2736 return maybe_le (TREE_STRING_LENGTH (base), off); 2737 tree size = DECL_SIZE_UNIT (base); 2738 tree refsz = TYPE_SIZE_UNIT (TREE_TYPE (expr)); 2739 if (size == NULL_TREE 2740 || refsz == NULL_TREE 2741 || !poly_int_tree_p (size) 2742 || !poly_int_tree_p (refsz) 2743 || maybe_le (wi::to_poly_offset (size), off) 2744 || maybe_gt (off + wi::to_poly_offset (refsz), 2745 wi::to_poly_offset (size))) 2746 return true; 2747 /* Now we are sure the whole base of the access is inside 2748 the object. */ 2749 return false; 2750 } 2751 return true; 2752 2753 case INDIRECT_REF: 2754 return !TREE_THIS_NOTRAP (expr); 2755 2756 case ASM_EXPR: 2757 return TREE_THIS_VOLATILE (expr); 2758 2759 case CALL_EXPR: 2760 /* Internal function calls do not trap. */ 2761 if (CALL_EXPR_FN (expr) == NULL_TREE) 2762 return false; 2763 t = get_callee_fndecl (expr); 2764 /* Assume that indirect and calls to weak functions may trap. */ 2765 if (!t || !DECL_P (t)) 2766 return true; 2767 if (DECL_WEAK (t)) 2768 return tree_could_trap_p (t); 2769 return false; 2770 2771 case FUNCTION_DECL: 2772 /* Assume that accesses to weak functions may trap, unless we know 2773 they are certainly defined in current TU or in some other 2774 LTO partition. */ 2775 if (DECL_WEAK (expr) && !DECL_COMDAT (expr) && DECL_EXTERNAL (expr)) 2776 { 2777 cgraph_node *node = cgraph_node::get (expr); 2778 if (node) 2779 node = node->function_symbol (); 2780 return !(node && node->in_other_partition); 2781 } 2782 return false; 2783 2784 case VAR_DECL: 2785 /* Assume that accesses to weak vars may trap, unless we know 2786 they are certainly defined in current TU or in some other 2787 LTO partition. */ 2788 if (DECL_WEAK (expr) && !DECL_COMDAT (expr) && DECL_EXTERNAL (expr)) 2789 { 2790 varpool_node *node = varpool_node::get (expr); 2791 if (node) 2792 node = node->ultimate_alias_target (); 2793 return !(node && node->in_other_partition); 2794 } 2795 return false; 2796 2797 default: 2798 return false; 2799 } 2800 } 2801 2802 /* Return non-NULL if there is an integer operation with trapping overflow 2803 we can rewrite into non-trapping. Called via walk_tree from 2804 rewrite_to_non_trapping_overflow. */ 2805 2806 static tree 2807 find_trapping_overflow (tree *tp, int *walk_subtrees, void *data) 2808 { 2809 if (EXPR_P (*tp) 2810 && ANY_INTEGRAL_TYPE_P (TREE_TYPE (*tp)) 2811 && !operation_no_trapping_overflow (TREE_TYPE (*tp), TREE_CODE (*tp))) 2812 return *tp; 2813 if (IS_TYPE_OR_DECL_P (*tp) 2814 || (TREE_CODE (*tp) == SAVE_EXPR && data == NULL)) 2815 *walk_subtrees = 0; 2816 return NULL_TREE; 2817 } 2818 2819 /* Rewrite selected operations into unsigned arithmetics, so that they 2820 don't trap on overflow. */ 2821 2822 static tree 2823 replace_trapping_overflow (tree *tp, int *walk_subtrees, void *data) 2824 { 2825 if (find_trapping_overflow (tp, walk_subtrees, data)) 2826 { 2827 tree type = TREE_TYPE (*tp); 2828 tree utype = unsigned_type_for (type); 2829 *walk_subtrees = 0; 2830 int len = TREE_OPERAND_LENGTH (*tp); 2831 for (int i = 0; i < len; ++i) 2832 walk_tree (&TREE_OPERAND (*tp, i), replace_trapping_overflow, 2833 data, (hash_set<tree> *) data); 2834 2835 if (TREE_CODE (*tp) == ABS_EXPR) 2836 { 2837 TREE_SET_CODE (*tp, ABSU_EXPR); 2838 TREE_TYPE (*tp) = utype; 2839 *tp = fold_convert (type, *tp); 2840 } 2841 else 2842 { 2843 TREE_TYPE (*tp) = utype; 2844 len = TREE_OPERAND_LENGTH (*tp); 2845 for (int i = 0; i < len; ++i) 2846 TREE_OPERAND (*tp, i) 2847 = fold_convert (utype, TREE_OPERAND (*tp, i)); 2848 *tp = fold_convert (type, *tp); 2849 } 2850 } 2851 return NULL_TREE; 2852 } 2853 2854 /* If any subexpression of EXPR can trap due to -ftrapv, rewrite it 2855 using unsigned arithmetics to avoid traps in it. */ 2856 2857 tree 2858 rewrite_to_non_trapping_overflow (tree expr) 2859 { 2860 if (!flag_trapv) 2861 return expr; 2862 hash_set<tree> pset; 2863 if (!walk_tree (&expr, find_trapping_overflow, &pset, &pset)) 2864 return expr; 2865 expr = unshare_expr (expr); 2866 pset.empty (); 2867 walk_tree (&expr, replace_trapping_overflow, &pset, &pset); 2868 return expr; 2869 } 2870 2871 /* Helper for stmt_could_throw_p. Return true if STMT (assumed to be a 2872 an assignment or a conditional) may throw. */ 2873 2874 static bool 2875 stmt_could_throw_1_p (gassign *stmt) 2876 { 2877 enum tree_code code = gimple_assign_rhs_code (stmt); 2878 bool honor_nans = false; 2879 bool honor_snans = false; 2880 bool fp_operation = false; 2881 bool honor_trapv = false; 2882 tree t; 2883 size_t i; 2884 bool handled, ret; 2885 2886 if (TREE_CODE_CLASS (code) == tcc_comparison 2887 || TREE_CODE_CLASS (code) == tcc_unary 2888 || TREE_CODE_CLASS (code) == tcc_binary) 2889 { 2890 if (TREE_CODE_CLASS (code) == tcc_comparison) 2891 t = TREE_TYPE (gimple_assign_rhs1 (stmt)); 2892 else 2893 t = TREE_TYPE (gimple_assign_lhs (stmt)); 2894 fp_operation = FLOAT_TYPE_P (t); 2895 if (fp_operation) 2896 { 2897 honor_nans = flag_trapping_math && !flag_finite_math_only; 2898 honor_snans = flag_signaling_nans != 0; 2899 } 2900 else if (INTEGRAL_TYPE_P (t) && TYPE_OVERFLOW_TRAPS (t)) 2901 honor_trapv = true; 2902 } 2903 2904 /* First check the LHS. */ 2905 if (tree_could_trap_p (gimple_assign_lhs (stmt))) 2906 return true; 2907 2908 /* Check if the main expression may trap. */ 2909 ret = operation_could_trap_helper_p (code, fp_operation, honor_trapv, 2910 honor_nans, honor_snans, 2911 gimple_assign_rhs2 (stmt), 2912 &handled); 2913 if (handled) 2914 return ret; 2915 2916 /* If the expression does not trap, see if any of the individual operands may 2917 trap. */ 2918 for (i = 1; i < gimple_num_ops (stmt); i++) 2919 if (tree_could_trap_p (gimple_op (stmt, i))) 2920 return true; 2921 2922 return false; 2923 } 2924 2925 2926 /* Return true if statement STMT within FUN could throw an exception. */ 2927 2928 bool 2929 stmt_could_throw_p (function *fun, gimple *stmt) 2930 { 2931 if (!flag_exceptions) 2932 return false; 2933 2934 /* The only statements that can throw an exception are assignments, 2935 conditionals, calls, resx, and asms. */ 2936 switch (gimple_code (stmt)) 2937 { 2938 case GIMPLE_RESX: 2939 return true; 2940 2941 case GIMPLE_CALL: 2942 return !gimple_call_nothrow_p (as_a <gcall *> (stmt)); 2943 2944 case GIMPLE_COND: 2945 { 2946 if (fun && !fun->can_throw_non_call_exceptions) 2947 return false; 2948 gcond *cond = as_a <gcond *> (stmt); 2949 tree lhs = gimple_cond_lhs (cond); 2950 return operation_could_trap_p (gimple_cond_code (cond), 2951 FLOAT_TYPE_P (TREE_TYPE (lhs)), 2952 false, NULL_TREE); 2953 } 2954 2955 case GIMPLE_ASSIGN: 2956 if ((fun && !fun->can_throw_non_call_exceptions) 2957 || gimple_clobber_p (stmt)) 2958 return false; 2959 return stmt_could_throw_1_p (as_a <gassign *> (stmt)); 2960 2961 case GIMPLE_ASM: 2962 if (fun && !fun->can_throw_non_call_exceptions) 2963 return false; 2964 return gimple_asm_volatile_p (as_a <gasm *> (stmt)); 2965 2966 default: 2967 return false; 2968 } 2969 } 2970 2971 /* Return true if STMT in function FUN must be assumed necessary because of 2972 non-call exceptions. */ 2973 2974 bool 2975 stmt_unremovable_because_of_non_call_eh_p (function *fun, gimple *stmt) 2976 { 2977 return (fun->can_throw_non_call_exceptions 2978 && !fun->can_delete_dead_exceptions 2979 && stmt_could_throw_p (fun, stmt)); 2980 } 2981 2982 /* Return true if expression T could throw an exception. */ 2983 2984 bool 2985 tree_could_throw_p (tree t) 2986 { 2987 if (!flag_exceptions) 2988 return false; 2989 if (TREE_CODE (t) == MODIFY_EXPR) 2990 { 2991 if (cfun->can_throw_non_call_exceptions 2992 && tree_could_trap_p (TREE_OPERAND (t, 0))) 2993 return true; 2994 t = TREE_OPERAND (t, 1); 2995 } 2996 2997 if (TREE_CODE (t) == WITH_SIZE_EXPR) 2998 t = TREE_OPERAND (t, 0); 2999 if (TREE_CODE (t) == CALL_EXPR) 3000 return (call_expr_flags (t) & ECF_NOTHROW) == 0; 3001 if (cfun->can_throw_non_call_exceptions) 3002 return tree_could_trap_p (t); 3003 return false; 3004 } 3005 3006 /* Return true if STMT can throw an exception that is not caught within its 3007 function FUN. FUN can be NULL but the function is extra conservative 3008 then. */ 3009 3010 bool 3011 stmt_can_throw_external (function *fun, gimple *stmt) 3012 { 3013 int lp_nr; 3014 3015 if (!stmt_could_throw_p (fun, stmt)) 3016 return false; 3017 if (!fun) 3018 return true; 3019 3020 lp_nr = lookup_stmt_eh_lp_fn (fun, stmt); 3021 return lp_nr == 0; 3022 } 3023 3024 /* Return true if STMT can throw an exception that is caught within its 3025 function FUN. */ 3026 3027 bool 3028 stmt_can_throw_internal (function *fun, gimple *stmt) 3029 { 3030 int lp_nr; 3031 3032 gcc_checking_assert (fun); 3033 if (!stmt_could_throw_p (fun, stmt)) 3034 return false; 3035 3036 lp_nr = lookup_stmt_eh_lp_fn (fun, stmt); 3037 return lp_nr > 0; 3038 } 3039 3040 /* Given a statement STMT in IFUN, if STMT can no longer throw, then 3041 remove any entry it might have from the EH table. Return true if 3042 any change was made. */ 3043 3044 bool 3045 maybe_clean_eh_stmt_fn (struct function *ifun, gimple *stmt) 3046 { 3047 if (stmt_could_throw_p (ifun, stmt)) 3048 return false; 3049 return remove_stmt_from_eh_lp_fn (ifun, stmt); 3050 } 3051 3052 /* Likewise, but always use the current function. */ 3053 3054 bool 3055 maybe_clean_eh_stmt (gimple *stmt) 3056 { 3057 return maybe_clean_eh_stmt_fn (cfun, stmt); 3058 } 3059 3060 /* Given a statement OLD_STMT and a new statement NEW_STMT that has replaced 3061 OLD_STMT in the function, remove OLD_STMT from the EH table and put NEW_STMT 3062 in the table if it should be in there. Return TRUE if a replacement was 3063 done that my require an EH edge purge. */ 3064 3065 bool 3066 maybe_clean_or_replace_eh_stmt (gimple *old_stmt, gimple *new_stmt) 3067 { 3068 int lp_nr = lookup_stmt_eh_lp (old_stmt); 3069 3070 if (lp_nr != 0) 3071 { 3072 bool new_stmt_could_throw = stmt_could_throw_p (cfun, new_stmt); 3073 3074 if (new_stmt == old_stmt && new_stmt_could_throw) 3075 return false; 3076 3077 remove_stmt_from_eh_lp (old_stmt); 3078 if (new_stmt_could_throw) 3079 { 3080 add_stmt_to_eh_lp (new_stmt, lp_nr); 3081 return false; 3082 } 3083 else 3084 return true; 3085 } 3086 3087 return false; 3088 } 3089 3090 /* Given a statement OLD_STMT in OLD_FUN and a duplicate statement NEW_STMT 3091 in NEW_FUN, copy the EH table data from OLD_STMT to NEW_STMT. The MAP 3092 operand is the return value of duplicate_eh_regions. */ 3093 3094 bool 3095 maybe_duplicate_eh_stmt_fn (struct function *new_fun, gimple *new_stmt, 3096 struct function *old_fun, gimple *old_stmt, 3097 hash_map<void *, void *> *map, 3098 int default_lp_nr) 3099 { 3100 int old_lp_nr, new_lp_nr; 3101 3102 if (!stmt_could_throw_p (new_fun, new_stmt)) 3103 return false; 3104 3105 old_lp_nr = lookup_stmt_eh_lp_fn (old_fun, old_stmt); 3106 if (old_lp_nr == 0) 3107 { 3108 if (default_lp_nr == 0) 3109 return false; 3110 new_lp_nr = default_lp_nr; 3111 } 3112 else if (old_lp_nr > 0) 3113 { 3114 eh_landing_pad old_lp, new_lp; 3115 3116 old_lp = (*old_fun->eh->lp_array)[old_lp_nr]; 3117 new_lp = static_cast<eh_landing_pad> (*map->get (old_lp)); 3118 new_lp_nr = new_lp->index; 3119 } 3120 else 3121 { 3122 eh_region old_r, new_r; 3123 3124 old_r = (*old_fun->eh->region_array)[-old_lp_nr]; 3125 new_r = static_cast<eh_region> (*map->get (old_r)); 3126 new_lp_nr = -new_r->index; 3127 } 3128 3129 add_stmt_to_eh_lp_fn (new_fun, new_stmt, new_lp_nr); 3130 return true; 3131 } 3132 3133 /* Similar, but both OLD_STMT and NEW_STMT are within the current function, 3134 and thus no remapping is required. */ 3135 3136 bool 3137 maybe_duplicate_eh_stmt (gimple *new_stmt, gimple *old_stmt) 3138 { 3139 int lp_nr; 3140 3141 if (!stmt_could_throw_p (cfun, new_stmt)) 3142 return false; 3143 3144 lp_nr = lookup_stmt_eh_lp (old_stmt); 3145 if (lp_nr == 0) 3146 return false; 3147 3148 add_stmt_to_eh_lp (new_stmt, lp_nr); 3149 return true; 3150 } 3151 3152 /* Returns TRUE if oneh and twoh are exception handlers (gimple_try_cleanup of 3154 GIMPLE_TRY) that are similar enough to be considered the same. Currently 3155 this only handles handlers consisting of a single call, as that's the 3156 important case for C++: a destructor call for a particular object showing 3157 up in multiple handlers. */ 3158 3159 static bool 3160 same_handler_p (gimple_seq oneh, gimple_seq twoh) 3161 { 3162 gimple_stmt_iterator gsi; 3163 gimple *ones, *twos; 3164 unsigned int ai; 3165 3166 gsi = gsi_start (oneh); 3167 if (!gsi_one_before_end_p (gsi)) 3168 return false; 3169 ones = gsi_stmt (gsi); 3170 3171 gsi = gsi_start (twoh); 3172 if (!gsi_one_before_end_p (gsi)) 3173 return false; 3174 twos = gsi_stmt (gsi); 3175 3176 if (!is_gimple_call (ones) 3177 || !is_gimple_call (twos) 3178 || gimple_call_lhs (ones) 3179 || gimple_call_lhs (twos) 3180 || gimple_call_chain (ones) 3181 || gimple_call_chain (twos) 3182 || !gimple_call_same_target_p (ones, twos) 3183 || gimple_call_num_args (ones) != gimple_call_num_args (twos)) 3184 return false; 3185 3186 for (ai = 0; ai < gimple_call_num_args (ones); ++ai) 3187 if (!operand_equal_p (gimple_call_arg (ones, ai), 3188 gimple_call_arg (twos, ai), 0)) 3189 return false; 3190 3191 return true; 3192 } 3193 3194 /* Optimize 3195 try { A() } finally { try { ~B() } catch { ~A() } } 3196 try { ... } finally { ~A() } 3197 into 3198 try { A() } catch { ~B() } 3199 try { ~B() ... } finally { ~A() } 3200 3201 This occurs frequently in C++, where A is a local variable and B is a 3202 temporary used in the initializer for A. */ 3203 3204 static void 3205 optimize_double_finally (gtry *one, gtry *two) 3206 { 3207 gimple *oneh; 3208 gimple_stmt_iterator gsi; 3209 gimple_seq cleanup; 3210 3211 cleanup = gimple_try_cleanup (one); 3212 gsi = gsi_start (cleanup); 3213 if (!gsi_one_before_end_p (gsi)) 3214 return; 3215 3216 oneh = gsi_stmt (gsi); 3217 if (gimple_code (oneh) != GIMPLE_TRY 3218 || gimple_try_kind (oneh) != GIMPLE_TRY_CATCH) 3219 return; 3220 3221 if (same_handler_p (gimple_try_cleanup (oneh), gimple_try_cleanup (two))) 3222 { 3223 gimple_seq seq = gimple_try_eval (oneh); 3224 3225 gimple_try_set_cleanup (one, seq); 3226 gimple_try_set_kind (one, GIMPLE_TRY_CATCH); 3227 seq = copy_gimple_seq_and_replace_locals (seq); 3228 gimple_seq_add_seq (&seq, gimple_try_eval (two)); 3229 gimple_try_set_eval (two, seq); 3230 } 3231 } 3232 3233 /* Perform EH refactoring optimizations that are simpler to do when code 3234 flow has been lowered but EH structures haven't. */ 3235 3236 static void 3237 refactor_eh_r (gimple_seq seq) 3238 { 3239 gimple_stmt_iterator gsi; 3240 gimple *one, *two; 3241 3242 one = NULL; 3243 two = NULL; 3244 gsi = gsi_start (seq); 3245 while (1) 3246 { 3247 one = two; 3248 if (gsi_end_p (gsi)) 3249 two = NULL; 3250 else 3251 two = gsi_stmt (gsi); 3252 if (one && two) 3253 if (gtry *try_one = dyn_cast <gtry *> (one)) 3254 if (gtry *try_two = dyn_cast <gtry *> (two)) 3255 if (gimple_try_kind (try_one) == GIMPLE_TRY_FINALLY 3256 && gimple_try_kind (try_two) == GIMPLE_TRY_FINALLY) 3257 optimize_double_finally (try_one, try_two); 3258 if (one) 3259 switch (gimple_code (one)) 3260 { 3261 case GIMPLE_TRY: 3262 refactor_eh_r (gimple_try_eval (one)); 3263 refactor_eh_r (gimple_try_cleanup (one)); 3264 break; 3265 case GIMPLE_CATCH: 3266 refactor_eh_r (gimple_catch_handler (as_a <gcatch *> (one))); 3267 break; 3268 case GIMPLE_EH_FILTER: 3269 refactor_eh_r (gimple_eh_filter_failure (one)); 3270 break; 3271 case GIMPLE_EH_ELSE: 3272 { 3273 geh_else *eh_else_stmt = as_a <geh_else *> (one); 3274 refactor_eh_r (gimple_eh_else_n_body (eh_else_stmt)); 3275 refactor_eh_r (gimple_eh_else_e_body (eh_else_stmt)); 3276 } 3277 break; 3278 default: 3279 break; 3280 } 3281 if (two) 3282 gsi_next (&gsi); 3283 else 3284 break; 3285 } 3286 } 3287 3288 namespace { 3289 3290 const pass_data pass_data_refactor_eh = 3291 { 3292 GIMPLE_PASS, /* type */ 3293 "ehopt", /* name */ 3294 OPTGROUP_NONE, /* optinfo_flags */ 3295 TV_TREE_EH, /* tv_id */ 3296 PROP_gimple_lcf, /* properties_required */ 3297 0, /* properties_provided */ 3298 0, /* properties_destroyed */ 3299 0, /* todo_flags_start */ 3300 0, /* todo_flags_finish */ 3301 }; 3302 3303 class pass_refactor_eh : public gimple_opt_pass 3304 { 3305 public: 3306 pass_refactor_eh (gcc::context *ctxt) 3307 : gimple_opt_pass (pass_data_refactor_eh, ctxt) 3308 {} 3309 3310 /* opt_pass methods: */ 3311 bool gate (function *) final override { return flag_exceptions != 0; } 3312 unsigned int execute (function *) final override 3313 { 3314 refactor_eh_r (gimple_body (current_function_decl)); 3315 return 0; 3316 } 3317 3318 }; // class pass_refactor_eh 3319 3320 } // anon namespace 3321 3322 gimple_opt_pass * 3323 make_pass_refactor_eh (gcc::context *ctxt) 3324 { 3325 return new pass_refactor_eh (ctxt); 3326 } 3327 3328 /* At the end of gimple optimization, we can lower RESX. */ 3330 3331 static bool 3332 lower_resx (basic_block bb, gresx *stmt, 3333 hash_map<eh_region, tree> *mnt_map) 3334 { 3335 int lp_nr; 3336 eh_region src_r, dst_r; 3337 gimple_stmt_iterator gsi; 3338 gcall *x; 3339 tree fn, src_nr; 3340 bool ret = false; 3341 3342 lp_nr = lookup_stmt_eh_lp (stmt); 3343 if (lp_nr != 0) 3344 dst_r = get_eh_region_from_lp_number (lp_nr); 3345 else 3346 dst_r = NULL; 3347 3348 src_r = get_eh_region_from_number (gimple_resx_region (stmt)); 3349 gsi = gsi_last_bb (bb); 3350 3351 if (src_r == NULL) 3352 { 3353 /* We can wind up with no source region when pass_cleanup_eh shows 3354 that there are no entries into an eh region and deletes it, but 3355 then the block that contains the resx isn't removed. This can 3356 happen without optimization when the switch statement created by 3357 lower_try_finally_switch isn't simplified to remove the eh case. 3358 3359 Resolve this by expanding the resx node to an abort. */ 3360 3361 fn = builtin_decl_implicit (BUILT_IN_TRAP); 3362 x = gimple_build_call (fn, 0); 3363 gimple_call_set_ctrl_altering (x, true); 3364 gsi_insert_before (&gsi, x, GSI_SAME_STMT); 3365 3366 while (EDGE_COUNT (bb->succs) > 0) 3367 remove_edge (EDGE_SUCC (bb, 0)); 3368 } 3369 else if (dst_r) 3370 { 3371 /* When we have a destination region, we resolve this by copying 3372 the excptr and filter values into place, and changing the edge 3373 to immediately after the landing pad. */ 3374 edge e; 3375 3376 if (lp_nr < 0) 3377 { 3378 basic_block new_bb; 3379 tree lab; 3380 3381 /* We are resuming into a MUST_NOT_CALL region. Expand a call to 3382 the failure decl into a new block, if needed. */ 3383 gcc_assert (dst_r->type == ERT_MUST_NOT_THROW); 3384 3385 tree *slot = mnt_map->get (dst_r); 3386 if (slot == NULL) 3387 { 3388 gimple_stmt_iterator gsi2; 3389 3390 new_bb = create_empty_bb (bb); 3391 new_bb->count = bb->count; 3392 add_bb_to_loop (new_bb, bb->loop_father); 3393 lab = gimple_block_label (new_bb); 3394 gsi2 = gsi_start_bb (new_bb); 3395 3396 /* Handle failure fns that expect either no arguments or the 3397 exception pointer. */ 3398 fn = dst_r->u.must_not_throw.failure_decl; 3399 if (TYPE_ARG_TYPES (TREE_TYPE (fn)) != void_list_node) 3400 { 3401 tree epfn = builtin_decl_implicit (BUILT_IN_EH_POINTER); 3402 src_nr = build_int_cst (integer_type_node, src_r->index); 3403 x = gimple_build_call (epfn, 1, src_nr); 3404 tree var = create_tmp_var (ptr_type_node); 3405 var = make_ssa_name (var, x); 3406 gimple_call_set_lhs (x, var); 3407 gsi_insert_after (&gsi2, x, GSI_CONTINUE_LINKING); 3408 x = gimple_build_call (fn, 1, var); 3409 } 3410 else 3411 x = gimple_build_call (fn, 0); 3412 gimple_set_location (x, dst_r->u.must_not_throw.failure_loc); 3413 gsi_insert_after (&gsi2, x, GSI_CONTINUE_LINKING); 3414 3415 mnt_map->put (dst_r, lab); 3416 } 3417 else 3418 { 3419 lab = *slot; 3420 new_bb = label_to_block (cfun, lab); 3421 } 3422 3423 gcc_assert (EDGE_COUNT (bb->succs) == 0); 3424 e = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU); 3425 } 3426 else 3427 { 3428 edge_iterator ei; 3429 tree dst_nr = build_int_cst (integer_type_node, dst_r->index); 3430 3431 fn = builtin_decl_implicit (BUILT_IN_EH_COPY_VALUES); 3432 src_nr = build_int_cst (integer_type_node, src_r->index); 3433 x = gimple_build_call (fn, 2, dst_nr, src_nr); 3434 gsi_insert_before (&gsi, x, GSI_SAME_STMT); 3435 3436 /* Update the flags for the outgoing edge. */ 3437 e = single_succ_edge (bb); 3438 gcc_assert (e->flags & EDGE_EH); 3439 e->flags = (e->flags & ~EDGE_EH) | EDGE_FALLTHRU; 3440 e->probability = profile_probability::always (); 3441 3442 /* If there are no more EH users of the landing pad, delete it. */ 3443 FOR_EACH_EDGE (e, ei, e->dest->preds) 3444 if (e->flags & EDGE_EH) 3445 break; 3446 if (e == NULL) 3447 { 3448 eh_landing_pad lp = get_eh_landing_pad_from_number (lp_nr); 3449 remove_eh_landing_pad (lp); 3450 } 3451 } 3452 3453 ret = true; 3454 } 3455 else 3456 { 3457 tree var; 3458 3459 /* When we don't have a destination region, this exception escapes 3460 up the call chain. We resolve this by generating a call to the 3461 _Unwind_Resume library function. */ 3462 3463 /* The ARM EABI redefines _Unwind_Resume as __cxa_end_cleanup 3464 with no arguments for C++. Check for that. */ 3465 if (src_r->use_cxa_end_cleanup) 3466 { 3467 fn = builtin_decl_implicit (BUILT_IN_CXA_END_CLEANUP); 3468 x = gimple_build_call (fn, 0); 3469 gsi_insert_before (&gsi, x, GSI_SAME_STMT); 3470 } 3471 else 3472 { 3473 fn = builtin_decl_implicit (BUILT_IN_EH_POINTER); 3474 src_nr = build_int_cst (integer_type_node, src_r->index); 3475 x = gimple_build_call (fn, 1, src_nr); 3476 var = create_tmp_var (ptr_type_node); 3477 var = make_ssa_name (var, x); 3478 gimple_call_set_lhs (x, var); 3479 gsi_insert_before (&gsi, x, GSI_SAME_STMT); 3480 3481 /* When exception handling is delegated to a caller function, we 3482 have to guarantee that shadow memory variables living on stack 3483 will be cleaner before control is given to a parent function. */ 3484 if (sanitize_flags_p (SANITIZE_ADDRESS)) 3485 { 3486 tree decl 3487 = builtin_decl_implicit (BUILT_IN_ASAN_HANDLE_NO_RETURN); 3488 gimple *g = gimple_build_call (decl, 0); 3489 gimple_set_location (g, gimple_location (stmt)); 3490 gsi_insert_before (&gsi, g, GSI_SAME_STMT); 3491 } 3492 3493 fn = builtin_decl_implicit (BUILT_IN_UNWIND_RESUME); 3494 x = gimple_build_call (fn, 1, var); 3495 gimple_call_set_ctrl_altering (x, true); 3496 gsi_insert_before (&gsi, x, GSI_SAME_STMT); 3497 } 3498 3499 gcc_assert (EDGE_COUNT (bb->succs) == 0); 3500 } 3501 3502 gsi_remove (&gsi, true); 3503 3504 return ret; 3505 } 3506 3507 namespace { 3508 3509 const pass_data pass_data_lower_resx = 3510 { 3511 GIMPLE_PASS, /* type */ 3512 "resx", /* name */ 3513 OPTGROUP_NONE, /* optinfo_flags */ 3514 TV_TREE_EH, /* tv_id */ 3515 PROP_gimple_lcf, /* properties_required */ 3516 0, /* properties_provided */ 3517 0, /* properties_destroyed */ 3518 0, /* todo_flags_start */ 3519 0, /* todo_flags_finish */ 3520 }; 3521 3522 class pass_lower_resx : public gimple_opt_pass 3523 { 3524 public: 3525 pass_lower_resx (gcc::context *ctxt) 3526 : gimple_opt_pass (pass_data_lower_resx, ctxt) 3527 {} 3528 3529 /* opt_pass methods: */ 3530 bool gate (function *) final override { return flag_exceptions != 0; } 3531 unsigned int execute (function *) final override; 3532 3533 }; // class pass_lower_resx 3534 3535 unsigned 3536 pass_lower_resx::execute (function *fun) 3537 { 3538 basic_block bb; 3539 bool dominance_invalidated = false; 3540 bool any_rewritten = false; 3541 3542 hash_map<eh_region, tree> mnt_map; 3543 3544 FOR_EACH_BB_FN (bb, fun) 3545 { 3546 if (gresx *last = safe_dyn_cast <gresx *> (*gsi_last_bb (bb))) 3547 { 3548 dominance_invalidated |= lower_resx (bb, last, &mnt_map); 3549 any_rewritten = true; 3550 } 3551 } 3552 3553 if (dominance_invalidated) 3554 { 3555 free_dominance_info (CDI_DOMINATORS); 3556 free_dominance_info (CDI_POST_DOMINATORS); 3557 } 3558 3559 return any_rewritten ? TODO_update_ssa_only_virtuals : 0; 3560 } 3561 3562 } // anon namespace 3563 3564 gimple_opt_pass * 3565 make_pass_lower_resx (gcc::context *ctxt) 3566 { 3567 return new pass_lower_resx (ctxt); 3568 } 3569 3570 /* Try to optimize var = {v} {CLOBBER} stmts followed just by 3571 external throw. */ 3572 3573 static void 3574 optimize_clobbers (basic_block bb) 3575 { 3576 gimple_stmt_iterator gsi = gsi_last_bb (bb); 3577 bool any_clobbers = false; 3578 bool seen_stack_restore = false; 3579 edge_iterator ei; 3580 edge e; 3581 3582 /* Only optimize anything if the bb contains at least one clobber, 3583 ends with resx (checked by caller), optionally contains some 3584 debug stmts or labels, or at most one __builtin_stack_restore 3585 call, and has an incoming EH edge. */ 3586 for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi)) 3587 { 3588 gimple *stmt = gsi_stmt (gsi); 3589 if (is_gimple_debug (stmt)) 3590 continue; 3591 if (gimple_clobber_p (stmt)) 3592 { 3593 any_clobbers = true; 3594 continue; 3595 } 3596 if (!seen_stack_restore 3597 && gimple_call_builtin_p (stmt, BUILT_IN_STACK_RESTORE)) 3598 { 3599 seen_stack_restore = true; 3600 continue; 3601 } 3602 if (gimple_code (stmt) == GIMPLE_LABEL) 3603 break; 3604 return; 3605 } 3606 if (!any_clobbers) 3607 return; 3608 FOR_EACH_EDGE (e, ei, bb->preds) 3609 if (e->flags & EDGE_EH) 3610 break; 3611 if (e == NULL) 3612 return; 3613 gsi = gsi_last_bb (bb); 3614 for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi)) 3615 { 3616 gimple *stmt = gsi_stmt (gsi); 3617 if (!gimple_clobber_p (stmt)) 3618 continue; 3619 unlink_stmt_vdef (stmt); 3620 gsi_remove (&gsi, true); 3621 release_defs (stmt); 3622 } 3623 } 3624 3625 /* Try to sink var = {v} {CLOBBER} stmts followed just by 3626 internal throw to successor BB. 3627 SUNK, if not NULL, is an array of sequences indexed by basic-block 3628 index to sink to and to pick up sinking opportunities from. 3629 If FOUND_OPPORTUNITY is not NULL then do not perform the optimization 3630 but set *FOUND_OPPORTUNITY to true. */ 3631 3632 static int 3633 sink_clobbers (basic_block bb, 3634 gimple_seq *sunk = NULL, bool *found_opportunity = NULL) 3635 { 3636 edge e; 3637 edge_iterator ei; 3638 gimple_stmt_iterator gsi, dgsi; 3639 basic_block succbb; 3640 bool any_clobbers = false; 3641 unsigned todo = 0; 3642 3643 /* Only optimize if BB has a single EH successor and 3644 all predecessor edges are EH too. */ 3645 if (!single_succ_p (bb) 3646 || (single_succ_edge (bb)->flags & EDGE_EH) == 0) 3647 return 0; 3648 3649 FOR_EACH_EDGE (e, ei, bb->preds) 3650 { 3651 if ((e->flags & EDGE_EH) == 0) 3652 return 0; 3653 } 3654 3655 /* And BB contains only CLOBBER stmts before the final 3656 RESX. */ 3657 gsi = gsi_last_bb (bb); 3658 for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi)) 3659 { 3660 gimple *stmt = gsi_stmt (gsi); 3661 if (is_gimple_debug (stmt)) 3662 continue; 3663 if (gimple_code (stmt) == GIMPLE_LABEL) 3664 break; 3665 if (!gimple_clobber_p (stmt)) 3666 return 0; 3667 any_clobbers = true; 3668 } 3669 if (!any_clobbers && (!sunk || gimple_seq_empty_p (sunk[bb->index]))) 3670 return 0; 3671 3672 /* If this was a dry run, tell it we found clobbers to sink. */ 3673 if (found_opportunity) 3674 { 3675 *found_opportunity = true; 3676 return 0; 3677 } 3678 3679 edge succe = single_succ_edge (bb); 3680 succbb = succe->dest; 3681 3682 /* See if there is a virtual PHI node to take an updated virtual 3683 operand from. */ 3684 gphi *vphi = NULL; 3685 for (gphi_iterator gpi = gsi_start_phis (succbb); 3686 !gsi_end_p (gpi); gsi_next (&gpi)) 3687 { 3688 tree res = gimple_phi_result (gpi.phi ()); 3689 if (virtual_operand_p (res)) 3690 { 3691 vphi = gpi.phi (); 3692 break; 3693 } 3694 } 3695 3696 gimple *first_sunk = NULL; 3697 gimple *last_sunk = NULL; 3698 if (sunk && !(succbb->flags & BB_VISITED)) 3699 dgsi = gsi_start (sunk[succbb->index]); 3700 else 3701 dgsi = gsi_after_labels (succbb); 3702 gsi = gsi_last_bb (bb); 3703 for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi)) 3704 { 3705 gimple *stmt = gsi_stmt (gsi); 3706 tree lhs; 3707 if (is_gimple_debug (stmt)) 3708 continue; 3709 if (gimple_code (stmt) == GIMPLE_LABEL) 3710 break; 3711 lhs = gimple_assign_lhs (stmt); 3712 /* Unfortunately we don't have dominance info updated at this 3713 point, so checking if 3714 dominated_by_p (CDI_DOMINATORS, succbb, 3715 gimple_bb (SSA_NAME_DEF_STMT (TREE_OPERAND (lhs, 0))) 3716 would be too costly. Thus, avoid sinking any clobbers that 3717 refer to non-(D) SSA_NAMEs. */ 3718 if (TREE_CODE (lhs) == MEM_REF 3719 && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME 3720 && !SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (lhs, 0))) 3721 { 3722 unlink_stmt_vdef (stmt); 3723 gsi_remove (&gsi, true); 3724 release_defs (stmt); 3725 continue; 3726 } 3727 3728 /* As we do not change stmt order when sinking across a 3729 forwarder edge we can keep virtual operands in place. */ 3730 gsi_remove (&gsi, false); 3731 gsi_insert_before (&dgsi, stmt, GSI_NEW_STMT); 3732 if (!first_sunk) 3733 first_sunk = stmt; 3734 last_sunk = stmt; 3735 } 3736 if (sunk && !gimple_seq_empty_p (sunk[bb->index])) 3737 { 3738 if (!first_sunk) 3739 first_sunk = gsi_stmt (gsi_last (sunk[bb->index])); 3740 last_sunk = gsi_stmt (gsi_start (sunk[bb->index])); 3741 gsi_insert_seq_before_without_update (&dgsi, 3742 sunk[bb->index], GSI_NEW_STMT); 3743 sunk[bb->index] = NULL; 3744 } 3745 if (first_sunk) 3746 { 3747 /* Adjust virtual operands if we sunk across a virtual PHI. */ 3748 if (vphi) 3749 { 3750 imm_use_iterator iter; 3751 use_operand_p use_p; 3752 gimple *use_stmt; 3753 tree phi_def = gimple_phi_result (vphi); 3754 FOR_EACH_IMM_USE_STMT (use_stmt, iter, phi_def) 3755 FOR_EACH_IMM_USE_ON_STMT (use_p, iter) 3756 SET_USE (use_p, gimple_vdef (first_sunk)); 3757 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (phi_def)) 3758 { 3759 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_vdef (first_sunk)) = 1; 3760 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (phi_def) = 0; 3761 } 3762 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (vphi, succe), 3763 gimple_vuse (last_sunk)); 3764 SET_USE (gimple_vuse_op (last_sunk), phi_def); 3765 } 3766 /* If there isn't a single predecessor but no virtual PHI node 3767 arrange for virtual operands to be renamed. */ 3768 else if (!single_pred_p (succbb) 3769 && TREE_CODE (gimple_vuse (last_sunk)) == SSA_NAME) 3770 { 3771 mark_virtual_operand_for_renaming (gimple_vuse (last_sunk)); 3772 todo |= TODO_update_ssa_only_virtuals; 3773 } 3774 } 3775 3776 return todo; 3777 } 3778 3779 /* At the end of inlining, we can lower EH_DISPATCH. Return true when 3780 we have found some duplicate labels and removed some edges. */ 3781 3782 static bool 3783 lower_eh_dispatch (basic_block src, geh_dispatch *stmt) 3784 { 3785 gimple_stmt_iterator gsi; 3786 int region_nr; 3787 eh_region r; 3788 tree filter, fn; 3789 gimple *x; 3790 bool redirected = false; 3791 3792 region_nr = gimple_eh_dispatch_region (stmt); 3793 r = get_eh_region_from_number (region_nr); 3794 3795 gsi = gsi_last_bb (src); 3796 3797 switch (r->type) 3798 { 3799 case ERT_TRY: 3800 { 3801 auto_vec<tree> labels; 3802 tree default_label = NULL; 3803 eh_catch c; 3804 edge_iterator ei; 3805 edge e; 3806 hash_set<tree> seen_values; 3807 3808 /* Collect the labels for a switch. Zero the post_landing_pad 3809 field becase we'll no longer have anything keeping these labels 3810 in existence and the optimizer will be free to merge these 3811 blocks at will. */ 3812 for (c = r->u.eh_try.first_catch; c ; c = c->next_catch) 3813 { 3814 tree tp_node, flt_node, lab = c->label; 3815 bool have_label = false; 3816 3817 c->label = NULL; 3818 tp_node = c->type_list; 3819 flt_node = c->filter_list; 3820 3821 if (tp_node == NULL) 3822 { 3823 default_label = lab; 3824 break; 3825 } 3826 do 3827 { 3828 /* Filter out duplicate labels that arise when this handler 3829 is shadowed by an earlier one. When no labels are 3830 attached to the handler anymore, we remove 3831 the corresponding edge and then we delete unreachable 3832 blocks at the end of this pass. */ 3833 if (! seen_values.contains (TREE_VALUE (flt_node))) 3834 { 3835 tree t = build_case_label (TREE_VALUE (flt_node), 3836 NULL, lab); 3837 labels.safe_push (t); 3838 seen_values.add (TREE_VALUE (flt_node)); 3839 have_label = true; 3840 } 3841 3842 tp_node = TREE_CHAIN (tp_node); 3843 flt_node = TREE_CHAIN (flt_node); 3844 } 3845 while (tp_node); 3846 if (! have_label) 3847 { 3848 remove_edge (find_edge (src, label_to_block (cfun, lab))); 3849 redirected = true; 3850 } 3851 } 3852 3853 /* Clean up the edge flags. */ 3854 FOR_EACH_EDGE (e, ei, src->succs) 3855 { 3856 if (e->flags & EDGE_FALLTHRU) 3857 { 3858 /* If there was no catch-all, use the fallthru edge. */ 3859 if (default_label == NULL) 3860 default_label = gimple_block_label (e->dest); 3861 e->flags &= ~EDGE_FALLTHRU; 3862 } 3863 } 3864 gcc_assert (default_label != NULL); 3865 3866 /* Don't generate a switch if there's only a default case. 3867 This is common in the form of try { A; } catch (...) { B; }. */ 3868 if (!labels.exists ()) 3869 { 3870 e = single_succ_edge (src); 3871 e->flags |= EDGE_FALLTHRU; 3872 } 3873 else 3874 { 3875 fn = builtin_decl_implicit (BUILT_IN_EH_FILTER); 3876 x = gimple_build_call (fn, 1, build_int_cst (integer_type_node, 3877 region_nr)); 3878 filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn))); 3879 filter = make_ssa_name (filter, x); 3880 gimple_call_set_lhs (x, filter); 3881 gimple_set_location (x, gimple_location (stmt)); 3882 gsi_insert_before (&gsi, x, GSI_SAME_STMT); 3883 3884 /* Turn the default label into a default case. */ 3885 default_label = build_case_label (NULL, NULL, default_label); 3886 sort_case_labels (labels); 3887 3888 x = gimple_build_switch (filter, default_label, labels); 3889 gimple_set_location (x, gimple_location (stmt)); 3890 gsi_insert_before (&gsi, x, GSI_SAME_STMT); 3891 } 3892 } 3893 break; 3894 3895 case ERT_ALLOWED_EXCEPTIONS: 3896 { 3897 edge b_e = BRANCH_EDGE (src); 3898 edge f_e = FALLTHRU_EDGE (src); 3899 3900 fn = builtin_decl_implicit (BUILT_IN_EH_FILTER); 3901 x = gimple_build_call (fn, 1, build_int_cst (integer_type_node, 3902 region_nr)); 3903 filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn))); 3904 filter = make_ssa_name (filter, x); 3905 gimple_call_set_lhs (x, filter); 3906 gimple_set_location (x, gimple_location (stmt)); 3907 gsi_insert_before (&gsi, x, GSI_SAME_STMT); 3908 3909 r->u.allowed.label = NULL; 3910 x = gimple_build_cond (EQ_EXPR, filter, 3911 build_int_cst (TREE_TYPE (filter), 3912 r->u.allowed.filter), 3913 NULL_TREE, NULL_TREE); 3914 gsi_insert_before (&gsi, x, GSI_SAME_STMT); 3915 3916 b_e->flags = b_e->flags | EDGE_TRUE_VALUE; 3917 f_e->flags = (f_e->flags & ~EDGE_FALLTHRU) | EDGE_FALSE_VALUE; 3918 } 3919 break; 3920 3921 default: 3922 gcc_unreachable (); 3923 } 3924 3925 /* Replace the EH_DISPATCH with the SWITCH or COND generated above. */ 3926 gsi_remove (&gsi, true); 3927 return redirected; 3928 } 3929 3930 namespace { 3931 3932 const pass_data pass_data_lower_eh_dispatch = 3933 { 3934 GIMPLE_PASS, /* type */ 3935 "ehdisp", /* name */ 3936 OPTGROUP_NONE, /* optinfo_flags */ 3937 TV_TREE_EH, /* tv_id */ 3938 PROP_gimple_lcf, /* properties_required */ 3939 0, /* properties_provided */ 3940 0, /* properties_destroyed */ 3941 0, /* todo_flags_start */ 3942 0, /* todo_flags_finish */ 3943 }; 3944 3945 class pass_lower_eh_dispatch : public gimple_opt_pass 3946 { 3947 public: 3948 pass_lower_eh_dispatch (gcc::context *ctxt) 3949 : gimple_opt_pass (pass_data_lower_eh_dispatch, ctxt) 3950 {} 3951 3952 /* opt_pass methods: */ 3953 bool gate (function *fun) final override 3954 { 3955 return fun->eh->region_tree != NULL; 3956 } 3957 unsigned int execute (function *) final override; 3958 3959 }; // class pass_lower_eh_dispatch 3960 3961 unsigned 3962 pass_lower_eh_dispatch::execute (function *fun) 3963 { 3964 basic_block bb; 3965 int flags = 0; 3966 bool redirected = false; 3967 bool any_resx_to_process = false; 3968 3969 assign_filter_values (); 3970 3971 FOR_EACH_BB_FN (bb, fun) 3972 { 3973 gimple *last = *gsi_last_bb (bb); 3974 if (last == NULL) 3975 continue; 3976 if (gimple_code (last) == GIMPLE_EH_DISPATCH) 3977 { 3978 redirected |= lower_eh_dispatch (bb, 3979 as_a <geh_dispatch *> (last)); 3980 flags |= TODO_update_ssa_only_virtuals; 3981 } 3982 else if (gimple_code (last) == GIMPLE_RESX) 3983 { 3984 if (stmt_can_throw_external (fun, last)) 3985 optimize_clobbers (bb); 3986 else if (!any_resx_to_process) 3987 sink_clobbers (bb, NULL, &any_resx_to_process); 3988 } 3989 bb->flags &= ~BB_VISITED; 3990 } 3991 if (redirected) 3992 { 3993 free_dominance_info (CDI_DOMINATORS); 3994 delete_unreachable_blocks (); 3995 } 3996 3997 if (any_resx_to_process) 3998 { 3999 /* Make sure to catch all secondary sinking opportunities by processing 4000 blocks in RPO order and after all CFG modifications from lowering 4001 and unreachable block removal. */ 4002 int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fun)); 4003 int rpo_n = pre_and_rev_post_order_compute_fn (fun, NULL, rpo, false); 4004 gimple_seq *sunk = XCNEWVEC (gimple_seq, last_basic_block_for_fn (fun)); 4005 for (int i = 0; i < rpo_n; ++i) 4006 { 4007 bb = BASIC_BLOCK_FOR_FN (fun, rpo[i]); 4008 gimple *last = *gsi_last_bb (bb); 4009 if (last 4010 && gimple_code (last) == GIMPLE_RESX 4011 && !stmt_can_throw_external (fun, last)) 4012 flags |= sink_clobbers (bb, sunk); 4013 /* If there were any clobbers sunk into this BB, insert them now. */ 4014 if (!gimple_seq_empty_p (sunk[bb->index])) 4015 { 4016 gimple_stmt_iterator gsi = gsi_after_labels (bb); 4017 gsi_insert_seq_before (&gsi, sunk[bb->index], GSI_NEW_STMT); 4018 sunk[bb->index] = NULL; 4019 } 4020 bb->flags |= BB_VISITED; 4021 } 4022 free (rpo); 4023 free (sunk); 4024 } 4025 4026 return flags; 4027 } 4028 4029 } // anon namespace 4030 4031 gimple_opt_pass * 4032 make_pass_lower_eh_dispatch (gcc::context *ctxt) 4033 { 4034 return new pass_lower_eh_dispatch (ctxt); 4035 } 4036 4037 /* Walk statements, see what regions and, optionally, landing pads 4039 are really referenced. 4040 4041 Returns in R_REACHABLEP an sbitmap with bits set for reachable regions, 4042 and in LP_REACHABLE an sbitmap with bits set for reachable landing pads. 4043 4044 Passing NULL for LP_REACHABLE is valid, in this case only reachable 4045 regions are marked. 4046 4047 The caller is responsible for freeing the returned sbitmaps. */ 4048 4049 static void 4050 mark_reachable_handlers (sbitmap *r_reachablep, sbitmap *lp_reachablep) 4051 { 4052 sbitmap r_reachable, lp_reachable; 4053 basic_block bb; 4054 bool mark_landing_pads = (lp_reachablep != NULL); 4055 gcc_checking_assert (r_reachablep != NULL); 4056 4057 r_reachable = sbitmap_alloc (cfun->eh->region_array->length ()); 4058 bitmap_clear (r_reachable); 4059 *r_reachablep = r_reachable; 4060 4061 if (mark_landing_pads) 4062 { 4063 lp_reachable = sbitmap_alloc (cfun->eh->lp_array->length ()); 4064 bitmap_clear (lp_reachable); 4065 *lp_reachablep = lp_reachable; 4066 } 4067 else 4068 lp_reachable = NULL; 4069 4070 FOR_EACH_BB_FN (bb, cfun) 4071 { 4072 gimple_stmt_iterator gsi; 4073 4074 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 4075 { 4076 gimple *stmt = gsi_stmt (gsi); 4077 4078 if (mark_landing_pads) 4079 { 4080 int lp_nr = lookup_stmt_eh_lp (stmt); 4081 4082 /* Negative LP numbers are MUST_NOT_THROW regions which 4083 are not considered BB enders. */ 4084 if (lp_nr < 0) 4085 bitmap_set_bit (r_reachable, -lp_nr); 4086 4087 /* Positive LP numbers are real landing pads, and BB enders. */ 4088 else if (lp_nr > 0) 4089 { 4090 gcc_assert (gsi_one_before_end_p (gsi)); 4091 eh_region region = get_eh_region_from_lp_number (lp_nr); 4092 bitmap_set_bit (r_reachable, region->index); 4093 bitmap_set_bit (lp_reachable, lp_nr); 4094 } 4095 } 4096 4097 /* Avoid removing regions referenced from RESX/EH_DISPATCH. */ 4098 switch (gimple_code (stmt)) 4099 { 4100 case GIMPLE_RESX: 4101 bitmap_set_bit (r_reachable, 4102 gimple_resx_region (as_a <gresx *> (stmt))); 4103 break; 4104 case GIMPLE_EH_DISPATCH: 4105 bitmap_set_bit (r_reachable, 4106 gimple_eh_dispatch_region ( 4107 as_a <geh_dispatch *> (stmt))); 4108 break; 4109 case GIMPLE_CALL: 4110 if (gimple_call_builtin_p (stmt, BUILT_IN_EH_COPY_VALUES)) 4111 for (int i = 0; i < 2; ++i) 4112 { 4113 tree rt = gimple_call_arg (stmt, i); 4114 HOST_WIDE_INT ri = tree_to_shwi (rt); 4115 4116 gcc_assert (ri == (int)ri); 4117 bitmap_set_bit (r_reachable, ri); 4118 } 4119 break; 4120 default: 4121 break; 4122 } 4123 } 4124 } 4125 } 4126 4127 /* Remove unreachable handlers and unreachable landing pads. */ 4128 4129 static void 4130 remove_unreachable_handlers (void) 4131 { 4132 sbitmap r_reachable, lp_reachable; 4133 eh_region region; 4134 eh_landing_pad lp; 4135 unsigned i; 4136 4137 mark_reachable_handlers (&r_reachable, &lp_reachable); 4138 4139 if (dump_file) 4140 { 4141 fprintf (dump_file, "Before removal of unreachable regions:\n"); 4142 dump_eh_tree (dump_file, cfun); 4143 fprintf (dump_file, "Reachable regions: "); 4144 dump_bitmap_file (dump_file, r_reachable); 4145 fprintf (dump_file, "Reachable landing pads: "); 4146 dump_bitmap_file (dump_file, lp_reachable); 4147 } 4148 4149 if (dump_file) 4150 { 4151 FOR_EACH_VEC_SAFE_ELT (cfun->eh->region_array, i, region) 4152 if (region && !bitmap_bit_p (r_reachable, region->index)) 4153 fprintf (dump_file, 4154 "Removing unreachable region %d\n", 4155 region->index); 4156 } 4157 4158 remove_unreachable_eh_regions (r_reachable); 4159 4160 FOR_EACH_VEC_SAFE_ELT (cfun->eh->lp_array, i, lp) 4161 if (lp && !bitmap_bit_p (lp_reachable, lp->index)) 4162 { 4163 if (dump_file) 4164 fprintf (dump_file, 4165 "Removing unreachable landing pad %d\n", 4166 lp->index); 4167 remove_eh_landing_pad (lp); 4168 } 4169 4170 if (dump_file) 4171 { 4172 fprintf (dump_file, "\n\nAfter removal of unreachable regions:\n"); 4173 dump_eh_tree (dump_file, cfun); 4174 fprintf (dump_file, "\n\n"); 4175 } 4176 4177 sbitmap_free (r_reachable); 4178 sbitmap_free (lp_reachable); 4179 4180 if (flag_checking) 4181 verify_eh_tree (cfun); 4182 } 4183 4184 /* Remove unreachable handlers if any landing pads have been removed after 4185 last ehcleanup pass (due to gimple_purge_dead_eh_edges). */ 4186 4187 void 4188 maybe_remove_unreachable_handlers (void) 4189 { 4190 eh_landing_pad lp; 4191 unsigned i; 4192 4193 if (cfun->eh == NULL) 4194 return; 4195 4196 FOR_EACH_VEC_SAFE_ELT (cfun->eh->lp_array, i, lp) 4197 if (lp 4198 && (lp->post_landing_pad == NULL_TREE 4199 || label_to_block (cfun, lp->post_landing_pad) == NULL)) 4200 { 4201 remove_unreachable_handlers (); 4202 return; 4203 } 4204 } 4205 4206 /* Remove regions that do not have landing pads. This assumes 4207 that remove_unreachable_handlers has already been run, and 4208 that we've just manipulated the landing pads since then. 4209 4210 Preserve regions with landing pads and regions that prevent 4211 exceptions from propagating further, even if these regions 4212 are not reachable. */ 4213 4214 static void 4215 remove_unreachable_handlers_no_lp (void) 4216 { 4217 eh_region region; 4218 sbitmap r_reachable; 4219 unsigned i; 4220 4221 mark_reachable_handlers (&r_reachable, /*lp_reachablep=*/NULL); 4222 4223 FOR_EACH_VEC_SAFE_ELT (cfun->eh->region_array, i, region) 4224 { 4225 if (! region) 4226 continue; 4227 4228 if (region->landing_pads != NULL 4229 || region->type == ERT_MUST_NOT_THROW) 4230 bitmap_set_bit (r_reachable, region->index); 4231 4232 if (dump_file 4233 && !bitmap_bit_p (r_reachable, region->index)) 4234 fprintf (dump_file, 4235 "Removing unreachable region %d\n", 4236 region->index); 4237 } 4238 4239 remove_unreachable_eh_regions (r_reachable); 4240 4241 sbitmap_free (r_reachable); 4242 } 4243 4244 /* Undo critical edge splitting on an EH landing pad. Earlier, we 4245 optimisticaly split all sorts of edges, including EH edges. The 4246 optimization passes in between may not have needed them; if not, 4247 we should undo the split. 4248 4249 Recognize this case by having one EH edge incoming to the BB and 4250 one normal edge outgoing; BB should be empty apart from the 4251 post_landing_pad label. 4252 4253 Note that this is slightly different from the empty handler case 4254 handled by cleanup_empty_eh, in that the actual handler may yet 4255 have actual code but the landing pad has been separated from the 4256 handler. As such, cleanup_empty_eh relies on this transformation 4257 having been done first. */ 4258 4259 static bool 4260 unsplit_eh (eh_landing_pad lp) 4261 { 4262 basic_block bb = label_to_block (cfun, lp->post_landing_pad); 4263 gimple_stmt_iterator gsi; 4264 edge e_in, e_out; 4265 4266 /* Quickly check the edge counts on BB for singularity. */ 4267 if (!single_pred_p (bb) || !single_succ_p (bb)) 4268 return false; 4269 e_in = single_pred_edge (bb); 4270 e_out = single_succ_edge (bb); 4271 4272 /* Input edge must be EH and output edge must be normal. */ 4273 if ((e_in->flags & EDGE_EH) == 0 || (e_out->flags & EDGE_EH) != 0) 4274 return false; 4275 4276 /* The block must be empty except for the labels and debug insns. */ 4277 gsi = gsi_after_labels (bb); 4278 if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) 4279 gsi_next_nondebug (&gsi); 4280 if (!gsi_end_p (gsi)) 4281 return false; 4282 4283 /* The destination block must not already have a landing pad 4284 for a different region. */ 4285 for (gsi = gsi_start_bb (e_out->dest); !gsi_end_p (gsi); gsi_next (&gsi)) 4286 { 4287 glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (gsi)); 4288 tree lab; 4289 int lp_nr; 4290 4291 if (!label_stmt) 4292 break; 4293 lab = gimple_label_label (label_stmt); 4294 lp_nr = EH_LANDING_PAD_NR (lab); 4295 if (lp_nr && get_eh_region_from_lp_number (lp_nr) != lp->region) 4296 return false; 4297 } 4298 4299 /* The new destination block must not already be a destination of 4300 the source block, lest we merge fallthru and eh edges and get 4301 all sorts of confused. */ 4302 if (find_edge (e_in->src, e_out->dest)) 4303 return false; 4304 4305 /* ??? We can get degenerate phis due to cfg cleanups. I would have 4306 thought this should have been cleaned up by a phicprop pass, but 4307 that doesn't appear to handle virtuals. Propagate by hand. */ 4308 if (!gimple_seq_empty_p (phi_nodes (bb))) 4309 { 4310 for (gphi_iterator gpi = gsi_start_phis (bb); !gsi_end_p (gpi); ) 4311 { 4312 gimple *use_stmt; 4313 gphi *phi = gpi.phi (); 4314 tree lhs = gimple_phi_result (phi); 4315 tree rhs = gimple_phi_arg_def (phi, 0); 4316 use_operand_p use_p; 4317 imm_use_iterator iter; 4318 4319 FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) 4320 { 4321 FOR_EACH_IMM_USE_ON_STMT (use_p, iter) 4322 SET_USE (use_p, rhs); 4323 } 4324 4325 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) 4326 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs) = 1; 4327 4328 remove_phi_node (&gpi, true); 4329 } 4330 } 4331 4332 if (dump_file && (dump_flags & TDF_DETAILS)) 4333 fprintf (dump_file, "Unsplit EH landing pad %d to block %i.\n", 4334 lp->index, e_out->dest->index); 4335 4336 /* Redirect the edge. Since redirect_eh_edge_1 expects to be moving 4337 a successor edge, humor it. But do the real CFG change with the 4338 predecessor of E_OUT in order to preserve the ordering of arguments 4339 to the PHI nodes in E_OUT->DEST. */ 4340 redirect_eh_edge_1 (e_in, e_out->dest, false); 4341 redirect_edge_pred (e_out, e_in->src); 4342 e_out->flags = e_in->flags; 4343 e_out->probability = e_in->probability; 4344 remove_edge (e_in); 4345 4346 return true; 4347 } 4348 4349 /* Examine each landing pad block and see if it matches unsplit_eh. */ 4350 4351 static bool 4352 unsplit_all_eh (void) 4353 { 4354 bool changed = false; 4355 eh_landing_pad lp; 4356 int i; 4357 4358 for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i) 4359 if (lp) 4360 changed |= unsplit_eh (lp); 4361 4362 return changed; 4363 } 4364 4365 /* Wrapper around unsplit_all_eh that makes it usable everywhere. */ 4366 4367 void 4368 unsplit_eh_edges (void) 4369 { 4370 bool changed; 4371 4372 /* unsplit_all_eh can die looking up unreachable landing pads. */ 4373 maybe_remove_unreachable_handlers (); 4374 4375 changed = unsplit_all_eh (); 4376 4377 /* If EH edges have been unsplit, delete unreachable forwarder blocks. */ 4378 if (changed) 4379 { 4380 free_dominance_info (CDI_DOMINATORS); 4381 free_dominance_info (CDI_POST_DOMINATORS); 4382 delete_unreachable_blocks (); 4383 } 4384 } 4385 4386 /* A subroutine of cleanup_empty_eh. Redirect all EH edges incoming 4387 to OLD_BB to NEW_BB; return true on success, false on failure. 4388 4389 OLD_BB_OUT is the edge into NEW_BB from OLD_BB, so if we miss any 4390 PHI variables from OLD_BB we can pick them up from OLD_BB_OUT. 4391 Virtual PHIs may be deleted and marked for renaming. */ 4392 4393 static bool 4394 cleanup_empty_eh_merge_phis (basic_block new_bb, basic_block old_bb, 4395 edge old_bb_out, bool change_region) 4396 { 4397 gphi_iterator ngsi, ogsi; 4398 edge_iterator ei; 4399 edge e; 4400 bitmap ophi_handled; 4401 4402 /* The destination block must not be a regular successor for any 4403 of the preds of the landing pad. Thus, avoid turning 4404 <..> 4405 | \ EH 4406 | <..> 4407 | / 4408 <..> 4409 into 4410 <..> 4411 | | EH 4412 <..> 4413 which CFG verification would choke on. See PR45172 and PR51089. */ 4414 if (!single_pred_p (new_bb)) 4415 FOR_EACH_EDGE (e, ei, old_bb->preds) 4416 if (find_edge (e->src, new_bb)) 4417 return false; 4418 4419 FOR_EACH_EDGE (e, ei, old_bb->preds) 4420 redirect_edge_var_map_clear (e); 4421 4422 ophi_handled = BITMAP_ALLOC (NULL); 4423 4424 /* First, iterate through the PHIs on NEW_BB and set up the edge_var_map 4425 for the edges we're going to move. */ 4426 for (ngsi = gsi_start_phis (new_bb); !gsi_end_p (ngsi); gsi_next (&ngsi)) 4427 { 4428 gphi *ophi, *nphi = ngsi.phi (); 4429 tree nresult, nop; 4430 4431 nresult = gimple_phi_result (nphi); 4432 nop = gimple_phi_arg_def (nphi, old_bb_out->dest_idx); 4433 4434 /* Find the corresponding PHI in OLD_BB so we can forward-propagate 4435 the source ssa_name. */ 4436 ophi = NULL; 4437 for (ogsi = gsi_start_phis (old_bb); !gsi_end_p (ogsi); gsi_next (&ogsi)) 4438 { 4439 ophi = ogsi.phi (); 4440 if (gimple_phi_result (ophi) == nop) 4441 break; 4442 ophi = NULL; 4443 } 4444 4445 /* If we did find the corresponding PHI, copy those inputs. */ 4446 if (ophi) 4447 { 4448 /* If NOP is used somewhere else beyond phis in new_bb, give up. */ 4449 if (!has_single_use (nop)) 4450 { 4451 imm_use_iterator imm_iter; 4452 use_operand_p use_p; 4453 4454 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, nop) 4455 { 4456 if (!gimple_debug_bind_p (USE_STMT (use_p)) 4457 && (gimple_code (USE_STMT (use_p)) != GIMPLE_PHI 4458 || gimple_bb (USE_STMT (use_p)) != new_bb)) 4459 goto fail; 4460 } 4461 } 4462 bitmap_set_bit (ophi_handled, SSA_NAME_VERSION (nop)); 4463 FOR_EACH_EDGE (e, ei, old_bb->preds) 4464 { 4465 location_t oloc; 4466 tree oop; 4467 4468 if ((e->flags & EDGE_EH) == 0) 4469 continue; 4470 oop = gimple_phi_arg_def (ophi, e->dest_idx); 4471 oloc = gimple_phi_arg_location (ophi, e->dest_idx); 4472 redirect_edge_var_map_add (e, nresult, oop, oloc); 4473 } 4474 } 4475 /* If we didn't find the PHI, if it's a real variable or a VOP, we know 4476 from the fact that OLD_BB is tree_empty_eh_handler_p that the 4477 variable is unchanged from input to the block and we can simply 4478 re-use the input to NEW_BB from the OLD_BB_OUT edge. */ 4479 else 4480 { 4481 location_t nloc 4482 = gimple_phi_arg_location (nphi, old_bb_out->dest_idx); 4483 FOR_EACH_EDGE (e, ei, old_bb->preds) 4484 redirect_edge_var_map_add (e, nresult, nop, nloc); 4485 } 4486 } 4487 4488 /* Second, verify that all PHIs from OLD_BB have been handled. If not, 4489 we don't know what values from the other edges into NEW_BB to use. */ 4490 for (ogsi = gsi_start_phis (old_bb); !gsi_end_p (ogsi); gsi_next (&ogsi)) 4491 { 4492 gphi *ophi = ogsi.phi (); 4493 tree oresult = gimple_phi_result (ophi); 4494 if (!bitmap_bit_p (ophi_handled, SSA_NAME_VERSION (oresult))) 4495 goto fail; 4496 } 4497 4498 /* Finally, move the edges and update the PHIs. */ 4499 for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)); ) 4500 if (e->flags & EDGE_EH) 4501 { 4502 /* ??? CFG manipluation routines do not try to update loop 4503 form on edge redirection. Do so manually here for now. */ 4504 /* If we redirect a loop entry or latch edge that will either create 4505 a multiple entry loop or rotate the loop. If the loops merge 4506 we may have created a loop with multiple latches. 4507 All of this isn't easily fixed thus cancel the affected loop 4508 and mark the other loop as possibly having multiple latches. */ 4509 if (e->dest == e->dest->loop_father->header) 4510 { 4511 mark_loop_for_removal (e->dest->loop_father); 4512 new_bb->loop_father->latch = NULL; 4513 loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES); 4514 } 4515 redirect_eh_edge_1 (e, new_bb, change_region); 4516 redirect_edge_succ (e, new_bb); 4517 flush_pending_stmts (e); 4518 } 4519 else 4520 ei_next (&ei); 4521 4522 BITMAP_FREE (ophi_handled); 4523 return true; 4524 4525 fail: 4526 FOR_EACH_EDGE (e, ei, old_bb->preds) 4527 redirect_edge_var_map_clear (e); 4528 BITMAP_FREE (ophi_handled); 4529 return false; 4530 } 4531 4532 /* A subroutine of cleanup_empty_eh. Move a landing pad LP from its 4533 old region to NEW_REGION at BB. */ 4534 4535 static void 4536 cleanup_empty_eh_move_lp (basic_block bb, edge e_out, 4537 eh_landing_pad lp, eh_region new_region) 4538 { 4539 gimple_stmt_iterator gsi; 4540 eh_landing_pad *pp; 4541 4542 for (pp = &lp->region->landing_pads; *pp != lp; pp = &(*pp)->next_lp) 4543 continue; 4544 *pp = lp->next_lp; 4545 4546 lp->region = new_region; 4547 lp->next_lp = new_region->landing_pads; 4548 new_region->landing_pads = lp; 4549 4550 /* Delete the RESX that was matched within the empty handler block. */ 4551 gsi = gsi_last_bb (bb); 4552 unlink_stmt_vdef (gsi_stmt (gsi)); 4553 gsi_remove (&gsi, true); 4554 4555 /* Clean up E_OUT for the fallthru. */ 4556 e_out->flags = (e_out->flags & ~EDGE_EH) | EDGE_FALLTHRU; 4557 e_out->probability = profile_probability::always (); 4558 } 4559 4560 /* A subroutine of cleanup_empty_eh. Handle more complex cases of 4561 unsplitting than unsplit_eh was prepared to handle, e.g. when 4562 multiple incoming edges and phis are involved. */ 4563 4564 static bool 4565 cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp) 4566 { 4567 gimple_stmt_iterator gsi; 4568 tree lab; 4569 4570 /* We really ought not have totally lost everything following 4571 a landing pad label. Given that BB is empty, there had better 4572 be a successor. */ 4573 gcc_assert (e_out != NULL); 4574 4575 /* The destination block must not already have a landing pad 4576 for a different region. */ 4577 lab = NULL; 4578 for (gsi = gsi_start_bb (e_out->dest); !gsi_end_p (gsi); gsi_next (&gsi)) 4579 { 4580 glabel *stmt = dyn_cast <glabel *> (gsi_stmt (gsi)); 4581 int lp_nr; 4582 4583 if (!stmt) 4584 break; 4585 lab = gimple_label_label (stmt); 4586 lp_nr = EH_LANDING_PAD_NR (lab); 4587 if (lp_nr && get_eh_region_from_lp_number (lp_nr) != lp->region) 4588 return false; 4589 } 4590 4591 /* Attempt to move the PHIs into the successor block. */ 4592 if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, false)) 4593 { 4594 if (dump_file && (dump_flags & TDF_DETAILS)) 4595 fprintf (dump_file, 4596 "Unsplit EH landing pad %d to block %i " 4597 "(via cleanup_empty_eh).\n", 4598 lp->index, e_out->dest->index); 4599 return true; 4600 } 4601 4602 return false; 4603 } 4604 4605 /* Return true if edge E_FIRST is part of an empty infinite loop 4606 or leads to such a loop through a series of single successor 4607 empty bbs. */ 4608 4609 static bool 4610 infinite_empty_loop_p (edge e_first) 4611 { 4612 bool inf_loop = false; 4613 edge e; 4614 4615 if (e_first->dest == e_first->src) 4616 return true; 4617 4618 e_first->src->aux = (void *) 1; 4619 for (e = e_first; single_succ_p (e->dest); e = single_succ_edge (e->dest)) 4620 { 4621 gimple_stmt_iterator gsi; 4622 if (e->dest->aux) 4623 { 4624 inf_loop = true; 4625 break; 4626 } 4627 e->dest->aux = (void *) 1; 4628 gsi = gsi_after_labels (e->dest); 4629 if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) 4630 gsi_next_nondebug (&gsi); 4631 if (!gsi_end_p (gsi)) 4632 break; 4633 } 4634 e_first->src->aux = NULL; 4635 for (e = e_first; e->dest->aux; e = single_succ_edge (e->dest)) 4636 e->dest->aux = NULL; 4637 4638 return inf_loop; 4639 } 4640 4641 /* Examine the block associated with LP to determine if it's an empty 4642 handler for its EH region. If so, attempt to redirect EH edges to 4643 an outer region. Return true the CFG was updated in any way. This 4644 is similar to jump forwarding, just across EH edges. */ 4645 4646 static bool 4647 cleanup_empty_eh (eh_landing_pad lp) 4648 { 4649 basic_block bb = label_to_block (cfun, lp->post_landing_pad); 4650 gimple_stmt_iterator gsi; 4651 gimple *resx; 4652 eh_region new_region; 4653 edge_iterator ei; 4654 edge e, e_out; 4655 bool has_non_eh_pred; 4656 bool ret = false; 4657 int new_lp_nr; 4658 4659 /* There can be zero or one edges out of BB. This is the quickest test. */ 4660 switch (EDGE_COUNT (bb->succs)) 4661 { 4662 case 0: 4663 e_out = NULL; 4664 break; 4665 case 1: 4666 e_out = single_succ_edge (bb); 4667 break; 4668 default: 4669 return false; 4670 } 4671 4672 gsi = gsi_last_nondebug_bb (bb); 4673 resx = gsi_stmt (gsi); 4674 if (resx && is_gimple_resx (resx)) 4675 { 4676 if (stmt_can_throw_external (cfun, resx)) 4677 optimize_clobbers (bb); 4678 else if (sink_clobbers (bb)) 4679 ret = true; 4680 } 4681 4682 gsi = gsi_after_labels (bb); 4683 4684 /* Make sure to skip debug statements. */ 4685 if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) 4686 gsi_next_nondebug (&gsi); 4687 4688 /* If the block is totally empty, look for more unsplitting cases. */ 4689 if (gsi_end_p (gsi)) 4690 { 4691 /* For the degenerate case of an infinite loop bail out. 4692 If bb has no successors and is totally empty, which can happen e.g. 4693 because of incorrect noreturn attribute, bail out too. */ 4694 if (e_out == NULL 4695 || infinite_empty_loop_p (e_out)) 4696 return ret; 4697 4698 return ret | cleanup_empty_eh_unsplit (bb, e_out, lp); 4699 } 4700 4701 /* The block should consist only of a single RESX statement, modulo a 4702 preceding call to __builtin_stack_restore if there is no outgoing 4703 edge, since the call can be eliminated in this case. */ 4704 resx = gsi_stmt (gsi); 4705 if (!e_out && gimple_call_builtin_p (resx, BUILT_IN_STACK_RESTORE)) 4706 { 4707 gsi_next_nondebug (&gsi); 4708 resx = gsi_stmt (gsi); 4709 } 4710 if (!is_gimple_resx (resx)) 4711 return ret; 4712 gcc_assert (gsi_one_nondebug_before_end_p (gsi)); 4713 4714 /* Determine if there are non-EH edges, or resx edges into the handler. */ 4715 has_non_eh_pred = false; 4716 FOR_EACH_EDGE (e, ei, bb->preds) 4717 if (!(e->flags & EDGE_EH)) 4718 has_non_eh_pred = true; 4719 4720 /* Find the handler that's outer of the empty handler by looking at 4721 where the RESX instruction was vectored. */ 4722 new_lp_nr = lookup_stmt_eh_lp (resx); 4723 new_region = get_eh_region_from_lp_number (new_lp_nr); 4724 4725 /* If there's no destination region within the current function, 4726 redirection is trivial via removing the throwing statements from 4727 the EH region, removing the EH edges, and allowing the block 4728 to go unreachable. */ 4729 if (new_region == NULL) 4730 { 4731 gcc_assert (e_out == NULL); 4732 for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); ) 4733 if (e->flags & EDGE_EH) 4734 { 4735 gimple *stmt = *gsi_last_bb (e->src); 4736 remove_stmt_from_eh_lp (stmt); 4737 remove_edge (e); 4738 } 4739 else 4740 ei_next (&ei); 4741 goto succeed; 4742 } 4743 4744 /* If the destination region is a MUST_NOT_THROW, allow the runtime 4745 to handle the abort and allow the blocks to go unreachable. */ 4746 if (new_region->type == ERT_MUST_NOT_THROW) 4747 { 4748 for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); ) 4749 if (e->flags & EDGE_EH) 4750 { 4751 gimple *stmt = *gsi_last_bb (e->src); 4752 remove_stmt_from_eh_lp (stmt); 4753 add_stmt_to_eh_lp (stmt, new_lp_nr); 4754 remove_edge (e); 4755 } 4756 else 4757 ei_next (&ei); 4758 goto succeed; 4759 } 4760 4761 /* Try to redirect the EH edges and merge the PHIs into the destination 4762 landing pad block. If the merge succeeds, we'll already have redirected 4763 all the EH edges. The handler itself will go unreachable if there were 4764 no normal edges. */ 4765 if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, true)) 4766 goto succeed; 4767 4768 /* Finally, if all input edges are EH edges, then we can (potentially) 4769 reduce the number of transfers from the runtime by moving the landing 4770 pad from the original region to the new region. This is a win when 4771 we remove the last CLEANUP region along a particular exception 4772 propagation path. Since nothing changes except for the region with 4773 which the landing pad is associated, the PHI nodes do not need to be 4774 adjusted at all. */ 4775 if (!has_non_eh_pred) 4776 { 4777 cleanup_empty_eh_move_lp (bb, e_out, lp, new_region); 4778 if (dump_file && (dump_flags & TDF_DETAILS)) 4779 fprintf (dump_file, "Empty EH handler %i moved to EH region %i.\n", 4780 lp->index, new_region->index); 4781 4782 /* ??? The CFG didn't change, but we may have rendered the 4783 old EH region unreachable. Trigger a cleanup there. */ 4784 return true; 4785 } 4786 4787 return ret; 4788 4789 succeed: 4790 if (dump_file && (dump_flags & TDF_DETAILS)) 4791 fprintf (dump_file, "Empty EH handler %i removed.\n", lp->index); 4792 remove_eh_landing_pad (lp); 4793 return true; 4794 } 4795 4796 /* Do a post-order traversal of the EH region tree. Examine each 4797 post_landing_pad block and see if we can eliminate it as empty. */ 4798 4799 static bool 4800 cleanup_all_empty_eh (void) 4801 { 4802 bool changed = false; 4803 eh_landing_pad lp; 4804 int i; 4805 4806 /* The post-order traversal may lead to quadraticness in the redirection 4807 of incoming EH edges from inner LPs, so first try to walk the region 4808 tree from inner to outer LPs in order to eliminate these edges. */ 4809 for (i = vec_safe_length (cfun->eh->lp_array) - 1; i >= 1; --i) 4810 { 4811 lp = (*cfun->eh->lp_array)[i]; 4812 if (lp) 4813 changed |= cleanup_empty_eh (lp); 4814 } 4815 4816 /* Now do the post-order traversal to eliminate outer empty LPs. */ 4817 for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i) 4818 if (lp) 4819 changed |= cleanup_empty_eh (lp); 4820 4821 return changed; 4822 } 4823 4824 /* Perform cleanups and lowering of exception handling 4825 1) cleanups regions with handlers doing nothing are optimized out 4826 2) MUST_NOT_THROW regions that became dead because of 1) are optimized out 4827 3) Info about regions that are containing instructions, and regions 4828 reachable via local EH edges is collected 4829 4) Eh tree is pruned for regions no longer necessary. 4830 4831 TODO: Push MUST_NOT_THROW regions to the root of the EH tree. 4832 Unify those that have the same failure decl and locus. 4833 */ 4834 4835 static unsigned int 4836 execute_cleanup_eh_1 (void) 4837 { 4838 /* Do this first: unsplit_all_eh and cleanup_all_empty_eh can die 4839 looking up unreachable landing pads. */ 4840 remove_unreachable_handlers (); 4841 4842 /* Watch out for the region tree vanishing due to all unreachable. */ 4843 if (cfun->eh->region_tree) 4844 { 4845 bool changed = false; 4846 4847 if (optimize) 4848 changed |= unsplit_all_eh (); 4849 changed |= cleanup_all_empty_eh (); 4850 4851 if (changed) 4852 { 4853 free_dominance_info (CDI_DOMINATORS); 4854 free_dominance_info (CDI_POST_DOMINATORS); 4855 4856 /* We delayed all basic block deletion, as we may have performed 4857 cleanups on EH edges while non-EH edges were still present. */ 4858 delete_unreachable_blocks (); 4859 4860 /* We manipulated the landing pads. Remove any region that no 4861 longer has a landing pad. */ 4862 remove_unreachable_handlers_no_lp (); 4863 4864 return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals; 4865 } 4866 } 4867 4868 return 0; 4869 } 4870 4871 namespace { 4872 4873 const pass_data pass_data_cleanup_eh = 4874 { 4875 GIMPLE_PASS, /* type */ 4876 "ehcleanup", /* name */ 4877 OPTGROUP_NONE, /* optinfo_flags */ 4878 TV_TREE_EH, /* tv_id */ 4879 PROP_gimple_lcf, /* properties_required */ 4880 0, /* properties_provided */ 4881 0, /* properties_destroyed */ 4882 0, /* todo_flags_start */ 4883 0, /* todo_flags_finish */ 4884 }; 4885 4886 class pass_cleanup_eh : public gimple_opt_pass 4887 { 4888 public: 4889 pass_cleanup_eh (gcc::context *ctxt) 4890 : gimple_opt_pass (pass_data_cleanup_eh, ctxt) 4891 {} 4892 4893 /* opt_pass methods: */ 4894 opt_pass * clone () final override { return new pass_cleanup_eh (m_ctxt); } 4895 bool gate (function *fun) final override 4896 { 4897 return fun->eh != NULL && fun->eh->region_tree != NULL; 4898 } 4899 4900 unsigned int execute (function *) final override; 4901 4902 }; // class pass_cleanup_eh 4903 4904 unsigned int 4905 pass_cleanup_eh::execute (function *fun) 4906 { 4907 int ret = execute_cleanup_eh_1 (); 4908 4909 /* If the function no longer needs an EH personality routine 4910 clear it. This exposes cross-language inlining opportunities 4911 and avoids references to a never defined personality routine. */ 4912 if (DECL_FUNCTION_PERSONALITY (current_function_decl) 4913 && function_needs_eh_personality (fun) != eh_personality_lang) 4914 DECL_FUNCTION_PERSONALITY (current_function_decl) = NULL_TREE; 4915 4916 return ret; 4917 } 4918 4919 } // anon namespace 4920 4921 gimple_opt_pass * 4922 make_pass_cleanup_eh (gcc::context *ctxt) 4923 { 4924 return new pass_cleanup_eh (ctxt); 4925 } 4926 4927 /* Disable warnings about missing quoting in GCC diagnostics for 4929 the verification errors. Their format strings don't follow GCC 4930 diagnostic conventions but are only used for debugging. */ 4931 #if __GNUC__ >= 10 4932 # pragma GCC diagnostic push 4933 # pragma GCC diagnostic ignored "-Wformat-diag" 4934 #endif 4935 4936 /* Verify that BB containing STMT as the last statement, has precisely the 4937 edge that make_eh_edge would create. */ 4938 4939 DEBUG_FUNCTION bool 4940 verify_eh_edges (gimple *stmt) 4941 { 4942 basic_block bb = gimple_bb (stmt); 4943 eh_landing_pad lp = NULL; 4944 int lp_nr; 4945 edge_iterator ei; 4946 edge e, eh_edge; 4947 4948 lp_nr = lookup_stmt_eh_lp (stmt); 4949 if (lp_nr > 0) 4950 lp = get_eh_landing_pad_from_number (lp_nr); 4951 4952 eh_edge = NULL; 4953 FOR_EACH_EDGE (e, ei, bb->succs) 4954 { 4955 if (e->flags & EDGE_EH) 4956 { 4957 if (eh_edge) 4958 { 4959 error ("BB %i has multiple EH edges", bb->index); 4960 return true; 4961 } 4962 else 4963 eh_edge = e; 4964 } 4965 } 4966 4967 if (lp == NULL) 4968 { 4969 if (eh_edge) 4970 { 4971 error ("BB %i cannot throw but has an EH edge", bb->index); 4972 return true; 4973 } 4974 return false; 4975 } 4976 4977 if (!stmt_could_throw_p (cfun, stmt)) 4978 { 4979 error ("BB %i last statement has incorrectly set lp", bb->index); 4980 return true; 4981 } 4982 4983 if (eh_edge == NULL) 4984 { 4985 error ("BB %i is missing an EH edge", bb->index); 4986 return true; 4987 } 4988 4989 if (eh_edge->dest != label_to_block (cfun, lp->post_landing_pad)) 4990 { 4991 error ("Incorrect EH edge %i->%i", bb->index, eh_edge->dest->index); 4992 return true; 4993 } 4994 4995 return false; 4996 } 4997 4998 /* Similarly, but handle GIMPLE_EH_DISPATCH specifically. */ 4999 5000 DEBUG_FUNCTION bool 5001 verify_eh_dispatch_edge (geh_dispatch *stmt) 5002 { 5003 eh_region r; 5004 eh_catch c; 5005 basic_block src, dst; 5006 bool want_fallthru = true; 5007 edge_iterator ei; 5008 edge e, fall_edge; 5009 5010 r = get_eh_region_from_number (gimple_eh_dispatch_region (stmt)); 5011 src = gimple_bb (stmt); 5012 5013 FOR_EACH_EDGE (e, ei, src->succs) 5014 gcc_assert (e->aux == NULL); 5015 5016 switch (r->type) 5017 { 5018 case ERT_TRY: 5019 for (c = r->u.eh_try.first_catch; c ; c = c->next_catch) 5020 { 5021 dst = label_to_block (cfun, c->label); 5022 e = find_edge (src, dst); 5023 if (e == NULL) 5024 { 5025 error ("BB %i is missing an edge", src->index); 5026 return true; 5027 } 5028 e->aux = (void *)e; 5029 5030 /* A catch-all handler doesn't have a fallthru. */ 5031 if (c->type_list == NULL) 5032 { 5033 want_fallthru = false; 5034 break; 5035 } 5036 } 5037 break; 5038 5039 case ERT_ALLOWED_EXCEPTIONS: 5040 dst = label_to_block (cfun, r->u.allowed.label); 5041 e = find_edge (src, dst); 5042 if (e == NULL) 5043 { 5044 error ("BB %i is missing an edge", src->index); 5045 return true; 5046 } 5047 e->aux = (void *)e; 5048 break; 5049 5050 default: 5051 gcc_unreachable (); 5052 } 5053 5054 fall_edge = NULL; 5055 FOR_EACH_EDGE (e, ei, src->succs) 5056 { 5057 if (e->flags & EDGE_FALLTHRU) 5058 { 5059 if (fall_edge != NULL) 5060 { 5061 error ("BB %i too many fallthru edges", src->index); 5062 return true; 5063 } 5064 fall_edge = e; 5065 } 5066 else if (e->aux) 5067 e->aux = NULL; 5068 else 5069 { 5070 error ("BB %i has incorrect edge", src->index); 5071 return true; 5072 } 5073 } 5074 if ((fall_edge != NULL) ^ want_fallthru) 5075 { 5076 error ("BB %i has incorrect fallthru edge", src->index); 5077 return true; 5078 } 5079 5080 return false; 5081 } 5082 5083 #if __GNUC__ >= 10 5084 # pragma GCC diagnostic pop 5085 #endif 5086