1 /* Implements exception handling. 2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 4 Free Software Foundation, Inc. 5 Contributed by Mike Stump <mrs@cygnus.com>. 6 7 This file is part of GCC. 8 9 GCC is free software; you can redistribute it and/or modify it under 10 the terms of the GNU General Public License as published by the Free 11 Software Foundation; either version 3, or (at your option) any later 12 version. 13 14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 15 WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with GCC; see the file COPYING3. If not see 21 <http://www.gnu.org/licenses/>. */ 22 23 24 /* An exception is an event that can be "thrown" from within a 25 function. This event can then be "caught" by the callers of 26 the function. 27 28 The representation of exceptions changes several times during 29 the compilation process: 30 31 In the beginning, in the front end, we have the GENERIC trees 32 TRY_CATCH_EXPR, TRY_FINALLY_EXPR, WITH_CLEANUP_EXPR, 33 CLEANUP_POINT_EXPR, CATCH_EXPR, and EH_FILTER_EXPR. 34 35 During initial gimplification (gimplify.c) these are lowered 36 to the GIMPLE_TRY, GIMPLE_CATCH, and GIMPLE_EH_FILTER nodes. 37 The WITH_CLEANUP_EXPR and CLEANUP_POINT_EXPR nodes are converted 38 into GIMPLE_TRY_FINALLY nodes; the others are a more direct 1-1 39 conversion. 40 41 During pass_lower_eh (tree-eh.c) we record the nested structure 42 of the TRY nodes in EH_REGION nodes in CFUN->EH->REGION_TREE. 43 We expand the eh_protect_cleanup_actions langhook into MUST_NOT_THROW 44 regions at this time. We can then flatten the statements within 45 the TRY nodes to straight-line code. Statements that had been within 46 TRY nodes that can throw are recorded within CFUN->EH->THROW_STMT_TABLE, 47 so that we may remember what action is supposed to be taken if 48 a given statement does throw. During this lowering process, 49 we create an EH_LANDING_PAD node for each EH_REGION that has 50 some code within the function that needs to be executed if a 51 throw does happen. We also create RESX statements that are 52 used to transfer control from an inner EH_REGION to an outer 53 EH_REGION. We also create EH_DISPATCH statements as placeholders 54 for a runtime type comparison that should be made in order to 55 select the action to perform among different CATCH and EH_FILTER 56 regions. 57 58 During pass_lower_eh_dispatch (tree-eh.c), which is run after 59 all inlining is complete, we are able to run assign_filter_values, 60 which allows us to map the set of types manipulated by all of the 61 CATCH and EH_FILTER regions to a set of integers. This set of integers 62 will be how the exception runtime communicates with the code generated 63 within the function. We then expand the GIMPLE_EH_DISPATCH statements 64 to a switch or conditional branches that use the argument provided by 65 the runtime (__builtin_eh_filter) and the set of integers we computed 66 in assign_filter_values. 67 68 During pass_lower_resx (tree-eh.c), which is run near the end 69 of optimization, we expand RESX statements. If the eh region 70 that is outer to the RESX statement is a MUST_NOT_THROW, then 71 the RESX expands to some form of abort statement. If the eh 72 region that is outer to the RESX statement is within the current 73 function, then the RESX expands to a bookkeeping call 74 (__builtin_eh_copy_values) and a goto. Otherwise, the next 75 handler for the exception must be within a function somewhere 76 up the call chain, so we call back into the exception runtime 77 (__builtin_unwind_resume). 78 79 During pass_expand (cfgexpand.c), we generate REG_EH_REGION notes 80 that create an rtl to eh_region mapping that corresponds to the 81 gimple to eh_region mapping that had been recorded in the 82 THROW_STMT_TABLE. 83 84 During pass_rtl_eh (except.c), we generate the real landing pads 85 to which the runtime will actually transfer control. These new 86 landing pads perform whatever bookkeeping is needed by the target 87 backend in order to resume execution within the current function. 88 Each of these new landing pads falls through into the post_landing_pad 89 label which had been used within the CFG up to this point. All 90 exception edges within the CFG are redirected to the new landing pads. 91 If the target uses setjmp to implement exceptions, the various extra 92 calls into the runtime to register and unregister the current stack 93 frame are emitted at this time. 94 95 During pass_convert_to_eh_region_ranges (except.c), we transform 96 the REG_EH_REGION notes attached to individual insns into 97 non-overlapping ranges of insns bounded by NOTE_INSN_EH_REGION_BEG 98 and NOTE_INSN_EH_REGION_END. Each insn within such ranges has the 99 same associated action within the exception region tree, meaning 100 that (1) the exception is caught by the same landing pad within the 101 current function, (2) the exception is blocked by the runtime with 102 a MUST_NOT_THROW region, or (3) the exception is not handled at all 103 within the current function. 104 105 Finally, during assembly generation, we call 106 output_function_exception_table (except.c) to emit the tables with 107 which the exception runtime can determine if a given stack frame 108 handles a given exception, and if so what filter value to provide 109 to the function when the non-local control transfer is effected. 110 If the target uses dwarf2 unwinding to implement exceptions, then 111 output_call_frame_info (dwarf2out.c) emits the required unwind data. */ 112 113 114 #include "config.h" 115 #include "system.h" 116 #include "coretypes.h" 117 #include "tm.h" 118 #include "rtl.h" 119 #include "tree.h" 120 #include "flags.h" 121 #include "function.h" 122 #include "expr.h" 123 #include "libfuncs.h" 124 #include "insn-config.h" 125 #include "except.h" 126 #include "integrate.h" 127 #include "hard-reg-set.h" 128 #include "basic-block.h" 129 #include "output.h" 130 #include "dwarf2asm.h" 131 #include "dwarf2out.h" 132 #include "dwarf2.h" 133 #include "toplev.h" 134 #include "hashtab.h" 135 #include "intl.h" 136 #include "ggc.h" 137 #include "tm_p.h" 138 #include "target.h" 139 #include "common/common-target.h" 140 #include "langhooks.h" 141 #include "cgraph.h" 142 #include "diagnostic.h" 143 #include "tree-pretty-print.h" 144 #include "tree-pass.h" 145 #include "timevar.h" 146 #include "tree-flow.h" 147 148 /* Provide defaults for stuff that may not be defined when using 149 sjlj exceptions. */ 150 #ifndef EH_RETURN_DATA_REGNO 151 #define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM 152 #endif 153 154 static GTY(()) int call_site_base; 155 static GTY ((param_is (union tree_node))) 156 htab_t type_to_runtime_map; 157 158 /* Describe the SjLj_Function_Context structure. */ 159 static GTY(()) tree sjlj_fc_type_node; 160 static int sjlj_fc_call_site_ofs; 161 static int sjlj_fc_data_ofs; 162 static int sjlj_fc_personality_ofs; 163 static int sjlj_fc_lsda_ofs; 164 static int sjlj_fc_jbuf_ofs; 165 166 167 struct GTY(()) call_site_record_d 168 { 169 rtx landing_pad; 170 int action; 171 }; 172 173 static bool get_eh_region_and_lp_from_rtx (const_rtx, eh_region *, 174 eh_landing_pad *); 175 176 static int t2r_eq (const void *, const void *); 177 static hashval_t t2r_hash (const void *); 178 179 static int ttypes_filter_eq (const void *, const void *); 180 static hashval_t ttypes_filter_hash (const void *); 181 static int ehspec_filter_eq (const void *, const void *); 182 static hashval_t ehspec_filter_hash (const void *); 183 static int add_ttypes_entry (htab_t, tree); 184 static int add_ehspec_entry (htab_t, htab_t, tree); 185 static void dw2_build_landing_pads (void); 186 187 static int action_record_eq (const void *, const void *); 188 static hashval_t action_record_hash (const void *); 189 static int add_action_record (htab_t, int, int); 190 static int collect_one_action_chain (htab_t, eh_region); 191 static int add_call_site (rtx, int, int); 192 193 static void push_uleb128 (VEC (uchar, gc) **, unsigned int); 194 static void push_sleb128 (VEC (uchar, gc) **, int); 195 #ifndef HAVE_AS_LEB128 196 static int dw2_size_of_call_site_table (int); 197 static int sjlj_size_of_call_site_table (void); 198 #endif 199 static void dw2_output_call_site_table (int, int); 200 static void sjlj_output_call_site_table (void); 201 202 203 void 204 init_eh (void) 205 { 206 if (! flag_exceptions) 207 return; 208 209 type_to_runtime_map = htab_create_ggc (31, t2r_hash, t2r_eq, NULL); 210 211 /* Create the SjLj_Function_Context structure. This should match 212 the definition in unwind-sjlj.c. */ 213 if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ) 214 { 215 tree f_jbuf, f_per, f_lsda, f_prev, f_cs, f_data, tmp; 216 217 sjlj_fc_type_node = lang_hooks.types.make_type (RECORD_TYPE); 218 219 f_prev = build_decl (BUILTINS_LOCATION, 220 FIELD_DECL, get_identifier ("__prev"), 221 build_pointer_type (sjlj_fc_type_node)); 222 DECL_FIELD_CONTEXT (f_prev) = sjlj_fc_type_node; 223 224 f_cs = build_decl (BUILTINS_LOCATION, 225 FIELD_DECL, get_identifier ("__call_site"), 226 integer_type_node); 227 DECL_FIELD_CONTEXT (f_cs) = sjlj_fc_type_node; 228 229 tmp = build_index_type (size_int (4 - 1)); 230 tmp = build_array_type (lang_hooks.types.type_for_mode 231 (targetm.unwind_word_mode (), 1), 232 tmp); 233 f_data = build_decl (BUILTINS_LOCATION, 234 FIELD_DECL, get_identifier ("__data"), tmp); 235 DECL_FIELD_CONTEXT (f_data) = sjlj_fc_type_node; 236 237 f_per = build_decl (BUILTINS_LOCATION, 238 FIELD_DECL, get_identifier ("__personality"), 239 ptr_type_node); 240 DECL_FIELD_CONTEXT (f_per) = sjlj_fc_type_node; 241 242 f_lsda = build_decl (BUILTINS_LOCATION, 243 FIELD_DECL, get_identifier ("__lsda"), 244 ptr_type_node); 245 DECL_FIELD_CONTEXT (f_lsda) = sjlj_fc_type_node; 246 247 #ifdef DONT_USE_BUILTIN_SETJMP 248 #ifdef JMP_BUF_SIZE 249 tmp = size_int (JMP_BUF_SIZE - 1); 250 #else 251 /* Should be large enough for most systems, if it is not, 252 JMP_BUF_SIZE should be defined with the proper value. It will 253 also tend to be larger than necessary for most systems, a more 254 optimal port will define JMP_BUF_SIZE. */ 255 tmp = size_int (FIRST_PSEUDO_REGISTER + 2 - 1); 256 #endif 257 #else 258 /* builtin_setjmp takes a pointer to 5 words. */ 259 tmp = size_int (5 * BITS_PER_WORD / POINTER_SIZE - 1); 260 #endif 261 tmp = build_index_type (tmp); 262 tmp = build_array_type (ptr_type_node, tmp); 263 f_jbuf = build_decl (BUILTINS_LOCATION, 264 FIELD_DECL, get_identifier ("__jbuf"), tmp); 265 #ifdef DONT_USE_BUILTIN_SETJMP 266 /* We don't know what the alignment requirements of the 267 runtime's jmp_buf has. Overestimate. */ 268 DECL_ALIGN (f_jbuf) = BIGGEST_ALIGNMENT; 269 DECL_USER_ALIGN (f_jbuf) = 1; 270 #endif 271 DECL_FIELD_CONTEXT (f_jbuf) = sjlj_fc_type_node; 272 273 TYPE_FIELDS (sjlj_fc_type_node) = f_prev; 274 TREE_CHAIN (f_prev) = f_cs; 275 TREE_CHAIN (f_cs) = f_data; 276 TREE_CHAIN (f_data) = f_per; 277 TREE_CHAIN (f_per) = f_lsda; 278 TREE_CHAIN (f_lsda) = f_jbuf; 279 280 layout_type (sjlj_fc_type_node); 281 282 /* Cache the interesting field offsets so that we have 283 easy access from rtl. */ 284 sjlj_fc_call_site_ofs 285 = (tree_low_cst (DECL_FIELD_OFFSET (f_cs), 1) 286 + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_cs), 1) / BITS_PER_UNIT); 287 sjlj_fc_data_ofs 288 = (tree_low_cst (DECL_FIELD_OFFSET (f_data), 1) 289 + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_data), 1) / BITS_PER_UNIT); 290 sjlj_fc_personality_ofs 291 = (tree_low_cst (DECL_FIELD_OFFSET (f_per), 1) 292 + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_per), 1) / BITS_PER_UNIT); 293 sjlj_fc_lsda_ofs 294 = (tree_low_cst (DECL_FIELD_OFFSET (f_lsda), 1) 295 + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_lsda), 1) / BITS_PER_UNIT); 296 sjlj_fc_jbuf_ofs 297 = (tree_low_cst (DECL_FIELD_OFFSET (f_jbuf), 1) 298 + tree_low_cst (DECL_FIELD_BIT_OFFSET (f_jbuf), 1) / BITS_PER_UNIT); 299 } 300 } 301 302 void 303 init_eh_for_function (void) 304 { 305 cfun->eh = ggc_alloc_cleared_eh_status (); 306 307 /* Make sure zero'th entries are used. */ 308 VEC_safe_push (eh_region, gc, cfun->eh->region_array, NULL); 309 VEC_safe_push (eh_landing_pad, gc, cfun->eh->lp_array, NULL); 310 } 311 312 /* Routines to generate the exception tree somewhat directly. 313 These are used from tree-eh.c when processing exception related 314 nodes during tree optimization. */ 315 316 static eh_region 317 gen_eh_region (enum eh_region_type type, eh_region outer) 318 { 319 eh_region new_eh; 320 321 /* Insert a new blank region as a leaf in the tree. */ 322 new_eh = ggc_alloc_cleared_eh_region_d (); 323 new_eh->type = type; 324 new_eh->outer = outer; 325 if (outer) 326 { 327 new_eh->next_peer = outer->inner; 328 outer->inner = new_eh; 329 } 330 else 331 { 332 new_eh->next_peer = cfun->eh->region_tree; 333 cfun->eh->region_tree = new_eh; 334 } 335 336 new_eh->index = VEC_length (eh_region, cfun->eh->region_array); 337 VEC_safe_push (eh_region, gc, cfun->eh->region_array, new_eh); 338 339 /* Copy the language's notion of whether to use __cxa_end_cleanup. */ 340 if (targetm.arm_eabi_unwinder && lang_hooks.eh_use_cxa_end_cleanup) 341 new_eh->use_cxa_end_cleanup = true; 342 343 return new_eh; 344 } 345 346 eh_region 347 gen_eh_region_cleanup (eh_region outer) 348 { 349 return gen_eh_region (ERT_CLEANUP, outer); 350 } 351 352 eh_region 353 gen_eh_region_try (eh_region outer) 354 { 355 return gen_eh_region (ERT_TRY, outer); 356 } 357 358 eh_catch 359 gen_eh_region_catch (eh_region t, tree type_or_list) 360 { 361 eh_catch c, l; 362 tree type_list, type_node; 363 364 gcc_assert (t->type == ERT_TRY); 365 366 /* Ensure to always end up with a type list to normalize further 367 processing, then register each type against the runtime types map. */ 368 type_list = type_or_list; 369 if (type_or_list) 370 { 371 if (TREE_CODE (type_or_list) != TREE_LIST) 372 type_list = tree_cons (NULL_TREE, type_or_list, NULL_TREE); 373 374 type_node = type_list; 375 for (; type_node; type_node = TREE_CHAIN (type_node)) 376 add_type_for_runtime (TREE_VALUE (type_node)); 377 } 378 379 c = ggc_alloc_cleared_eh_catch_d (); 380 c->type_list = type_list; 381 l = t->u.eh_try.last_catch; 382 c->prev_catch = l; 383 if (l) 384 l->next_catch = c; 385 else 386 t->u.eh_try.first_catch = c; 387 t->u.eh_try.last_catch = c; 388 389 return c; 390 } 391 392 eh_region 393 gen_eh_region_allowed (eh_region outer, tree allowed) 394 { 395 eh_region region = gen_eh_region (ERT_ALLOWED_EXCEPTIONS, outer); 396 region->u.allowed.type_list = allowed; 397 398 for (; allowed ; allowed = TREE_CHAIN (allowed)) 399 add_type_for_runtime (TREE_VALUE (allowed)); 400 401 return region; 402 } 403 404 eh_region 405 gen_eh_region_must_not_throw (eh_region outer) 406 { 407 return gen_eh_region (ERT_MUST_NOT_THROW, outer); 408 } 409 410 eh_landing_pad 411 gen_eh_landing_pad (eh_region region) 412 { 413 eh_landing_pad lp = ggc_alloc_cleared_eh_landing_pad_d (); 414 415 lp->next_lp = region->landing_pads; 416 lp->region = region; 417 lp->index = VEC_length (eh_landing_pad, cfun->eh->lp_array); 418 region->landing_pads = lp; 419 420 VEC_safe_push (eh_landing_pad, gc, cfun->eh->lp_array, lp); 421 422 return lp; 423 } 424 425 eh_region 426 get_eh_region_from_number_fn (struct function *ifun, int i) 427 { 428 return VEC_index (eh_region, ifun->eh->region_array, i); 429 } 430 431 eh_region 432 get_eh_region_from_number (int i) 433 { 434 return get_eh_region_from_number_fn (cfun, i); 435 } 436 437 eh_landing_pad 438 get_eh_landing_pad_from_number_fn (struct function *ifun, int i) 439 { 440 return VEC_index (eh_landing_pad, ifun->eh->lp_array, i); 441 } 442 443 eh_landing_pad 444 get_eh_landing_pad_from_number (int i) 445 { 446 return get_eh_landing_pad_from_number_fn (cfun, i); 447 } 448 449 eh_region 450 get_eh_region_from_lp_number_fn (struct function *ifun, int i) 451 { 452 if (i < 0) 453 return VEC_index (eh_region, ifun->eh->region_array, -i); 454 else if (i == 0) 455 return NULL; 456 else 457 { 458 eh_landing_pad lp; 459 lp = VEC_index (eh_landing_pad, ifun->eh->lp_array, i); 460 return lp->region; 461 } 462 } 463 464 eh_region 465 get_eh_region_from_lp_number (int i) 466 { 467 return get_eh_region_from_lp_number_fn (cfun, i); 468 } 469 470 /* Returns true if the current function has exception handling regions. */ 471 472 bool 473 current_function_has_exception_handlers (void) 474 { 475 return cfun->eh->region_tree != NULL; 476 } 477 478 /* A subroutine of duplicate_eh_regions. Copy the eh_region tree at OLD. 479 Root it at OUTER, and apply LP_OFFSET to the lp numbers. */ 480 481 struct duplicate_eh_regions_data 482 { 483 duplicate_eh_regions_map label_map; 484 void *label_map_data; 485 struct pointer_map_t *eh_map; 486 }; 487 488 static void 489 duplicate_eh_regions_1 (struct duplicate_eh_regions_data *data, 490 eh_region old_r, eh_region outer) 491 { 492 eh_landing_pad old_lp, new_lp; 493 eh_region new_r; 494 void **slot; 495 496 new_r = gen_eh_region (old_r->type, outer); 497 slot = pointer_map_insert (data->eh_map, (void *)old_r); 498 gcc_assert (*slot == NULL); 499 *slot = (void *)new_r; 500 501 switch (old_r->type) 502 { 503 case ERT_CLEANUP: 504 break; 505 506 case ERT_TRY: 507 { 508 eh_catch oc, nc; 509 for (oc = old_r->u.eh_try.first_catch; oc ; oc = oc->next_catch) 510 { 511 /* We should be doing all our region duplication before and 512 during inlining, which is before filter lists are created. */ 513 gcc_assert (oc->filter_list == NULL); 514 nc = gen_eh_region_catch (new_r, oc->type_list); 515 nc->label = data->label_map (oc->label, data->label_map_data); 516 } 517 } 518 break; 519 520 case ERT_ALLOWED_EXCEPTIONS: 521 new_r->u.allowed.type_list = old_r->u.allowed.type_list; 522 if (old_r->u.allowed.label) 523 new_r->u.allowed.label 524 = data->label_map (old_r->u.allowed.label, data->label_map_data); 525 else 526 new_r->u.allowed.label = NULL_TREE; 527 break; 528 529 case ERT_MUST_NOT_THROW: 530 new_r->u.must_not_throw = old_r->u.must_not_throw; 531 break; 532 } 533 534 for (old_lp = old_r->landing_pads; old_lp ; old_lp = old_lp->next_lp) 535 { 536 /* Don't bother copying unused landing pads. */ 537 if (old_lp->post_landing_pad == NULL) 538 continue; 539 540 new_lp = gen_eh_landing_pad (new_r); 541 slot = pointer_map_insert (data->eh_map, (void *)old_lp); 542 gcc_assert (*slot == NULL); 543 *slot = (void *)new_lp; 544 545 new_lp->post_landing_pad 546 = data->label_map (old_lp->post_landing_pad, data->label_map_data); 547 EH_LANDING_PAD_NR (new_lp->post_landing_pad) = new_lp->index; 548 } 549 550 /* Make sure to preserve the original use of __cxa_end_cleanup. */ 551 new_r->use_cxa_end_cleanup = old_r->use_cxa_end_cleanup; 552 553 for (old_r = old_r->inner; old_r ; old_r = old_r->next_peer) 554 duplicate_eh_regions_1 (data, old_r, new_r); 555 } 556 557 /* Duplicate the EH regions from IFUN rooted at COPY_REGION into 558 the current function and root the tree below OUTER_REGION. 559 The special case of COPY_REGION of NULL means all regions. 560 Remap labels using MAP/MAP_DATA callback. Return a pointer map 561 that allows the caller to remap uses of both EH regions and 562 EH landing pads. */ 563 564 struct pointer_map_t * 565 duplicate_eh_regions (struct function *ifun, 566 eh_region copy_region, int outer_lp, 567 duplicate_eh_regions_map map, void *map_data) 568 { 569 struct duplicate_eh_regions_data data; 570 eh_region outer_region; 571 572 #ifdef ENABLE_CHECKING 573 verify_eh_tree (ifun); 574 #endif 575 576 data.label_map = map; 577 data.label_map_data = map_data; 578 data.eh_map = pointer_map_create (); 579 580 outer_region = get_eh_region_from_lp_number (outer_lp); 581 582 /* Copy all the regions in the subtree. */ 583 if (copy_region) 584 duplicate_eh_regions_1 (&data, copy_region, outer_region); 585 else 586 { 587 eh_region r; 588 for (r = ifun->eh->region_tree; r ; r = r->next_peer) 589 duplicate_eh_regions_1 (&data, r, outer_region); 590 } 591 592 #ifdef ENABLE_CHECKING 593 verify_eh_tree (cfun); 594 #endif 595 596 return data.eh_map; 597 } 598 599 /* Return the region that is outer to both REGION_A and REGION_B in IFUN. */ 600 601 eh_region 602 eh_region_outermost (struct function *ifun, eh_region region_a, 603 eh_region region_b) 604 { 605 sbitmap b_outer; 606 607 gcc_assert (ifun->eh->region_array); 608 gcc_assert (ifun->eh->region_tree); 609 610 b_outer = sbitmap_alloc (VEC_length (eh_region, ifun->eh->region_array)); 611 sbitmap_zero (b_outer); 612 613 do 614 { 615 SET_BIT (b_outer, region_b->index); 616 region_b = region_b->outer; 617 } 618 while (region_b); 619 620 do 621 { 622 if (TEST_BIT (b_outer, region_a->index)) 623 break; 624 region_a = region_a->outer; 625 } 626 while (region_a); 627 628 sbitmap_free (b_outer); 629 return region_a; 630 } 631 632 static int 633 t2r_eq (const void *pentry, const void *pdata) 634 { 635 const_tree const entry = (const_tree) pentry; 636 const_tree const data = (const_tree) pdata; 637 638 return TREE_PURPOSE (entry) == data; 639 } 640 641 static hashval_t 642 t2r_hash (const void *pentry) 643 { 644 const_tree const entry = (const_tree) pentry; 645 return TREE_HASH (TREE_PURPOSE (entry)); 646 } 647 648 void 649 add_type_for_runtime (tree type) 650 { 651 tree *slot; 652 653 /* If TYPE is NOP_EXPR, it means that it already is a runtime type. */ 654 if (TREE_CODE (type) == NOP_EXPR) 655 return; 656 657 slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type, 658 TREE_HASH (type), INSERT); 659 if (*slot == NULL) 660 { 661 tree runtime = lang_hooks.eh_runtime_type (type); 662 *slot = tree_cons (type, runtime, NULL_TREE); 663 } 664 } 665 666 tree 667 lookup_type_for_runtime (tree type) 668 { 669 tree *slot; 670 671 /* If TYPE is NOP_EXPR, it means that it already is a runtime type. */ 672 if (TREE_CODE (type) == NOP_EXPR) 673 return type; 674 675 slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type, 676 TREE_HASH (type), NO_INSERT); 677 678 /* We should have always inserted the data earlier. */ 679 return TREE_VALUE (*slot); 680 } 681 682 683 /* Represent an entry in @TTypes for either catch actions 684 or exception filter actions. */ 685 struct ttypes_filter { 686 tree t; 687 int filter; 688 }; 689 690 /* Compare ENTRY (a ttypes_filter entry in the hash table) with DATA 691 (a tree) for a @TTypes type node we are thinking about adding. */ 692 693 static int 694 ttypes_filter_eq (const void *pentry, const void *pdata) 695 { 696 const struct ttypes_filter *const entry 697 = (const struct ttypes_filter *) pentry; 698 const_tree const data = (const_tree) pdata; 699 700 return entry->t == data; 701 } 702 703 static hashval_t 704 ttypes_filter_hash (const void *pentry) 705 { 706 const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry; 707 return TREE_HASH (entry->t); 708 } 709 710 /* Compare ENTRY with DATA (both struct ttypes_filter) for a @TTypes 711 exception specification list we are thinking about adding. */ 712 /* ??? Currently we use the type lists in the order given. Someone 713 should put these in some canonical order. */ 714 715 static int 716 ehspec_filter_eq (const void *pentry, const void *pdata) 717 { 718 const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry; 719 const struct ttypes_filter *data = (const struct ttypes_filter *) pdata; 720 721 return type_list_equal (entry->t, data->t); 722 } 723 724 /* Hash function for exception specification lists. */ 725 726 static hashval_t 727 ehspec_filter_hash (const void *pentry) 728 { 729 const struct ttypes_filter *entry = (const struct ttypes_filter *) pentry; 730 hashval_t h = 0; 731 tree list; 732 733 for (list = entry->t; list ; list = TREE_CHAIN (list)) 734 h = (h << 5) + (h >> 27) + TREE_HASH (TREE_VALUE (list)); 735 return h; 736 } 737 738 /* Add TYPE (which may be NULL) to cfun->eh->ttype_data, using TYPES_HASH 739 to speed up the search. Return the filter value to be used. */ 740 741 static int 742 add_ttypes_entry (htab_t ttypes_hash, tree type) 743 { 744 struct ttypes_filter **slot, *n; 745 746 slot = (struct ttypes_filter **) 747 htab_find_slot_with_hash (ttypes_hash, type, TREE_HASH (type), INSERT); 748 749 if ((n = *slot) == NULL) 750 { 751 /* Filter value is a 1 based table index. */ 752 753 n = XNEW (struct ttypes_filter); 754 n->t = type; 755 n->filter = VEC_length (tree, cfun->eh->ttype_data) + 1; 756 *slot = n; 757 758 VEC_safe_push (tree, gc, cfun->eh->ttype_data, type); 759 } 760 761 return n->filter; 762 } 763 764 /* Add LIST to cfun->eh->ehspec_data, using EHSPEC_HASH and TYPES_HASH 765 to speed up the search. Return the filter value to be used. */ 766 767 static int 768 add_ehspec_entry (htab_t ehspec_hash, htab_t ttypes_hash, tree list) 769 { 770 struct ttypes_filter **slot, *n; 771 struct ttypes_filter dummy; 772 773 dummy.t = list; 774 slot = (struct ttypes_filter **) 775 htab_find_slot (ehspec_hash, &dummy, INSERT); 776 777 if ((n = *slot) == NULL) 778 { 779 int len; 780 781 if (targetm.arm_eabi_unwinder) 782 len = VEC_length (tree, cfun->eh->ehspec_data.arm_eabi); 783 else 784 len = VEC_length (uchar, cfun->eh->ehspec_data.other); 785 786 /* Filter value is a -1 based byte index into a uleb128 buffer. */ 787 788 n = XNEW (struct ttypes_filter); 789 n->t = list; 790 n->filter = -(len + 1); 791 *slot = n; 792 793 /* Generate a 0 terminated list of filter values. */ 794 for (; list ; list = TREE_CHAIN (list)) 795 { 796 if (targetm.arm_eabi_unwinder) 797 VEC_safe_push (tree, gc, cfun->eh->ehspec_data.arm_eabi, 798 TREE_VALUE (list)); 799 else 800 { 801 /* Look up each type in the list and encode its filter 802 value as a uleb128. */ 803 push_uleb128 (&cfun->eh->ehspec_data.other, 804 add_ttypes_entry (ttypes_hash, TREE_VALUE (list))); 805 } 806 } 807 if (targetm.arm_eabi_unwinder) 808 VEC_safe_push (tree, gc, cfun->eh->ehspec_data.arm_eabi, NULL_TREE); 809 else 810 VEC_safe_push (uchar, gc, cfun->eh->ehspec_data.other, 0); 811 } 812 813 return n->filter; 814 } 815 816 /* Generate the action filter values to be used for CATCH and 817 ALLOWED_EXCEPTIONS regions. When using dwarf2 exception regions, 818 we use lots of landing pads, and so every type or list can share 819 the same filter value, which saves table space. */ 820 821 void 822 assign_filter_values (void) 823 { 824 int i; 825 htab_t ttypes, ehspec; 826 eh_region r; 827 eh_catch c; 828 829 cfun->eh->ttype_data = VEC_alloc (tree, gc, 16); 830 if (targetm.arm_eabi_unwinder) 831 cfun->eh->ehspec_data.arm_eabi = VEC_alloc (tree, gc, 64); 832 else 833 cfun->eh->ehspec_data.other = VEC_alloc (uchar, gc, 64); 834 835 ttypes = htab_create (31, ttypes_filter_hash, ttypes_filter_eq, free); 836 ehspec = htab_create (31, ehspec_filter_hash, ehspec_filter_eq, free); 837 838 for (i = 1; VEC_iterate (eh_region, cfun->eh->region_array, i, r); ++i) 839 { 840 if (r == NULL) 841 continue; 842 843 switch (r->type) 844 { 845 case ERT_TRY: 846 for (c = r->u.eh_try.first_catch; c ; c = c->next_catch) 847 { 848 /* Whatever type_list is (NULL or true list), we build a list 849 of filters for the region. */ 850 c->filter_list = NULL_TREE; 851 852 if (c->type_list != NULL) 853 { 854 /* Get a filter value for each of the types caught and store 855 them in the region's dedicated list. */ 856 tree tp_node = c->type_list; 857 858 for ( ; tp_node; tp_node = TREE_CHAIN (tp_node)) 859 { 860 int flt = add_ttypes_entry (ttypes, TREE_VALUE (tp_node)); 861 tree flt_node = build_int_cst (integer_type_node, flt); 862 863 c->filter_list 864 = tree_cons (NULL_TREE, flt_node, c->filter_list); 865 } 866 } 867 else 868 { 869 /* Get a filter value for the NULL list also since it 870 will need an action record anyway. */ 871 int flt = add_ttypes_entry (ttypes, NULL); 872 tree flt_node = build_int_cst (integer_type_node, flt); 873 874 c->filter_list 875 = tree_cons (NULL_TREE, flt_node, NULL); 876 } 877 } 878 break; 879 880 case ERT_ALLOWED_EXCEPTIONS: 881 r->u.allowed.filter 882 = add_ehspec_entry (ehspec, ttypes, r->u.allowed.type_list); 883 break; 884 885 default: 886 break; 887 } 888 } 889 890 htab_delete (ttypes); 891 htab_delete (ehspec); 892 } 893 894 /* Emit SEQ into basic block just before INSN (that is assumed to be 895 first instruction of some existing BB and return the newly 896 produced block. */ 897 static basic_block 898 emit_to_new_bb_before (rtx seq, rtx insn) 899 { 900 rtx last; 901 basic_block bb; 902 edge e; 903 edge_iterator ei; 904 905 /* If there happens to be a fallthru edge (possibly created by cleanup_cfg 906 call), we don't want it to go into newly created landing pad or other EH 907 construct. */ 908 for (ei = ei_start (BLOCK_FOR_INSN (insn)->preds); (e = ei_safe_edge (ei)); ) 909 if (e->flags & EDGE_FALLTHRU) 910 force_nonfallthru (e); 911 else 912 ei_next (&ei); 913 last = emit_insn_before (seq, insn); 914 if (BARRIER_P (last)) 915 last = PREV_INSN (last); 916 bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->prev_bb); 917 update_bb_for_insn (bb); 918 bb->flags |= BB_SUPERBLOCK; 919 return bb; 920 } 921 922 /* A subroutine of dw2_build_landing_pads, also used for edge splitting 923 at the rtl level. Emit the code required by the target at a landing 924 pad for the given region. */ 925 926 void 927 expand_dw2_landing_pad_for_region (eh_region region) 928 { 929 #ifdef HAVE_exception_receiver 930 if (HAVE_exception_receiver) 931 emit_insn (gen_exception_receiver ()); 932 else 933 #endif 934 #ifdef HAVE_nonlocal_goto_receiver 935 if (HAVE_nonlocal_goto_receiver) 936 emit_insn (gen_nonlocal_goto_receiver ()); 937 else 938 #endif 939 { /* Nothing */ } 940 941 if (region->exc_ptr_reg) 942 emit_move_insn (region->exc_ptr_reg, 943 gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0))); 944 if (region->filter_reg) 945 emit_move_insn (region->filter_reg, 946 gen_rtx_REG (targetm.eh_return_filter_mode (), 947 EH_RETURN_DATA_REGNO (1))); 948 } 949 950 /* Expand the extra code needed at landing pads for dwarf2 unwinding. */ 951 952 static void 953 dw2_build_landing_pads (void) 954 { 955 int i; 956 eh_landing_pad lp; 957 int e_flags = EDGE_FALLTHRU; 958 959 /* If we're going to partition blocks, we need to be able to add 960 new landing pads later, which means that we need to hold on to 961 the post-landing-pad block. Prevent it from being merged away. 962 We'll remove this bit after partitioning. */ 963 if (flag_reorder_blocks_and_partition) 964 e_flags |= EDGE_PRESERVE; 965 966 for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i) 967 { 968 basic_block bb; 969 rtx seq; 970 edge e; 971 972 if (lp == NULL || lp->post_landing_pad == NULL) 973 continue; 974 975 start_sequence (); 976 977 lp->landing_pad = gen_label_rtx (); 978 emit_label (lp->landing_pad); 979 LABEL_PRESERVE_P (lp->landing_pad) = 1; 980 981 expand_dw2_landing_pad_for_region (lp->region); 982 983 seq = get_insns (); 984 end_sequence (); 985 986 bb = emit_to_new_bb_before (seq, label_rtx (lp->post_landing_pad)); 987 e = make_edge (bb, bb->next_bb, e_flags); 988 e->count = bb->count; 989 e->probability = REG_BR_PROB_BASE; 990 } 991 } 992 993 994 static VEC (int, heap) *sjlj_lp_call_site_index; 995 996 /* Process all active landing pads. Assign each one a compact dispatch 997 index, and a call-site index. */ 998 999 static int 1000 sjlj_assign_call_site_values (void) 1001 { 1002 htab_t ar_hash; 1003 int i, disp_index; 1004 eh_landing_pad lp; 1005 1006 crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64); 1007 ar_hash = htab_create (31, action_record_hash, action_record_eq, free); 1008 1009 disp_index = 0; 1010 call_site_base = 1; 1011 for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i) 1012 if (lp && lp->post_landing_pad) 1013 { 1014 int action, call_site; 1015 1016 /* First: build the action table. */ 1017 action = collect_one_action_chain (ar_hash, lp->region); 1018 1019 /* Next: assign call-site values. If dwarf2 terms, this would be 1020 the region number assigned by convert_to_eh_region_ranges, but 1021 handles no-action and must-not-throw differently. */ 1022 /* Map must-not-throw to otherwise unused call-site index 0. */ 1023 if (action == -2) 1024 call_site = 0; 1025 /* Map no-action to otherwise unused call-site index -1. */ 1026 else if (action == -1) 1027 call_site = -1; 1028 /* Otherwise, look it up in the table. */ 1029 else 1030 call_site = add_call_site (GEN_INT (disp_index), action, 0); 1031 VEC_replace (int, sjlj_lp_call_site_index, i, call_site); 1032 1033 disp_index++; 1034 } 1035 1036 htab_delete (ar_hash); 1037 1038 return disp_index; 1039 } 1040 1041 /* Emit code to record the current call-site index before every 1042 insn that can throw. */ 1043 1044 static void 1045 sjlj_mark_call_sites (void) 1046 { 1047 int last_call_site = -2; 1048 rtx insn, mem; 1049 1050 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn)) 1051 { 1052 eh_landing_pad lp; 1053 eh_region r; 1054 bool nothrow; 1055 int this_call_site; 1056 rtx before, p; 1057 1058 /* Reset value tracking at extended basic block boundaries. */ 1059 if (LABEL_P (insn)) 1060 last_call_site = -2; 1061 1062 if (! INSN_P (insn)) 1063 continue; 1064 1065 nothrow = get_eh_region_and_lp_from_rtx (insn, &r, &lp); 1066 if (nothrow) 1067 continue; 1068 if (lp) 1069 this_call_site = VEC_index (int, sjlj_lp_call_site_index, lp->index); 1070 else if (r == NULL) 1071 { 1072 /* Calls (and trapping insns) without notes are outside any 1073 exception handling region in this function. Mark them as 1074 no action. */ 1075 this_call_site = -1; 1076 } 1077 else 1078 { 1079 gcc_assert (r->type == ERT_MUST_NOT_THROW); 1080 this_call_site = 0; 1081 } 1082 1083 if (this_call_site != -1) 1084 crtl->uses_eh_lsda = 1; 1085 1086 if (this_call_site == last_call_site) 1087 continue; 1088 1089 /* Don't separate a call from it's argument loads. */ 1090 before = insn; 1091 if (CALL_P (insn)) 1092 before = find_first_parameter_load (insn, NULL_RTX); 1093 1094 start_sequence (); 1095 mem = adjust_address (crtl->eh.sjlj_fc, TYPE_MODE (integer_type_node), 1096 sjlj_fc_call_site_ofs); 1097 emit_move_insn (mem, GEN_INT (this_call_site)); 1098 p = get_insns (); 1099 end_sequence (); 1100 1101 emit_insn_before (p, before); 1102 last_call_site = this_call_site; 1103 } 1104 } 1105 1106 /* Construct the SjLj_Function_Context. */ 1107 1108 static void 1109 sjlj_emit_function_enter (rtx dispatch_label) 1110 { 1111 rtx fn_begin, fc, mem, seq; 1112 bool fn_begin_outside_block; 1113 rtx personality = get_personality_function (current_function_decl); 1114 1115 fc = crtl->eh.sjlj_fc; 1116 1117 start_sequence (); 1118 1119 /* We're storing this libcall's address into memory instead of 1120 calling it directly. Thus, we must call assemble_external_libcall 1121 here, as we can not depend on emit_library_call to do it for us. */ 1122 assemble_external_libcall (personality); 1123 mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs); 1124 emit_move_insn (mem, personality); 1125 1126 mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs); 1127 if (crtl->uses_eh_lsda) 1128 { 1129 char buf[20]; 1130 rtx sym; 1131 1132 ASM_GENERATE_INTERNAL_LABEL (buf, "LLSDA", current_function_funcdef_no); 1133 sym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); 1134 SYMBOL_REF_FLAGS (sym) = SYMBOL_FLAG_LOCAL; 1135 emit_move_insn (mem, sym); 1136 } 1137 else 1138 emit_move_insn (mem, const0_rtx); 1139 1140 if (dispatch_label) 1141 { 1142 #ifdef DONT_USE_BUILTIN_SETJMP 1143 rtx x, last; 1144 x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_RETURNS_TWICE, 1145 TYPE_MODE (integer_type_node), 1, 1146 plus_constant (XEXP (fc, 0), 1147 sjlj_fc_jbuf_ofs), Pmode); 1148 1149 emit_cmp_and_jump_insns (x, const0_rtx, NE, 0, 1150 TYPE_MODE (integer_type_node), 0, 1151 dispatch_label); 1152 last = get_last_insn (); 1153 if (JUMP_P (last) && any_condjump_p (last)) 1154 { 1155 gcc_assert (!find_reg_note (last, REG_BR_PROB, 0)); 1156 add_reg_note (last, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE / 100)); 1157 } 1158 #else 1159 expand_builtin_setjmp_setup (plus_constant (XEXP (fc, 0), 1160 sjlj_fc_jbuf_ofs), 1161 dispatch_label); 1162 #endif 1163 } 1164 1165 emit_library_call (unwind_sjlj_register_libfunc, LCT_NORMAL, VOIDmode, 1166 1, XEXP (fc, 0), Pmode); 1167 1168 seq = get_insns (); 1169 end_sequence (); 1170 1171 /* ??? Instead of doing this at the beginning of the function, 1172 do this in a block that is at loop level 0 and dominates all 1173 can_throw_internal instructions. */ 1174 1175 fn_begin_outside_block = true; 1176 for (fn_begin = get_insns (); ; fn_begin = NEXT_INSN (fn_begin)) 1177 if (NOTE_P (fn_begin)) 1178 { 1179 if (NOTE_KIND (fn_begin) == NOTE_INSN_FUNCTION_BEG) 1180 break; 1181 else if (NOTE_INSN_BASIC_BLOCK_P (fn_begin)) 1182 fn_begin_outside_block = false; 1183 } 1184 1185 if (fn_begin_outside_block) 1186 insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR)); 1187 else 1188 emit_insn_after (seq, fn_begin); 1189 } 1190 1191 /* Call back from expand_function_end to know where we should put 1192 the call to unwind_sjlj_unregister_libfunc if needed. */ 1193 1194 void 1195 sjlj_emit_function_exit_after (rtx after) 1196 { 1197 crtl->eh.sjlj_exit_after = after; 1198 } 1199 1200 static void 1201 sjlj_emit_function_exit (void) 1202 { 1203 rtx seq, insn; 1204 1205 start_sequence (); 1206 1207 emit_library_call (unwind_sjlj_unregister_libfunc, LCT_NORMAL, VOIDmode, 1208 1, XEXP (crtl->eh.sjlj_fc, 0), Pmode); 1209 1210 seq = get_insns (); 1211 end_sequence (); 1212 1213 /* ??? Really this can be done in any block at loop level 0 that 1214 post-dominates all can_throw_internal instructions. This is 1215 the last possible moment. */ 1216 1217 insn = crtl->eh.sjlj_exit_after; 1218 if (LABEL_P (insn)) 1219 insn = NEXT_INSN (insn); 1220 1221 emit_insn_after (seq, insn); 1222 } 1223 1224 static void 1225 sjlj_emit_dispatch_table (rtx dispatch_label, int num_dispatch) 1226 { 1227 enum machine_mode unwind_word_mode = targetm.unwind_word_mode (); 1228 enum machine_mode filter_mode = targetm.eh_return_filter_mode (); 1229 eh_landing_pad lp; 1230 rtx mem, seq, fc, before, exc_ptr_reg, filter_reg; 1231 rtx first_reachable_label; 1232 basic_block bb; 1233 eh_region r; 1234 edge e; 1235 int i, disp_index; 1236 gimple switch_stmt; 1237 1238 fc = crtl->eh.sjlj_fc; 1239 1240 start_sequence (); 1241 1242 emit_label (dispatch_label); 1243 1244 #ifndef DONT_USE_BUILTIN_SETJMP 1245 expand_builtin_setjmp_receiver (dispatch_label); 1246 1247 /* The caller of expand_builtin_setjmp_receiver is responsible for 1248 making sure that the label doesn't vanish. The only other caller 1249 is the expander for __builtin_setjmp_receiver, which places this 1250 label on the nonlocal_goto_label list. Since we're modeling these 1251 CFG edges more exactly, we can use the forced_labels list instead. */ 1252 LABEL_PRESERVE_P (dispatch_label) = 1; 1253 forced_labels 1254 = gen_rtx_EXPR_LIST (VOIDmode, dispatch_label, forced_labels); 1255 #endif 1256 1257 /* Load up exc_ptr and filter values from the function context. */ 1258 mem = adjust_address (fc, unwind_word_mode, sjlj_fc_data_ofs); 1259 if (unwind_word_mode != ptr_mode) 1260 { 1261 #ifdef POINTERS_EXTEND_UNSIGNED 1262 mem = convert_memory_address (ptr_mode, mem); 1263 #else 1264 mem = convert_to_mode (ptr_mode, mem, 0); 1265 #endif 1266 } 1267 exc_ptr_reg = force_reg (ptr_mode, mem); 1268 1269 mem = adjust_address (fc, unwind_word_mode, 1270 sjlj_fc_data_ofs + GET_MODE_SIZE (unwind_word_mode)); 1271 if (unwind_word_mode != filter_mode) 1272 mem = convert_to_mode (filter_mode, mem, 0); 1273 filter_reg = force_reg (filter_mode, mem); 1274 1275 /* Jump to one of the directly reachable regions. */ 1276 1277 disp_index = 0; 1278 first_reachable_label = NULL; 1279 1280 /* If there's exactly one call site in the function, don't bother 1281 generating a switch statement. */ 1282 switch_stmt = NULL; 1283 if (num_dispatch > 1) 1284 { 1285 tree disp; 1286 1287 mem = adjust_address (fc, TYPE_MODE (integer_type_node), 1288 sjlj_fc_call_site_ofs); 1289 disp = make_tree (integer_type_node, mem); 1290 1291 switch_stmt = gimple_build_switch_nlabels (num_dispatch, disp, NULL); 1292 } 1293 1294 for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i) 1295 if (lp && lp->post_landing_pad) 1296 { 1297 rtx seq2, label; 1298 1299 start_sequence (); 1300 1301 lp->landing_pad = dispatch_label; 1302 1303 if (num_dispatch > 1) 1304 { 1305 tree t_label, case_elt, t; 1306 1307 t_label = create_artificial_label (UNKNOWN_LOCATION); 1308 t = build_int_cst (integer_type_node, disp_index); 1309 case_elt = build_case_label (t, NULL, t_label); 1310 gimple_switch_set_label (switch_stmt, disp_index, case_elt); 1311 1312 label = label_rtx (t_label); 1313 } 1314 else 1315 label = gen_label_rtx (); 1316 1317 if (disp_index == 0) 1318 first_reachable_label = label; 1319 emit_label (label); 1320 1321 r = lp->region; 1322 if (r->exc_ptr_reg) 1323 emit_move_insn (r->exc_ptr_reg, exc_ptr_reg); 1324 if (r->filter_reg) 1325 emit_move_insn (r->filter_reg, filter_reg); 1326 1327 seq2 = get_insns (); 1328 end_sequence (); 1329 1330 before = label_rtx (lp->post_landing_pad); 1331 bb = emit_to_new_bb_before (seq2, before); 1332 e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU); 1333 e->count = bb->count; 1334 e->probability = REG_BR_PROB_BASE; 1335 1336 disp_index++; 1337 } 1338 gcc_assert (disp_index == num_dispatch); 1339 1340 if (num_dispatch > 1) 1341 { 1342 expand_case (switch_stmt); 1343 expand_builtin_trap (); 1344 } 1345 1346 seq = get_insns (); 1347 end_sequence (); 1348 1349 bb = emit_to_new_bb_before (seq, first_reachable_label); 1350 if (num_dispatch == 1) 1351 { 1352 e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU); 1353 e->count = bb->count; 1354 e->probability = REG_BR_PROB_BASE; 1355 } 1356 } 1357 1358 static void 1359 sjlj_build_landing_pads (void) 1360 { 1361 int num_dispatch; 1362 1363 num_dispatch = VEC_length (eh_landing_pad, cfun->eh->lp_array); 1364 if (num_dispatch == 0) 1365 return; 1366 VEC_safe_grow (int, heap, sjlj_lp_call_site_index, num_dispatch); 1367 1368 num_dispatch = sjlj_assign_call_site_values (); 1369 if (num_dispatch > 0) 1370 { 1371 rtx dispatch_label = gen_label_rtx (); 1372 int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node, 1373 TYPE_MODE (sjlj_fc_type_node), 1374 TYPE_ALIGN (sjlj_fc_type_node)); 1375 crtl->eh.sjlj_fc 1376 = assign_stack_local (TYPE_MODE (sjlj_fc_type_node), 1377 int_size_in_bytes (sjlj_fc_type_node), 1378 align); 1379 1380 sjlj_mark_call_sites (); 1381 sjlj_emit_function_enter (dispatch_label); 1382 sjlj_emit_dispatch_table (dispatch_label, num_dispatch); 1383 sjlj_emit_function_exit (); 1384 } 1385 1386 /* If we do not have any landing pads, we may still need to register a 1387 personality routine and (empty) LSDA to handle must-not-throw regions. */ 1388 else if (function_needs_eh_personality (cfun) != eh_personality_none) 1389 { 1390 int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node, 1391 TYPE_MODE (sjlj_fc_type_node), 1392 TYPE_ALIGN (sjlj_fc_type_node)); 1393 crtl->eh.sjlj_fc 1394 = assign_stack_local (TYPE_MODE (sjlj_fc_type_node), 1395 int_size_in_bytes (sjlj_fc_type_node), 1396 align); 1397 1398 sjlj_mark_call_sites (); 1399 sjlj_emit_function_enter (NULL_RTX); 1400 sjlj_emit_function_exit (); 1401 } 1402 1403 VEC_free (int, heap, sjlj_lp_call_site_index); 1404 } 1405 1406 /* After initial rtl generation, call back to finish generating 1407 exception support code. */ 1408 1409 static void 1410 finish_eh_generation (void) 1411 { 1412 basic_block bb; 1413 1414 /* Construct the landing pads. */ 1415 if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ) 1416 sjlj_build_landing_pads (); 1417 else 1418 dw2_build_landing_pads (); 1419 break_superblocks (); 1420 1421 if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ 1422 /* Kludge for Alpha/Tru64 (see alpha_gp_save_rtx). */ 1423 || single_succ_edge (ENTRY_BLOCK_PTR)->insns.r) 1424 commit_edge_insertions (); 1425 1426 /* Redirect all EH edges from the post_landing_pad to the landing pad. */ 1427 FOR_EACH_BB (bb) 1428 { 1429 eh_landing_pad lp; 1430 edge_iterator ei; 1431 edge e; 1432 1433 lp = get_eh_landing_pad_from_rtx (BB_END (bb)); 1434 1435 FOR_EACH_EDGE (e, ei, bb->succs) 1436 if (e->flags & EDGE_EH) 1437 break; 1438 1439 /* We should not have generated any new throwing insns during this 1440 pass, and we should not have lost any EH edges, so we only need 1441 to handle two cases here: 1442 (1) reachable handler and an existing edge to post-landing-pad, 1443 (2) no reachable handler and no edge. */ 1444 gcc_assert ((lp != NULL) == (e != NULL)); 1445 if (lp != NULL) 1446 { 1447 gcc_assert (BB_HEAD (e->dest) == label_rtx (lp->post_landing_pad)); 1448 1449 redirect_edge_succ (e, BLOCK_FOR_INSN (lp->landing_pad)); 1450 e->flags |= (CALL_P (BB_END (bb)) 1451 ? EDGE_ABNORMAL | EDGE_ABNORMAL_CALL 1452 : EDGE_ABNORMAL); 1453 } 1454 } 1455 } 1456 1457 static bool 1458 gate_handle_eh (void) 1459 { 1460 /* Nothing to do if no regions created. */ 1461 return cfun->eh->region_tree != NULL; 1462 } 1463 1464 /* Complete generation of exception handling code. */ 1465 static unsigned int 1466 rest_of_handle_eh (void) 1467 { 1468 finish_eh_generation (); 1469 cleanup_cfg (CLEANUP_NO_INSN_DEL); 1470 return 0; 1471 } 1472 1473 struct rtl_opt_pass pass_rtl_eh = 1474 { 1475 { 1476 RTL_PASS, 1477 "rtl_eh", /* name */ 1478 gate_handle_eh, /* gate */ 1479 rest_of_handle_eh, /* execute */ 1480 NULL, /* sub */ 1481 NULL, /* next */ 1482 0, /* static_pass_number */ 1483 TV_JUMP, /* tv_id */ 1484 0, /* properties_required */ 1485 0, /* properties_provided */ 1486 0, /* properties_destroyed */ 1487 0, /* todo_flags_start */ 1488 0 /* todo_flags_finish */ 1489 } 1490 }; 1491 1492 /* This section handles removing dead code for flow. */ 1493 1494 void 1495 remove_eh_landing_pad (eh_landing_pad lp) 1496 { 1497 eh_landing_pad *pp; 1498 1499 for (pp = &lp->region->landing_pads; *pp != lp; pp = &(*pp)->next_lp) 1500 continue; 1501 *pp = lp->next_lp; 1502 1503 if (lp->post_landing_pad) 1504 EH_LANDING_PAD_NR (lp->post_landing_pad) = 0; 1505 VEC_replace (eh_landing_pad, cfun->eh->lp_array, lp->index, NULL); 1506 } 1507 1508 /* Splice REGION from the region tree. */ 1509 1510 void 1511 remove_eh_handler (eh_region region) 1512 { 1513 eh_region *pp, *pp_start, p, outer; 1514 eh_landing_pad lp; 1515 1516 for (lp = region->landing_pads; lp ; lp = lp->next_lp) 1517 { 1518 if (lp->post_landing_pad) 1519 EH_LANDING_PAD_NR (lp->post_landing_pad) = 0; 1520 VEC_replace (eh_landing_pad, cfun->eh->lp_array, lp->index, NULL); 1521 } 1522 1523 outer = region->outer; 1524 if (outer) 1525 pp_start = &outer->inner; 1526 else 1527 pp_start = &cfun->eh->region_tree; 1528 for (pp = pp_start, p = *pp; p != region; pp = &p->next_peer, p = *pp) 1529 continue; 1530 if (region->inner) 1531 { 1532 *pp = p = region->inner; 1533 do 1534 { 1535 p->outer = outer; 1536 pp = &p->next_peer; 1537 p = *pp; 1538 } 1539 while (p); 1540 } 1541 *pp = region->next_peer; 1542 1543 VEC_replace (eh_region, cfun->eh->region_array, region->index, NULL); 1544 } 1545 1546 /* Invokes CALLBACK for every exception handler landing pad label. 1547 Only used by reload hackery; should not be used by new code. */ 1548 1549 void 1550 for_each_eh_label (void (*callback) (rtx)) 1551 { 1552 eh_landing_pad lp; 1553 int i; 1554 1555 for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i) 1556 { 1557 if (lp) 1558 { 1559 rtx lab = lp->landing_pad; 1560 if (lab && LABEL_P (lab)) 1561 (*callback) (lab); 1562 } 1563 } 1564 } 1565 1566 /* Create the REG_EH_REGION note for INSN, given its ECF_FLAGS for a 1567 call insn. 1568 1569 At the gimple level, we use LP_NR 1570 > 0 : The statement transfers to landing pad LP_NR 1571 = 0 : The statement is outside any EH region 1572 < 0 : The statement is within MUST_NOT_THROW region -LP_NR. 1573 1574 At the rtl level, we use LP_NR 1575 > 0 : The insn transfers to landing pad LP_NR 1576 = 0 : The insn cannot throw 1577 < 0 : The insn is within MUST_NOT_THROW region -LP_NR 1578 = INT_MIN : The insn cannot throw or execute a nonlocal-goto. 1579 missing note: The insn is outside any EH region. 1580 1581 ??? This difference probably ought to be avoided. We could stand 1582 to record nothrow for arbitrary gimple statements, and so avoid 1583 some moderately complex lookups in stmt_could_throw_p. Perhaps 1584 NOTHROW should be mapped on both sides to INT_MIN. Perhaps the 1585 no-nonlocal-goto property should be recorded elsewhere as a bit 1586 on the call_insn directly. Perhaps we should make more use of 1587 attaching the trees to call_insns (reachable via symbol_ref in 1588 direct call cases) and just pull the data out of the trees. */ 1589 1590 void 1591 make_reg_eh_region_note (rtx insn, int ecf_flags, int lp_nr) 1592 { 1593 rtx value; 1594 if (ecf_flags & ECF_NOTHROW) 1595 value = const0_rtx; 1596 else if (lp_nr != 0) 1597 value = GEN_INT (lp_nr); 1598 else 1599 return; 1600 add_reg_note (insn, REG_EH_REGION, value); 1601 } 1602 1603 /* Create a REG_EH_REGION note for a CALL_INSN that cannot throw 1604 nor perform a non-local goto. Replace the region note if it 1605 already exists. */ 1606 1607 void 1608 make_reg_eh_region_note_nothrow_nononlocal (rtx insn) 1609 { 1610 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX); 1611 rtx intmin = GEN_INT (INT_MIN); 1612 1613 if (note != 0) 1614 XEXP (note, 0) = intmin; 1615 else 1616 add_reg_note (insn, REG_EH_REGION, intmin); 1617 } 1618 1619 /* Return true if INSN could throw, assuming no REG_EH_REGION note 1620 to the contrary. */ 1621 1622 bool 1623 insn_could_throw_p (const_rtx insn) 1624 { 1625 if (!flag_exceptions) 1626 return false; 1627 if (CALL_P (insn)) 1628 return true; 1629 if (INSN_P (insn) && cfun->can_throw_non_call_exceptions) 1630 return may_trap_p (PATTERN (insn)); 1631 return false; 1632 } 1633 1634 /* Copy an REG_EH_REGION note to each insn that might throw beginning 1635 at FIRST and ending at LAST. NOTE_OR_INSN is either the source insn 1636 to look for a note, or the note itself. */ 1637 1638 void 1639 copy_reg_eh_region_note_forward (rtx note_or_insn, rtx first, rtx last) 1640 { 1641 rtx insn, note = note_or_insn; 1642 1643 if (INSN_P (note_or_insn)) 1644 { 1645 note = find_reg_note (note_or_insn, REG_EH_REGION, NULL_RTX); 1646 if (note == NULL) 1647 return; 1648 } 1649 note = XEXP (note, 0); 1650 1651 for (insn = first; insn != last ; insn = NEXT_INSN (insn)) 1652 if (!find_reg_note (insn, REG_EH_REGION, NULL_RTX) 1653 && insn_could_throw_p (insn)) 1654 add_reg_note (insn, REG_EH_REGION, note); 1655 } 1656 1657 /* Likewise, but iterate backward. */ 1658 1659 void 1660 copy_reg_eh_region_note_backward (rtx note_or_insn, rtx last, rtx first) 1661 { 1662 rtx insn, note = note_or_insn; 1663 1664 if (INSN_P (note_or_insn)) 1665 { 1666 note = find_reg_note (note_or_insn, REG_EH_REGION, NULL_RTX); 1667 if (note == NULL) 1668 return; 1669 } 1670 note = XEXP (note, 0); 1671 1672 for (insn = last; insn != first; insn = PREV_INSN (insn)) 1673 if (insn_could_throw_p (insn)) 1674 add_reg_note (insn, REG_EH_REGION, note); 1675 } 1676 1677 1678 /* Extract all EH information from INSN. Return true if the insn 1679 was marked NOTHROW. */ 1680 1681 static bool 1682 get_eh_region_and_lp_from_rtx (const_rtx insn, eh_region *pr, 1683 eh_landing_pad *plp) 1684 { 1685 eh_landing_pad lp = NULL; 1686 eh_region r = NULL; 1687 bool ret = false; 1688 rtx note; 1689 int lp_nr; 1690 1691 if (! INSN_P (insn)) 1692 goto egress; 1693 1694 if (NONJUMP_INSN_P (insn) 1695 && GET_CODE (PATTERN (insn)) == SEQUENCE) 1696 insn = XVECEXP (PATTERN (insn), 0, 0); 1697 1698 note = find_reg_note (insn, REG_EH_REGION, NULL_RTX); 1699 if (!note) 1700 { 1701 ret = !insn_could_throw_p (insn); 1702 goto egress; 1703 } 1704 1705 lp_nr = INTVAL (XEXP (note, 0)); 1706 if (lp_nr == 0 || lp_nr == INT_MIN) 1707 { 1708 ret = true; 1709 goto egress; 1710 } 1711 1712 if (lp_nr < 0) 1713 r = VEC_index (eh_region, cfun->eh->region_array, -lp_nr); 1714 else 1715 { 1716 lp = VEC_index (eh_landing_pad, cfun->eh->lp_array, lp_nr); 1717 r = lp->region; 1718 } 1719 1720 egress: 1721 *plp = lp; 1722 *pr = r; 1723 return ret; 1724 } 1725 1726 /* Return the landing pad to which INSN may go, or NULL if it does not 1727 have a reachable landing pad within this function. */ 1728 1729 eh_landing_pad 1730 get_eh_landing_pad_from_rtx (const_rtx insn) 1731 { 1732 eh_landing_pad lp; 1733 eh_region r; 1734 1735 get_eh_region_and_lp_from_rtx (insn, &r, &lp); 1736 return lp; 1737 } 1738 1739 /* Return the region to which INSN may go, or NULL if it does not 1740 have a reachable region within this function. */ 1741 1742 eh_region 1743 get_eh_region_from_rtx (const_rtx insn) 1744 { 1745 eh_landing_pad lp; 1746 eh_region r; 1747 1748 get_eh_region_and_lp_from_rtx (insn, &r, &lp); 1749 return r; 1750 } 1751 1752 /* Return true if INSN throws and is caught by something in this function. */ 1753 1754 bool 1755 can_throw_internal (const_rtx insn) 1756 { 1757 return get_eh_landing_pad_from_rtx (insn) != NULL; 1758 } 1759 1760 /* Return true if INSN throws and escapes from the current function. */ 1761 1762 bool 1763 can_throw_external (const_rtx insn) 1764 { 1765 eh_landing_pad lp; 1766 eh_region r; 1767 bool nothrow; 1768 1769 if (! INSN_P (insn)) 1770 return false; 1771 1772 if (NONJUMP_INSN_P (insn) 1773 && GET_CODE (PATTERN (insn)) == SEQUENCE) 1774 { 1775 rtx seq = PATTERN (insn); 1776 int i, n = XVECLEN (seq, 0); 1777 1778 for (i = 0; i < n; i++) 1779 if (can_throw_external (XVECEXP (seq, 0, i))) 1780 return true; 1781 1782 return false; 1783 } 1784 1785 nothrow = get_eh_region_and_lp_from_rtx (insn, &r, &lp); 1786 1787 /* If we can't throw, we obviously can't throw external. */ 1788 if (nothrow) 1789 return false; 1790 1791 /* If we have an internal landing pad, then we're not external. */ 1792 if (lp != NULL) 1793 return false; 1794 1795 /* If we're not within an EH region, then we are external. */ 1796 if (r == NULL) 1797 return true; 1798 1799 /* The only thing that ought to be left is MUST_NOT_THROW regions, 1800 which don't always have landing pads. */ 1801 gcc_assert (r->type == ERT_MUST_NOT_THROW); 1802 return false; 1803 } 1804 1805 /* Return true if INSN cannot throw at all. */ 1806 1807 bool 1808 insn_nothrow_p (const_rtx insn) 1809 { 1810 eh_landing_pad lp; 1811 eh_region r; 1812 1813 if (! INSN_P (insn)) 1814 return true; 1815 1816 if (NONJUMP_INSN_P (insn) 1817 && GET_CODE (PATTERN (insn)) == SEQUENCE) 1818 { 1819 rtx seq = PATTERN (insn); 1820 int i, n = XVECLEN (seq, 0); 1821 1822 for (i = 0; i < n; i++) 1823 if (!insn_nothrow_p (XVECEXP (seq, 0, i))) 1824 return false; 1825 1826 return true; 1827 } 1828 1829 return get_eh_region_and_lp_from_rtx (insn, &r, &lp); 1830 } 1831 1832 /* Return true if INSN can perform a non-local goto. */ 1833 /* ??? This test is here in this file because it (ab)uses REG_EH_REGION. */ 1834 1835 bool 1836 can_nonlocal_goto (const_rtx insn) 1837 { 1838 if (nonlocal_goto_handler_labels && CALL_P (insn)) 1839 { 1840 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX); 1841 if (!note || INTVAL (XEXP (note, 0)) != INT_MIN) 1842 return true; 1843 } 1844 return false; 1845 } 1846 1847 /* Set TREE_NOTHROW and crtl->all_throwers_are_sibcalls. */ 1848 1849 static unsigned int 1850 set_nothrow_function_flags (void) 1851 { 1852 rtx insn; 1853 1854 crtl->nothrow = 1; 1855 1856 /* Assume crtl->all_throwers_are_sibcalls until we encounter 1857 something that can throw an exception. We specifically exempt 1858 CALL_INSNs that are SIBLING_CALL_P, as these are really jumps, 1859 and can't throw. Most CALL_INSNs are not SIBLING_CALL_P, so this 1860 is optimistic. */ 1861 1862 crtl->all_throwers_are_sibcalls = 1; 1863 1864 /* If we don't know that this implementation of the function will 1865 actually be used, then we must not set TREE_NOTHROW, since 1866 callers must not assume that this function does not throw. */ 1867 if (TREE_NOTHROW (current_function_decl)) 1868 return 0; 1869 1870 if (! flag_exceptions) 1871 return 0; 1872 1873 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 1874 if (can_throw_external (insn)) 1875 { 1876 crtl->nothrow = 0; 1877 1878 if (!CALL_P (insn) || !SIBLING_CALL_P (insn)) 1879 { 1880 crtl->all_throwers_are_sibcalls = 0; 1881 return 0; 1882 } 1883 } 1884 1885 for (insn = crtl->epilogue_delay_list; insn; 1886 insn = XEXP (insn, 1)) 1887 if (can_throw_external (insn)) 1888 { 1889 crtl->nothrow = 0; 1890 1891 if (!CALL_P (insn) || !SIBLING_CALL_P (insn)) 1892 { 1893 crtl->all_throwers_are_sibcalls = 0; 1894 return 0; 1895 } 1896 } 1897 if (crtl->nothrow 1898 && (cgraph_function_body_availability (cgraph_get_node 1899 (current_function_decl)) 1900 >= AVAIL_AVAILABLE)) 1901 { 1902 struct cgraph_node *node = cgraph_get_node (current_function_decl); 1903 struct cgraph_edge *e; 1904 for (e = node->callers; e; e = e->next_caller) 1905 e->can_throw_external = false; 1906 cgraph_set_nothrow_flag (node, true); 1907 1908 if (dump_file) 1909 fprintf (dump_file, "Marking function nothrow: %s\n\n", 1910 current_function_name ()); 1911 } 1912 return 0; 1913 } 1914 1915 struct rtl_opt_pass pass_set_nothrow_function_flags = 1916 { 1917 { 1918 RTL_PASS, 1919 "nothrow", /* name */ 1920 NULL, /* gate */ 1921 set_nothrow_function_flags, /* execute */ 1922 NULL, /* sub */ 1923 NULL, /* next */ 1924 0, /* static_pass_number */ 1925 TV_NONE, /* tv_id */ 1926 0, /* properties_required */ 1927 0, /* properties_provided */ 1928 0, /* properties_destroyed */ 1929 0, /* todo_flags_start */ 1930 0 /* todo_flags_finish */ 1931 } 1932 }; 1933 1934 1935 /* Various hooks for unwind library. */ 1936 1937 /* Expand the EH support builtin functions: 1938 __builtin_eh_pointer and __builtin_eh_filter. */ 1939 1940 static eh_region 1941 expand_builtin_eh_common (tree region_nr_t) 1942 { 1943 HOST_WIDE_INT region_nr; 1944 eh_region region; 1945 1946 gcc_assert (host_integerp (region_nr_t, 0)); 1947 region_nr = tree_low_cst (region_nr_t, 0); 1948 1949 region = VEC_index (eh_region, cfun->eh->region_array, region_nr); 1950 1951 /* ??? We shouldn't have been able to delete a eh region without 1952 deleting all the code that depended on it. */ 1953 gcc_assert (region != NULL); 1954 1955 return region; 1956 } 1957 1958 /* Expand to the exc_ptr value from the given eh region. */ 1959 1960 rtx 1961 expand_builtin_eh_pointer (tree exp) 1962 { 1963 eh_region region 1964 = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0)); 1965 if (region->exc_ptr_reg == NULL) 1966 region->exc_ptr_reg = gen_reg_rtx (ptr_mode); 1967 return region->exc_ptr_reg; 1968 } 1969 1970 /* Expand to the filter value from the given eh region. */ 1971 1972 rtx 1973 expand_builtin_eh_filter (tree exp) 1974 { 1975 eh_region region 1976 = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0)); 1977 if (region->filter_reg == NULL) 1978 region->filter_reg = gen_reg_rtx (targetm.eh_return_filter_mode ()); 1979 return region->filter_reg; 1980 } 1981 1982 /* Copy the exc_ptr and filter values from one landing pad's registers 1983 to another. This is used to inline the resx statement. */ 1984 1985 rtx 1986 expand_builtin_eh_copy_values (tree exp) 1987 { 1988 eh_region dst 1989 = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0)); 1990 eh_region src 1991 = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 1)); 1992 enum machine_mode fmode = targetm.eh_return_filter_mode (); 1993 1994 if (dst->exc_ptr_reg == NULL) 1995 dst->exc_ptr_reg = gen_reg_rtx (ptr_mode); 1996 if (src->exc_ptr_reg == NULL) 1997 src->exc_ptr_reg = gen_reg_rtx (ptr_mode); 1998 1999 if (dst->filter_reg == NULL) 2000 dst->filter_reg = gen_reg_rtx (fmode); 2001 if (src->filter_reg == NULL) 2002 src->filter_reg = gen_reg_rtx (fmode); 2003 2004 emit_move_insn (dst->exc_ptr_reg, src->exc_ptr_reg); 2005 emit_move_insn (dst->filter_reg, src->filter_reg); 2006 2007 return const0_rtx; 2008 } 2009 2010 /* Do any necessary initialization to access arbitrary stack frames. 2011 On the SPARC, this means flushing the register windows. */ 2012 2013 void 2014 expand_builtin_unwind_init (void) 2015 { 2016 /* Set this so all the registers get saved in our frame; we need to be 2017 able to copy the saved values for any registers from frames we unwind. */ 2018 crtl->saves_all_registers = 1; 2019 2020 #ifdef SETUP_FRAME_ADDRESSES 2021 SETUP_FRAME_ADDRESSES (); 2022 #endif 2023 } 2024 2025 /* Map a non-negative number to an eh return data register number; expands 2026 to -1 if no return data register is associated with the input number. 2027 At least the inputs 0 and 1 must be mapped; the target may provide more. */ 2028 2029 rtx 2030 expand_builtin_eh_return_data_regno (tree exp) 2031 { 2032 tree which = CALL_EXPR_ARG (exp, 0); 2033 unsigned HOST_WIDE_INT iwhich; 2034 2035 if (TREE_CODE (which) != INTEGER_CST) 2036 { 2037 error ("argument of %<__builtin_eh_return_regno%> must be constant"); 2038 return constm1_rtx; 2039 } 2040 2041 iwhich = tree_low_cst (which, 1); 2042 iwhich = EH_RETURN_DATA_REGNO (iwhich); 2043 if (iwhich == INVALID_REGNUM) 2044 return constm1_rtx; 2045 2046 #ifdef DWARF_FRAME_REGNUM 2047 iwhich = DWARF_FRAME_REGNUM (iwhich); 2048 #else 2049 iwhich = DBX_REGISTER_NUMBER (iwhich); 2050 #endif 2051 2052 return GEN_INT (iwhich); 2053 } 2054 2055 /* Given a value extracted from the return address register or stack slot, 2056 return the actual address encoded in that value. */ 2057 2058 rtx 2059 expand_builtin_extract_return_addr (tree addr_tree) 2060 { 2061 rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL); 2062 2063 if (GET_MODE (addr) != Pmode 2064 && GET_MODE (addr) != VOIDmode) 2065 { 2066 #ifdef POINTERS_EXTEND_UNSIGNED 2067 addr = convert_memory_address (Pmode, addr); 2068 #else 2069 addr = convert_to_mode (Pmode, addr, 0); 2070 #endif 2071 } 2072 2073 /* First mask out any unwanted bits. */ 2074 #ifdef MASK_RETURN_ADDR 2075 expand_and (Pmode, addr, MASK_RETURN_ADDR, addr); 2076 #endif 2077 2078 /* Then adjust to find the real return address. */ 2079 #if defined (RETURN_ADDR_OFFSET) 2080 addr = plus_constant (addr, RETURN_ADDR_OFFSET); 2081 #endif 2082 2083 return addr; 2084 } 2085 2086 /* Given an actual address in addr_tree, do any necessary encoding 2087 and return the value to be stored in the return address register or 2088 stack slot so the epilogue will return to that address. */ 2089 2090 rtx 2091 expand_builtin_frob_return_addr (tree addr_tree) 2092 { 2093 rtx addr = expand_expr (addr_tree, NULL_RTX, ptr_mode, EXPAND_NORMAL); 2094 2095 addr = convert_memory_address (Pmode, addr); 2096 2097 #ifdef RETURN_ADDR_OFFSET 2098 addr = force_reg (Pmode, addr); 2099 addr = plus_constant (addr, -RETURN_ADDR_OFFSET); 2100 #endif 2101 2102 return addr; 2103 } 2104 2105 /* Set up the epilogue with the magic bits we'll need to return to the 2106 exception handler. */ 2107 2108 void 2109 expand_builtin_eh_return (tree stackadj_tree ATTRIBUTE_UNUSED, 2110 tree handler_tree) 2111 { 2112 rtx tmp; 2113 2114 #ifdef EH_RETURN_STACKADJ_RTX 2115 tmp = expand_expr (stackadj_tree, crtl->eh.ehr_stackadj, 2116 VOIDmode, EXPAND_NORMAL); 2117 tmp = convert_memory_address (Pmode, tmp); 2118 if (!crtl->eh.ehr_stackadj) 2119 crtl->eh.ehr_stackadj = copy_to_reg (tmp); 2120 else if (tmp != crtl->eh.ehr_stackadj) 2121 emit_move_insn (crtl->eh.ehr_stackadj, tmp); 2122 #endif 2123 2124 tmp = expand_expr (handler_tree, crtl->eh.ehr_handler, 2125 VOIDmode, EXPAND_NORMAL); 2126 tmp = convert_memory_address (Pmode, tmp); 2127 if (!crtl->eh.ehr_handler) 2128 crtl->eh.ehr_handler = copy_to_reg (tmp); 2129 else if (tmp != crtl->eh.ehr_handler) 2130 emit_move_insn (crtl->eh.ehr_handler, tmp); 2131 2132 if (!crtl->eh.ehr_label) 2133 crtl->eh.ehr_label = gen_label_rtx (); 2134 emit_jump (crtl->eh.ehr_label); 2135 } 2136 2137 /* Expand __builtin_eh_return. This exit path from the function loads up 2138 the eh return data registers, adjusts the stack, and branches to a 2139 given PC other than the normal return address. */ 2140 2141 void 2142 expand_eh_return (void) 2143 { 2144 rtx around_label; 2145 2146 if (! crtl->eh.ehr_label) 2147 return; 2148 2149 crtl->calls_eh_return = 1; 2150 2151 #ifdef EH_RETURN_STACKADJ_RTX 2152 emit_move_insn (EH_RETURN_STACKADJ_RTX, const0_rtx); 2153 #endif 2154 2155 around_label = gen_label_rtx (); 2156 emit_jump (around_label); 2157 2158 emit_label (crtl->eh.ehr_label); 2159 clobber_return_register (); 2160 2161 #ifdef EH_RETURN_STACKADJ_RTX 2162 emit_move_insn (EH_RETURN_STACKADJ_RTX, crtl->eh.ehr_stackadj); 2163 #endif 2164 2165 #ifdef HAVE_eh_return 2166 if (HAVE_eh_return) 2167 emit_insn (gen_eh_return (crtl->eh.ehr_handler)); 2168 else 2169 #endif 2170 { 2171 #ifdef EH_RETURN_HANDLER_RTX 2172 emit_move_insn (EH_RETURN_HANDLER_RTX, crtl->eh.ehr_handler); 2173 #else 2174 error ("__builtin_eh_return not supported on this target"); 2175 #endif 2176 } 2177 2178 emit_label (around_label); 2179 } 2180 2181 /* Convert a ptr_mode address ADDR_TREE to a Pmode address controlled by 2182 POINTERS_EXTEND_UNSIGNED and return it. */ 2183 2184 rtx 2185 expand_builtin_extend_pointer (tree addr_tree) 2186 { 2187 rtx addr = expand_expr (addr_tree, NULL_RTX, ptr_mode, EXPAND_NORMAL); 2188 int extend; 2189 2190 #ifdef POINTERS_EXTEND_UNSIGNED 2191 extend = POINTERS_EXTEND_UNSIGNED; 2192 #else 2193 /* The previous EH code did an unsigned extend by default, so we do this also 2194 for consistency. */ 2195 extend = 1; 2196 #endif 2197 2198 return convert_modes (targetm.unwind_word_mode (), ptr_mode, addr, extend); 2199 } 2200 2201 /* In the following functions, we represent entries in the action table 2202 as 1-based indices. Special cases are: 2203 2204 0: null action record, non-null landing pad; implies cleanups 2205 -1: null action record, null landing pad; implies no action 2206 -2: no call-site entry; implies must_not_throw 2207 -3: we have yet to process outer regions 2208 2209 Further, no special cases apply to the "next" field of the record. 2210 For next, 0 means end of list. */ 2211 2212 struct action_record 2213 { 2214 int offset; 2215 int filter; 2216 int next; 2217 }; 2218 2219 static int 2220 action_record_eq (const void *pentry, const void *pdata) 2221 { 2222 const struct action_record *entry = (const struct action_record *) pentry; 2223 const struct action_record *data = (const struct action_record *) pdata; 2224 return entry->filter == data->filter && entry->next == data->next; 2225 } 2226 2227 static hashval_t 2228 action_record_hash (const void *pentry) 2229 { 2230 const struct action_record *entry = (const struct action_record *) pentry; 2231 return entry->next * 1009 + entry->filter; 2232 } 2233 2234 static int 2235 add_action_record (htab_t ar_hash, int filter, int next) 2236 { 2237 struct action_record **slot, *new_ar, tmp; 2238 2239 tmp.filter = filter; 2240 tmp.next = next; 2241 slot = (struct action_record **) htab_find_slot (ar_hash, &tmp, INSERT); 2242 2243 if ((new_ar = *slot) == NULL) 2244 { 2245 new_ar = XNEW (struct action_record); 2246 new_ar->offset = VEC_length (uchar, crtl->eh.action_record_data) + 1; 2247 new_ar->filter = filter; 2248 new_ar->next = next; 2249 *slot = new_ar; 2250 2251 /* The filter value goes in untouched. The link to the next 2252 record is a "self-relative" byte offset, or zero to indicate 2253 that there is no next record. So convert the absolute 1 based 2254 indices we've been carrying around into a displacement. */ 2255 2256 push_sleb128 (&crtl->eh.action_record_data, filter); 2257 if (next) 2258 next -= VEC_length (uchar, crtl->eh.action_record_data) + 1; 2259 push_sleb128 (&crtl->eh.action_record_data, next); 2260 } 2261 2262 return new_ar->offset; 2263 } 2264 2265 static int 2266 collect_one_action_chain (htab_t ar_hash, eh_region region) 2267 { 2268 int next; 2269 2270 /* If we've reached the top of the region chain, then we have 2271 no actions, and require no landing pad. */ 2272 if (region == NULL) 2273 return -1; 2274 2275 switch (region->type) 2276 { 2277 case ERT_CLEANUP: 2278 { 2279 eh_region r; 2280 /* A cleanup adds a zero filter to the beginning of the chain, but 2281 there are special cases to look out for. If there are *only* 2282 cleanups along a path, then it compresses to a zero action. 2283 Further, if there are multiple cleanups along a path, we only 2284 need to represent one of them, as that is enough to trigger 2285 entry to the landing pad at runtime. */ 2286 next = collect_one_action_chain (ar_hash, region->outer); 2287 if (next <= 0) 2288 return 0; 2289 for (r = region->outer; r ; r = r->outer) 2290 if (r->type == ERT_CLEANUP) 2291 return next; 2292 return add_action_record (ar_hash, 0, next); 2293 } 2294 2295 case ERT_TRY: 2296 { 2297 eh_catch c; 2298 2299 /* Process the associated catch regions in reverse order. 2300 If there's a catch-all handler, then we don't need to 2301 search outer regions. Use a magic -3 value to record 2302 that we haven't done the outer search. */ 2303 next = -3; 2304 for (c = region->u.eh_try.last_catch; c ; c = c->prev_catch) 2305 { 2306 if (c->type_list == NULL) 2307 { 2308 /* Retrieve the filter from the head of the filter list 2309 where we have stored it (see assign_filter_values). */ 2310 int filter = TREE_INT_CST_LOW (TREE_VALUE (c->filter_list)); 2311 next = add_action_record (ar_hash, filter, 0); 2312 } 2313 else 2314 { 2315 /* Once the outer search is done, trigger an action record for 2316 each filter we have. */ 2317 tree flt_node; 2318 2319 if (next == -3) 2320 { 2321 next = collect_one_action_chain (ar_hash, region->outer); 2322 2323 /* If there is no next action, terminate the chain. */ 2324 if (next == -1) 2325 next = 0; 2326 /* If all outer actions are cleanups or must_not_throw, 2327 we'll have no action record for it, since we had wanted 2328 to encode these states in the call-site record directly. 2329 Add a cleanup action to the chain to catch these. */ 2330 else if (next <= 0) 2331 next = add_action_record (ar_hash, 0, 0); 2332 } 2333 2334 flt_node = c->filter_list; 2335 for (; flt_node; flt_node = TREE_CHAIN (flt_node)) 2336 { 2337 int filter = TREE_INT_CST_LOW (TREE_VALUE (flt_node)); 2338 next = add_action_record (ar_hash, filter, next); 2339 } 2340 } 2341 } 2342 return next; 2343 } 2344 2345 case ERT_ALLOWED_EXCEPTIONS: 2346 /* An exception specification adds its filter to the 2347 beginning of the chain. */ 2348 next = collect_one_action_chain (ar_hash, region->outer); 2349 2350 /* If there is no next action, terminate the chain. */ 2351 if (next == -1) 2352 next = 0; 2353 /* If all outer actions are cleanups or must_not_throw, 2354 we'll have no action record for it, since we had wanted 2355 to encode these states in the call-site record directly. 2356 Add a cleanup action to the chain to catch these. */ 2357 else if (next <= 0) 2358 next = add_action_record (ar_hash, 0, 0); 2359 2360 return add_action_record (ar_hash, region->u.allowed.filter, next); 2361 2362 case ERT_MUST_NOT_THROW: 2363 /* A must-not-throw region with no inner handlers or cleanups 2364 requires no call-site entry. Note that this differs from 2365 the no handler or cleanup case in that we do require an lsda 2366 to be generated. Return a magic -2 value to record this. */ 2367 return -2; 2368 } 2369 2370 gcc_unreachable (); 2371 } 2372 2373 static int 2374 add_call_site (rtx landing_pad, int action, int section) 2375 { 2376 call_site_record record; 2377 2378 record = ggc_alloc_call_site_record_d (); 2379 record->landing_pad = landing_pad; 2380 record->action = action; 2381 2382 VEC_safe_push (call_site_record, gc, 2383 crtl->eh.call_site_record[section], record); 2384 2385 return call_site_base + VEC_length (call_site_record, 2386 crtl->eh.call_site_record[section]) - 1; 2387 } 2388 2389 /* Turn REG_EH_REGION notes back into NOTE_INSN_EH_REGION notes. 2390 The new note numbers will not refer to region numbers, but 2391 instead to call site entries. */ 2392 2393 static unsigned int 2394 convert_to_eh_region_ranges (void) 2395 { 2396 rtx insn, iter, note; 2397 htab_t ar_hash; 2398 int last_action = -3; 2399 rtx last_action_insn = NULL_RTX; 2400 rtx last_landing_pad = NULL_RTX; 2401 rtx first_no_action_insn = NULL_RTX; 2402 int call_site = 0; 2403 int cur_sec = 0; 2404 rtx section_switch_note = NULL_RTX; 2405 rtx first_no_action_insn_before_switch = NULL_RTX; 2406 rtx last_no_action_insn_before_switch = NULL_RTX; 2407 int saved_call_site_base = call_site_base; 2408 2409 crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64); 2410 2411 ar_hash = htab_create (31, action_record_hash, action_record_eq, free); 2412 2413 for (iter = get_insns (); iter ; iter = NEXT_INSN (iter)) 2414 if (INSN_P (iter)) 2415 { 2416 eh_landing_pad lp; 2417 eh_region region; 2418 bool nothrow; 2419 int this_action; 2420 rtx this_landing_pad; 2421 2422 insn = iter; 2423 if (NONJUMP_INSN_P (insn) 2424 && GET_CODE (PATTERN (insn)) == SEQUENCE) 2425 insn = XVECEXP (PATTERN (insn), 0, 0); 2426 2427 nothrow = get_eh_region_and_lp_from_rtx (insn, ®ion, &lp); 2428 if (nothrow) 2429 continue; 2430 if (region) 2431 this_action = collect_one_action_chain (ar_hash, region); 2432 else 2433 this_action = -1; 2434 2435 /* Existence of catch handlers, or must-not-throw regions 2436 implies that an lsda is needed (even if empty). */ 2437 if (this_action != -1) 2438 crtl->uses_eh_lsda = 1; 2439 2440 /* Delay creation of region notes for no-action regions 2441 until we're sure that an lsda will be required. */ 2442 else if (last_action == -3) 2443 { 2444 first_no_action_insn = iter; 2445 last_action = -1; 2446 } 2447 2448 if (this_action >= 0) 2449 this_landing_pad = lp->landing_pad; 2450 else 2451 this_landing_pad = NULL_RTX; 2452 2453 /* Differing actions or landing pads implies a change in call-site 2454 info, which implies some EH_REGION note should be emitted. */ 2455 if (last_action != this_action 2456 || last_landing_pad != this_landing_pad) 2457 { 2458 /* If there is a queued no-action region in the other section 2459 with hot/cold partitioning, emit it now. */ 2460 if (first_no_action_insn_before_switch) 2461 { 2462 gcc_assert (this_action != -1 2463 && last_action == (first_no_action_insn 2464 ? -1 : -3)); 2465 call_site = add_call_site (NULL_RTX, 0, 0); 2466 note = emit_note_before (NOTE_INSN_EH_REGION_BEG, 2467 first_no_action_insn_before_switch); 2468 NOTE_EH_HANDLER (note) = call_site; 2469 note = emit_note_after (NOTE_INSN_EH_REGION_END, 2470 last_no_action_insn_before_switch); 2471 NOTE_EH_HANDLER (note) = call_site; 2472 gcc_assert (last_action != -3 2473 || (last_action_insn 2474 == last_no_action_insn_before_switch)); 2475 first_no_action_insn_before_switch = NULL_RTX; 2476 last_no_action_insn_before_switch = NULL_RTX; 2477 call_site_base++; 2478 } 2479 /* If we'd not seen a previous action (-3) or the previous 2480 action was must-not-throw (-2), then we do not need an 2481 end note. */ 2482 if (last_action >= -1) 2483 { 2484 /* If we delayed the creation of the begin, do it now. */ 2485 if (first_no_action_insn) 2486 { 2487 call_site = add_call_site (NULL_RTX, 0, cur_sec); 2488 note = emit_note_before (NOTE_INSN_EH_REGION_BEG, 2489 first_no_action_insn); 2490 NOTE_EH_HANDLER (note) = call_site; 2491 first_no_action_insn = NULL_RTX; 2492 } 2493 2494 note = emit_note_after (NOTE_INSN_EH_REGION_END, 2495 last_action_insn); 2496 NOTE_EH_HANDLER (note) = call_site; 2497 } 2498 2499 /* If the new action is must-not-throw, then no region notes 2500 are created. */ 2501 if (this_action >= -1) 2502 { 2503 call_site = add_call_site (this_landing_pad, 2504 this_action < 0 ? 0 : this_action, 2505 cur_sec); 2506 note = emit_note_before (NOTE_INSN_EH_REGION_BEG, iter); 2507 NOTE_EH_HANDLER (note) = call_site; 2508 } 2509 2510 last_action = this_action; 2511 last_landing_pad = this_landing_pad; 2512 } 2513 last_action_insn = iter; 2514 } 2515 else if (NOTE_P (iter) 2516 && NOTE_KIND (iter) == NOTE_INSN_SWITCH_TEXT_SECTIONS) 2517 { 2518 gcc_assert (section_switch_note == NULL_RTX); 2519 gcc_assert (flag_reorder_blocks_and_partition); 2520 section_switch_note = iter; 2521 if (first_no_action_insn) 2522 { 2523 first_no_action_insn_before_switch = first_no_action_insn; 2524 last_no_action_insn_before_switch = last_action_insn; 2525 first_no_action_insn = NULL_RTX; 2526 gcc_assert (last_action == -1); 2527 last_action = -3; 2528 } 2529 /* Force closing of current EH region before section switch and 2530 opening a new one afterwards. */ 2531 else if (last_action != -3) 2532 last_landing_pad = pc_rtx; 2533 call_site_base += VEC_length (call_site_record, 2534 crtl->eh.call_site_record[cur_sec]); 2535 cur_sec++; 2536 gcc_assert (crtl->eh.call_site_record[cur_sec] == NULL); 2537 crtl->eh.call_site_record[cur_sec] 2538 = VEC_alloc (call_site_record, gc, 10); 2539 } 2540 2541 if (last_action >= -1 && ! first_no_action_insn) 2542 { 2543 note = emit_note_after (NOTE_INSN_EH_REGION_END, last_action_insn); 2544 NOTE_EH_HANDLER (note) = call_site; 2545 } 2546 2547 call_site_base = saved_call_site_base; 2548 2549 htab_delete (ar_hash); 2550 return 0; 2551 } 2552 2553 static bool 2554 gate_convert_to_eh_region_ranges (void) 2555 { 2556 /* Nothing to do for SJLJ exceptions or if no regions created. */ 2557 if (cfun->eh->region_tree == NULL) 2558 return false; 2559 if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ) 2560 return false; 2561 return true; 2562 } 2563 2564 struct rtl_opt_pass pass_convert_to_eh_region_ranges = 2565 { 2566 { 2567 RTL_PASS, 2568 "eh_ranges", /* name */ 2569 gate_convert_to_eh_region_ranges, /* gate */ 2570 convert_to_eh_region_ranges, /* execute */ 2571 NULL, /* sub */ 2572 NULL, /* next */ 2573 0, /* static_pass_number */ 2574 TV_NONE, /* tv_id */ 2575 0, /* properties_required */ 2576 0, /* properties_provided */ 2577 0, /* properties_destroyed */ 2578 0, /* todo_flags_start */ 2579 0 /* todo_flags_finish */ 2580 } 2581 }; 2582 2583 static void 2584 push_uleb128 (VEC (uchar, gc) **data_area, unsigned int value) 2585 { 2586 do 2587 { 2588 unsigned char byte = value & 0x7f; 2589 value >>= 7; 2590 if (value) 2591 byte |= 0x80; 2592 VEC_safe_push (uchar, gc, *data_area, byte); 2593 } 2594 while (value); 2595 } 2596 2597 static void 2598 push_sleb128 (VEC (uchar, gc) **data_area, int value) 2599 { 2600 unsigned char byte; 2601 int more; 2602 2603 do 2604 { 2605 byte = value & 0x7f; 2606 value >>= 7; 2607 more = ! ((value == 0 && (byte & 0x40) == 0) 2608 || (value == -1 && (byte & 0x40) != 0)); 2609 if (more) 2610 byte |= 0x80; 2611 VEC_safe_push (uchar, gc, *data_area, byte); 2612 } 2613 while (more); 2614 } 2615 2616 2617 #ifndef HAVE_AS_LEB128 2618 static int 2619 dw2_size_of_call_site_table (int section) 2620 { 2621 int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]); 2622 int size = n * (4 + 4 + 4); 2623 int i; 2624 2625 for (i = 0; i < n; ++i) 2626 { 2627 struct call_site_record_d *cs = 2628 VEC_index (call_site_record, crtl->eh.call_site_record[section], i); 2629 size += size_of_uleb128 (cs->action); 2630 } 2631 2632 return size; 2633 } 2634 2635 static int 2636 sjlj_size_of_call_site_table (void) 2637 { 2638 int n = VEC_length (call_site_record, crtl->eh.call_site_record[0]); 2639 int size = 0; 2640 int i; 2641 2642 for (i = 0; i < n; ++i) 2643 { 2644 struct call_site_record_d *cs = 2645 VEC_index (call_site_record, crtl->eh.call_site_record[0], i); 2646 size += size_of_uleb128 (INTVAL (cs->landing_pad)); 2647 size += size_of_uleb128 (cs->action); 2648 } 2649 2650 return size; 2651 } 2652 #endif 2653 2654 static void 2655 dw2_output_call_site_table (int cs_format, int section) 2656 { 2657 int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]); 2658 int i; 2659 const char *begin; 2660 2661 if (section == 0) 2662 begin = current_function_func_begin_label; 2663 else if (first_function_block_is_cold) 2664 begin = crtl->subsections.hot_section_label; 2665 else 2666 begin = crtl->subsections.cold_section_label; 2667 2668 for (i = 0; i < n; ++i) 2669 { 2670 struct call_site_record_d *cs = 2671 VEC_index (call_site_record, crtl->eh.call_site_record[section], i); 2672 char reg_start_lab[32]; 2673 char reg_end_lab[32]; 2674 char landing_pad_lab[32]; 2675 2676 ASM_GENERATE_INTERNAL_LABEL (reg_start_lab, "LEHB", call_site_base + i); 2677 ASM_GENERATE_INTERNAL_LABEL (reg_end_lab, "LEHE", call_site_base + i); 2678 2679 if (cs->landing_pad) 2680 ASM_GENERATE_INTERNAL_LABEL (landing_pad_lab, "L", 2681 CODE_LABEL_NUMBER (cs->landing_pad)); 2682 2683 /* ??? Perhaps use insn length scaling if the assembler supports 2684 generic arithmetic. */ 2685 /* ??? Perhaps use attr_length to choose data1 or data2 instead of 2686 data4 if the function is small enough. */ 2687 if (cs_format == DW_EH_PE_uleb128) 2688 { 2689 dw2_asm_output_delta_uleb128 (reg_start_lab, begin, 2690 "region %d start", i); 2691 dw2_asm_output_delta_uleb128 (reg_end_lab, reg_start_lab, 2692 "length"); 2693 if (cs->landing_pad) 2694 dw2_asm_output_delta_uleb128 (landing_pad_lab, begin, 2695 "landing pad"); 2696 else 2697 dw2_asm_output_data_uleb128 (0, "landing pad"); 2698 } 2699 else 2700 { 2701 dw2_asm_output_delta (4, reg_start_lab, begin, 2702 "region %d start", i); 2703 dw2_asm_output_delta (4, reg_end_lab, reg_start_lab, "length"); 2704 if (cs->landing_pad) 2705 dw2_asm_output_delta (4, landing_pad_lab, begin, 2706 "landing pad"); 2707 else 2708 dw2_asm_output_data (4, 0, "landing pad"); 2709 } 2710 dw2_asm_output_data_uleb128 (cs->action, "action"); 2711 } 2712 2713 call_site_base += n; 2714 } 2715 2716 static void 2717 sjlj_output_call_site_table (void) 2718 { 2719 int n = VEC_length (call_site_record, crtl->eh.call_site_record[0]); 2720 int i; 2721 2722 for (i = 0; i < n; ++i) 2723 { 2724 struct call_site_record_d *cs = 2725 VEC_index (call_site_record, crtl->eh.call_site_record[0], i); 2726 2727 dw2_asm_output_data_uleb128 (INTVAL (cs->landing_pad), 2728 "region %d landing pad", i); 2729 dw2_asm_output_data_uleb128 (cs->action, "action"); 2730 } 2731 2732 call_site_base += n; 2733 } 2734 2735 /* Switch to the section that should be used for exception tables. */ 2736 2737 static void 2738 switch_to_exception_section (const char * ARG_UNUSED (fnname)) 2739 { 2740 section *s; 2741 2742 if (exception_section) 2743 s = exception_section; 2744 else 2745 { 2746 /* Compute the section and cache it into exception_section, 2747 unless it depends on the function name. */ 2748 if (targetm_common.have_named_sections) 2749 { 2750 int flags; 2751 2752 if (EH_TABLES_CAN_BE_READ_ONLY) 2753 { 2754 int tt_format = 2755 ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1); 2756 flags = ((! flag_pic 2757 || ((tt_format & 0x70) != DW_EH_PE_absptr 2758 && (tt_format & 0x70) != DW_EH_PE_aligned)) 2759 ? 0 : SECTION_WRITE); 2760 } 2761 else 2762 flags = SECTION_WRITE; 2763 2764 #ifdef HAVE_LD_EH_GC_SECTIONS 2765 if (flag_function_sections) 2766 { 2767 char *section_name = XNEWVEC (char, strlen (fnname) + 32); 2768 sprintf (section_name, ".gcc_except_table.%s", fnname); 2769 s = get_section (section_name, flags, NULL); 2770 free (section_name); 2771 } 2772 else 2773 #endif 2774 exception_section 2775 = s = get_section (".gcc_except_table", flags, NULL); 2776 } 2777 else 2778 exception_section 2779 = s = flag_pic ? data_section : readonly_data_section; 2780 } 2781 2782 switch_to_section (s); 2783 } 2784 2785 2786 /* Output a reference from an exception table to the type_info object TYPE. 2787 TT_FORMAT and TT_FORMAT_SIZE describe the DWARF encoding method used for 2788 the value. */ 2789 2790 static void 2791 output_ttype (tree type, int tt_format, int tt_format_size) 2792 { 2793 rtx value; 2794 bool is_public = true; 2795 2796 if (type == NULL_TREE) 2797 value = const0_rtx; 2798 else 2799 { 2800 struct varpool_node *node; 2801 2802 /* FIXME lto. pass_ipa_free_lang_data changes all types to 2803 runtime types so TYPE should already be a runtime type 2804 reference. When pass_ipa_free_lang data is made a default 2805 pass, we can then remove the call to lookup_type_for_runtime 2806 below. */ 2807 if (TYPE_P (type)) 2808 type = lookup_type_for_runtime (type); 2809 2810 value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER); 2811 2812 /* Let cgraph know that the rtti decl is used. Not all of the 2813 paths below go through assemble_integer, which would take 2814 care of this for us. */ 2815 STRIP_NOPS (type); 2816 if (TREE_CODE (type) == ADDR_EXPR) 2817 { 2818 type = TREE_OPERAND (type, 0); 2819 if (TREE_CODE (type) == VAR_DECL) 2820 { 2821 node = varpool_node (type); 2822 if (node) 2823 varpool_mark_needed_node (node); 2824 is_public = TREE_PUBLIC (type); 2825 } 2826 } 2827 else 2828 gcc_assert (TREE_CODE (type) == INTEGER_CST); 2829 } 2830 2831 /* Allow the target to override the type table entry format. */ 2832 if (targetm.asm_out.ttype (value)) 2833 return; 2834 2835 if (tt_format == DW_EH_PE_absptr || tt_format == DW_EH_PE_aligned) 2836 assemble_integer (value, tt_format_size, 2837 tt_format_size * BITS_PER_UNIT, 1); 2838 else 2839 dw2_asm_output_encoded_addr_rtx (tt_format, value, is_public, NULL); 2840 } 2841 2842 static void 2843 output_one_function_exception_table (int section) 2844 { 2845 int tt_format, cs_format, lp_format, i; 2846 #ifdef HAVE_AS_LEB128 2847 char ttype_label[32]; 2848 char cs_after_size_label[32]; 2849 char cs_end_label[32]; 2850 #else 2851 int call_site_len; 2852 #endif 2853 int have_tt_data; 2854 int tt_format_size = 0; 2855 2856 have_tt_data = (VEC_length (tree, cfun->eh->ttype_data) 2857 || (targetm.arm_eabi_unwinder 2858 ? VEC_length (tree, cfun->eh->ehspec_data.arm_eabi) 2859 : VEC_length (uchar, cfun->eh->ehspec_data.other))); 2860 2861 /* Indicate the format of the @TType entries. */ 2862 if (! have_tt_data) 2863 tt_format = DW_EH_PE_omit; 2864 else 2865 { 2866 tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1); 2867 #ifdef HAVE_AS_LEB128 2868 ASM_GENERATE_INTERNAL_LABEL (ttype_label, 2869 section ? "LLSDATTC" : "LLSDATT", 2870 current_function_funcdef_no); 2871 #endif 2872 tt_format_size = size_of_encoded_value (tt_format); 2873 2874 assemble_align (tt_format_size * BITS_PER_UNIT); 2875 } 2876 2877 targetm.asm_out.internal_label (asm_out_file, section ? "LLSDAC" : "LLSDA", 2878 current_function_funcdef_no); 2879 2880 /* The LSDA header. */ 2881 2882 /* Indicate the format of the landing pad start pointer. An omitted 2883 field implies @LPStart == @Start. */ 2884 /* Currently we always put @LPStart == @Start. This field would 2885 be most useful in moving the landing pads completely out of 2886 line to another section, but it could also be used to minimize 2887 the size of uleb128 landing pad offsets. */ 2888 lp_format = DW_EH_PE_omit; 2889 dw2_asm_output_data (1, lp_format, "@LPStart format (%s)", 2890 eh_data_format_name (lp_format)); 2891 2892 /* @LPStart pointer would go here. */ 2893 2894 dw2_asm_output_data (1, tt_format, "@TType format (%s)", 2895 eh_data_format_name (tt_format)); 2896 2897 #ifndef HAVE_AS_LEB128 2898 if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ) 2899 call_site_len = sjlj_size_of_call_site_table (); 2900 else 2901 call_site_len = dw2_size_of_call_site_table (section); 2902 #endif 2903 2904 /* A pc-relative 4-byte displacement to the @TType data. */ 2905 if (have_tt_data) 2906 { 2907 #ifdef HAVE_AS_LEB128 2908 char ttype_after_disp_label[32]; 2909 ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label, 2910 section ? "LLSDATTDC" : "LLSDATTD", 2911 current_function_funcdef_no); 2912 dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label, 2913 "@TType base offset"); 2914 ASM_OUTPUT_LABEL (asm_out_file, ttype_after_disp_label); 2915 #else 2916 /* Ug. Alignment queers things. */ 2917 unsigned int before_disp, after_disp, last_disp, disp; 2918 2919 before_disp = 1 + 1; 2920 after_disp = (1 + size_of_uleb128 (call_site_len) 2921 + call_site_len 2922 + VEC_length (uchar, crtl->eh.action_record_data) 2923 + (VEC_length (tree, cfun->eh->ttype_data) 2924 * tt_format_size)); 2925 2926 disp = after_disp; 2927 do 2928 { 2929 unsigned int disp_size, pad; 2930 2931 last_disp = disp; 2932 disp_size = size_of_uleb128 (disp); 2933 pad = before_disp + disp_size + after_disp; 2934 if (pad % tt_format_size) 2935 pad = tt_format_size - (pad % tt_format_size); 2936 else 2937 pad = 0; 2938 disp = after_disp + pad; 2939 } 2940 while (disp != last_disp); 2941 2942 dw2_asm_output_data_uleb128 (disp, "@TType base offset"); 2943 #endif 2944 } 2945 2946 /* Indicate the format of the call-site offsets. */ 2947 #ifdef HAVE_AS_LEB128 2948 cs_format = DW_EH_PE_uleb128; 2949 #else 2950 cs_format = DW_EH_PE_udata4; 2951 #endif 2952 dw2_asm_output_data (1, cs_format, "call-site format (%s)", 2953 eh_data_format_name (cs_format)); 2954 2955 #ifdef HAVE_AS_LEB128 2956 ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label, 2957 section ? "LLSDACSBC" : "LLSDACSB", 2958 current_function_funcdef_no); 2959 ASM_GENERATE_INTERNAL_LABEL (cs_end_label, 2960 section ? "LLSDACSEC" : "LLSDACSE", 2961 current_function_funcdef_no); 2962 dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label, 2963 "Call-site table length"); 2964 ASM_OUTPUT_LABEL (asm_out_file, cs_after_size_label); 2965 if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ) 2966 sjlj_output_call_site_table (); 2967 else 2968 dw2_output_call_site_table (cs_format, section); 2969 ASM_OUTPUT_LABEL (asm_out_file, cs_end_label); 2970 #else 2971 dw2_asm_output_data_uleb128 (call_site_len, "Call-site table length"); 2972 if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ) 2973 sjlj_output_call_site_table (); 2974 else 2975 dw2_output_call_site_table (cs_format, section); 2976 #endif 2977 2978 /* ??? Decode and interpret the data for flag_debug_asm. */ 2979 { 2980 uchar uc; 2981 FOR_EACH_VEC_ELT (uchar, crtl->eh.action_record_data, i, uc) 2982 dw2_asm_output_data (1, uc, i ? NULL : "Action record table"); 2983 } 2984 2985 if (have_tt_data) 2986 assemble_align (tt_format_size * BITS_PER_UNIT); 2987 2988 i = VEC_length (tree, cfun->eh->ttype_data); 2989 while (i-- > 0) 2990 { 2991 tree type = VEC_index (tree, cfun->eh->ttype_data, i); 2992 output_ttype (type, tt_format, tt_format_size); 2993 } 2994 2995 #ifdef HAVE_AS_LEB128 2996 if (have_tt_data) 2997 ASM_OUTPUT_LABEL (asm_out_file, ttype_label); 2998 #endif 2999 3000 /* ??? Decode and interpret the data for flag_debug_asm. */ 3001 if (targetm.arm_eabi_unwinder) 3002 { 3003 tree type; 3004 for (i = 0; 3005 VEC_iterate (tree, cfun->eh->ehspec_data.arm_eabi, i, type); ++i) 3006 output_ttype (type, tt_format, tt_format_size); 3007 } 3008 else 3009 { 3010 uchar uc; 3011 for (i = 0; 3012 VEC_iterate (uchar, cfun->eh->ehspec_data.other, i, uc); ++i) 3013 dw2_asm_output_data (1, uc, 3014 i ? NULL : "Exception specification table"); 3015 } 3016 } 3017 3018 void 3019 output_function_exception_table (const char *fnname) 3020 { 3021 rtx personality = get_personality_function (current_function_decl); 3022 3023 /* Not all functions need anything. */ 3024 if (! crtl->uses_eh_lsda) 3025 return; 3026 3027 if (personality) 3028 { 3029 assemble_external_libcall (personality); 3030 3031 if (targetm.asm_out.emit_except_personality) 3032 targetm.asm_out.emit_except_personality (personality); 3033 } 3034 3035 switch_to_exception_section (fnname); 3036 3037 /* If the target wants a label to begin the table, emit it here. */ 3038 targetm.asm_out.emit_except_table_label (asm_out_file); 3039 3040 output_one_function_exception_table (0); 3041 if (crtl->eh.call_site_record[1] != NULL) 3042 output_one_function_exception_table (1); 3043 3044 switch_to_section (current_function_section ()); 3045 } 3046 3047 void 3048 set_eh_throw_stmt_table (struct function *fun, struct htab *table) 3049 { 3050 fun->eh->throw_stmt_table = table; 3051 } 3052 3053 htab_t 3054 get_eh_throw_stmt_table (struct function *fun) 3055 { 3056 return fun->eh->throw_stmt_table; 3057 } 3058 3059 /* Determine if the function needs an EH personality function. */ 3060 3061 enum eh_personality_kind 3062 function_needs_eh_personality (struct function *fn) 3063 { 3064 enum eh_personality_kind kind = eh_personality_none; 3065 eh_region i; 3066 3067 FOR_ALL_EH_REGION_FN (i, fn) 3068 { 3069 switch (i->type) 3070 { 3071 case ERT_CLEANUP: 3072 /* Can do with any personality including the generic C one. */ 3073 kind = eh_personality_any; 3074 break; 3075 3076 case ERT_TRY: 3077 case ERT_ALLOWED_EXCEPTIONS: 3078 /* Always needs a EH personality function. The generic C 3079 personality doesn't handle these even for empty type lists. */ 3080 return eh_personality_lang; 3081 3082 case ERT_MUST_NOT_THROW: 3083 /* Always needs a EH personality function. The language may specify 3084 what abort routine that must be used, e.g. std::terminate. */ 3085 return eh_personality_lang; 3086 } 3087 } 3088 3089 return kind; 3090 } 3091 3092 /* Dump EH information to OUT. */ 3093 3094 void 3095 dump_eh_tree (FILE * out, struct function *fun) 3096 { 3097 eh_region i; 3098 int depth = 0; 3099 static const char *const type_name[] = { 3100 "cleanup", "try", "allowed_exceptions", "must_not_throw" 3101 }; 3102 3103 i = fun->eh->region_tree; 3104 if (!i) 3105 return; 3106 3107 fprintf (out, "Eh tree:\n"); 3108 while (1) 3109 { 3110 fprintf (out, " %*s %i %s", depth * 2, "", 3111 i->index, type_name[(int) i->type]); 3112 3113 if (i->landing_pads) 3114 { 3115 eh_landing_pad lp; 3116 3117 fprintf (out, " land:"); 3118 if (current_ir_type () == IR_GIMPLE) 3119 { 3120 for (lp = i->landing_pads; lp ; lp = lp->next_lp) 3121 { 3122 fprintf (out, "{%i,", lp->index); 3123 print_generic_expr (out, lp->post_landing_pad, 0); 3124 fputc ('}', out); 3125 if (lp->next_lp) 3126 fputc (',', out); 3127 } 3128 } 3129 else 3130 { 3131 for (lp = i->landing_pads; lp ; lp = lp->next_lp) 3132 { 3133 fprintf (out, "{%i,", lp->index); 3134 if (lp->landing_pad) 3135 fprintf (out, "%i%s,", INSN_UID (lp->landing_pad), 3136 NOTE_P (lp->landing_pad) ? "(del)" : ""); 3137 else 3138 fprintf (out, "(nil),"); 3139 if (lp->post_landing_pad) 3140 { 3141 rtx lab = label_rtx (lp->post_landing_pad); 3142 fprintf (out, "%i%s}", INSN_UID (lab), 3143 NOTE_P (lab) ? "(del)" : ""); 3144 } 3145 else 3146 fprintf (out, "(nil)}"); 3147 if (lp->next_lp) 3148 fputc (',', out); 3149 } 3150 } 3151 } 3152 3153 switch (i->type) 3154 { 3155 case ERT_CLEANUP: 3156 case ERT_MUST_NOT_THROW: 3157 break; 3158 3159 case ERT_TRY: 3160 { 3161 eh_catch c; 3162 fprintf (out, " catch:"); 3163 for (c = i->u.eh_try.first_catch; c; c = c->next_catch) 3164 { 3165 fputc ('{', out); 3166 if (c->label) 3167 { 3168 fprintf (out, "lab:"); 3169 print_generic_expr (out, c->label, 0); 3170 fputc (';', out); 3171 } 3172 print_generic_expr (out, c->type_list, 0); 3173 fputc ('}', out); 3174 if (c->next_catch) 3175 fputc (',', out); 3176 } 3177 } 3178 break; 3179 3180 case ERT_ALLOWED_EXCEPTIONS: 3181 fprintf (out, " filter :%i types:", i->u.allowed.filter); 3182 print_generic_expr (out, i->u.allowed.type_list, 0); 3183 break; 3184 } 3185 fputc ('\n', out); 3186 3187 /* If there are sub-regions, process them. */ 3188 if (i->inner) 3189 i = i->inner, depth++; 3190 /* If there are peers, process them. */ 3191 else if (i->next_peer) 3192 i = i->next_peer; 3193 /* Otherwise, step back up the tree to the next peer. */ 3194 else 3195 { 3196 do 3197 { 3198 i = i->outer; 3199 depth--; 3200 if (i == NULL) 3201 return; 3202 } 3203 while (i->next_peer == NULL); 3204 i = i->next_peer; 3205 } 3206 } 3207 } 3208 3209 /* Dump the EH tree for FN on stderr. */ 3210 3211 DEBUG_FUNCTION void 3212 debug_eh_tree (struct function *fn) 3213 { 3214 dump_eh_tree (stderr, fn); 3215 } 3216 3217 /* Verify invariants on EH datastructures. */ 3218 3219 DEBUG_FUNCTION void 3220 verify_eh_tree (struct function *fun) 3221 { 3222 eh_region r, outer; 3223 int nvisited_lp, nvisited_r; 3224 int count_lp, count_r, depth, i; 3225 eh_landing_pad lp; 3226 bool err = false; 3227 3228 if (!fun->eh->region_tree) 3229 return; 3230 3231 count_r = 0; 3232 for (i = 1; VEC_iterate (eh_region, fun->eh->region_array, i, r); ++i) 3233 if (r) 3234 { 3235 if (r->index == i) 3236 count_r++; 3237 else 3238 { 3239 error ("region_array is corrupted for region %i", r->index); 3240 err = true; 3241 } 3242 } 3243 3244 count_lp = 0; 3245 for (i = 1; VEC_iterate (eh_landing_pad, fun->eh->lp_array, i, lp); ++i) 3246 if (lp) 3247 { 3248 if (lp->index == i) 3249 count_lp++; 3250 else 3251 { 3252 error ("lp_array is corrupted for lp %i", lp->index); 3253 err = true; 3254 } 3255 } 3256 3257 depth = nvisited_lp = nvisited_r = 0; 3258 outer = NULL; 3259 r = fun->eh->region_tree; 3260 while (1) 3261 { 3262 if (VEC_index (eh_region, fun->eh->region_array, r->index) != r) 3263 { 3264 error ("region_array is corrupted for region %i", r->index); 3265 err = true; 3266 } 3267 if (r->outer != outer) 3268 { 3269 error ("outer block of region %i is wrong", r->index); 3270 err = true; 3271 } 3272 if (depth < 0) 3273 { 3274 error ("negative nesting depth of region %i", r->index); 3275 err = true; 3276 } 3277 nvisited_r++; 3278 3279 for (lp = r->landing_pads; lp ; lp = lp->next_lp) 3280 { 3281 if (VEC_index (eh_landing_pad, fun->eh->lp_array, lp->index) != lp) 3282 { 3283 error ("lp_array is corrupted for lp %i", lp->index); 3284 err = true; 3285 } 3286 if (lp->region != r) 3287 { 3288 error ("region of lp %i is wrong", lp->index); 3289 err = true; 3290 } 3291 nvisited_lp++; 3292 } 3293 3294 if (r->inner) 3295 outer = r, r = r->inner, depth++; 3296 else if (r->next_peer) 3297 r = r->next_peer; 3298 else 3299 { 3300 do 3301 { 3302 r = r->outer; 3303 if (r == NULL) 3304 goto region_done; 3305 depth--; 3306 outer = r->outer; 3307 } 3308 while (r->next_peer == NULL); 3309 r = r->next_peer; 3310 } 3311 } 3312 region_done: 3313 if (depth != 0) 3314 { 3315 error ("tree list ends on depth %i", depth); 3316 err = true; 3317 } 3318 if (count_r != nvisited_r) 3319 { 3320 error ("region_array does not match region_tree"); 3321 err = true; 3322 } 3323 if (count_lp != nvisited_lp) 3324 { 3325 error ("lp_array does not match region_tree"); 3326 err = true; 3327 } 3328 3329 if (err) 3330 { 3331 dump_eh_tree (stderr, fun); 3332 internal_error ("verify_eh_tree failed"); 3333 } 3334 } 3335 3336 #include "gt-except.h" 3337