diff options
Diffstat (limited to 'gcc/except.c')
-rw-r--r-- | gcc/except.c | 166 |
1 files changed, 38 insertions, 128 deletions
diff --git a/gcc/except.c b/gcc/except.c index bb16036..8d56e10 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -919,6 +919,34 @@ emit_to_new_bb_before (rtx seq, rtx insn) return bb; } +/* A subroutine of dw2_build_landing_pads, also used for edge splitting + at the rtl level. Emit the code required by the target at a landing + pad for the given region. */ + +void +expand_dw2_landing_pad_for_region (eh_region region) +{ +#ifdef HAVE_exception_receiver + if (HAVE_exception_receiver) + emit_insn (gen_exception_receiver ()); + else +#endif +#ifdef HAVE_nonlocal_goto_receiver + if (HAVE_nonlocal_goto_receiver) + emit_insn (gen_nonlocal_goto_receiver ()); + else +#endif + { /* Nothing */ } + + if (region->exc_ptr_reg) + emit_move_insn (region->exc_ptr_reg, + gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0))); + if (region->filter_reg) + emit_move_insn (region->filter_reg, + gen_rtx_REG (targetm.eh_return_filter_mode (), + EH_RETURN_DATA_REGNO (1))); +} + /* Expand the extra code needed at landing pads for dwarf2 unwinding. */ static void @@ -926,10 +954,17 @@ dw2_build_landing_pads (void) { int i; eh_landing_pad lp; + int e_flags = EDGE_FALLTHRU; + + /* If we're going to partition blocks, we need to be able to add + new landing pads later, which means that we need to hold on to + the post-landing-pad block. Prevent it from being merged away. + We'll remove this bit after partitioning. */ + if (flag_reorder_blocks_and_partition) + e_flags |= EDGE_PRESERVE; for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i) { - eh_region region; basic_block bb; rtx seq; edge e; @@ -943,32 +978,13 @@ dw2_build_landing_pads (void) emit_label (lp->landing_pad); LABEL_PRESERVE_P (lp->landing_pad) = 1; -#ifdef HAVE_exception_receiver - if (HAVE_exception_receiver) - emit_insn (gen_exception_receiver ()); - else -#endif -#ifdef HAVE_nonlocal_goto_receiver - if (HAVE_nonlocal_goto_receiver) - emit_insn (gen_nonlocal_goto_receiver ()); - else -#endif - { /* Nothing */ } - - region = lp->region; - if (region->exc_ptr_reg) - emit_move_insn (region->exc_ptr_reg, - gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0))); - if (region->filter_reg) - emit_move_insn (region->filter_reg, - gen_rtx_REG (targetm.eh_return_filter_mode (), - EH_RETURN_DATA_REGNO (1))); + expand_dw2_landing_pad_for_region (lp->region); seq = get_insns (); end_sequence (); bb = emit_to_new_bb_before (seq, label_rtx (lp->post_landing_pad)); - e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU); + e = make_edge (bb, bb->next_bb, e_flags); e->count = bb->count; e->probability = REG_BR_PROB_BASE; } @@ -2388,9 +2404,6 @@ convert_to_eh_region_ranges (void) rtx section_switch_note = NULL_RTX; rtx first_no_action_insn_before_switch = NULL_RTX; rtx last_no_action_insn_before_switch = NULL_RTX; - rtx *pad_map = NULL; - sbitmap pad_loc = NULL; - int min_labelno = 0, max_labelno = 0; int saved_call_site_base = call_site_base; crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64); @@ -2523,13 +2536,7 @@ convert_to_eh_region_ranges (void) gcc_assert (crtl->eh.call_site_record[cur_sec] == NULL); crtl->eh.call_site_record[cur_sec] = VEC_alloc (call_site_record, gc, 10); - max_labelno = max_label_num (); - min_labelno = get_first_label_num (); - pad_map = XCNEWVEC (rtx, max_labelno - min_labelno + 1); - pad_loc = sbitmap_alloc (max_labelno - min_labelno + 1); } - else if (LABEL_P (iter) && pad_map) - SET_BIT (pad_loc, CODE_LABEL_NUMBER (iter) - min_labelno); if (last_action >= -1 && ! first_no_action_insn) { @@ -2539,103 +2546,6 @@ convert_to_eh_region_ranges (void) call_site_base = saved_call_site_base; - if (pad_map) - { - /* When doing hot/cold partitioning, ensure landing pads are - always in the same section as the EH region, .gcc_except_table - can't express it otherwise. */ - for (cur_sec = 0; cur_sec < 2; cur_sec++) - { - int i, idx; - int n = VEC_length (call_site_record, - crtl->eh.call_site_record[cur_sec]); - basic_block prev_bb = NULL, padbb; - - for (i = 0; i < n; ++i) - { - struct call_site_record_d *cs = - VEC_index (call_site_record, - crtl->eh.call_site_record[cur_sec], i); - rtx jump, note; - - if (cs->landing_pad == NULL_RTX) - continue; - idx = CODE_LABEL_NUMBER (cs->landing_pad) - min_labelno; - /* If the landing pad is in the correct section, nothing - is needed. */ - if (TEST_BIT (pad_loc, idx) ^ (cur_sec == 0)) - continue; - /* Otherwise, if we haven't seen this pad yet, we need to - add a new label and jump to the correct section. */ - if (pad_map[idx] == NULL_RTX) - { - pad_map[idx] = gen_label_rtx (); - if (prev_bb == NULL) - for (iter = section_switch_note; - iter; iter = PREV_INSN (iter)) - if (NOTE_INSN_BASIC_BLOCK_P (iter)) - { - prev_bb = NOTE_BASIC_BLOCK (iter); - break; - } - if (cur_sec == 0) - { - note = emit_label_before (pad_map[idx], - section_switch_note); - jump = emit_jump_insn_before (gen_jump (cs->landing_pad), - section_switch_note); - } - else - { - jump = emit_jump_insn_after (gen_jump (cs->landing_pad), - section_switch_note); - note = emit_label_after (pad_map[idx], - section_switch_note); - } - JUMP_LABEL (jump) = cs->landing_pad; - add_reg_note (jump, REG_CROSSING_JUMP, NULL_RTX); - iter = NEXT_INSN (cs->landing_pad); - if (iter && NOTE_INSN_BASIC_BLOCK_P (iter)) - padbb = NOTE_BASIC_BLOCK (iter); - else - padbb = NULL; - if (padbb && prev_bb - && BB_PARTITION (padbb) != BB_UNPARTITIONED) - { - basic_block bb; - int part - = BB_PARTITION (padbb) == BB_COLD_PARTITION - ? BB_HOT_PARTITION : BB_COLD_PARTITION; - edge_iterator ei; - edge e; - - bb = create_basic_block (note, jump, prev_bb); - make_single_succ_edge (bb, padbb, EDGE_CROSSING); - BB_SET_PARTITION (bb, part); - for (ei = ei_start (padbb->preds); - (e = ei_safe_edge (ei)); ) - { - if ((e->flags & (EDGE_EH|EDGE_CROSSING)) - == (EDGE_EH|EDGE_CROSSING)) - { - redirect_edge_succ (e, bb); - e->flags &= ~EDGE_CROSSING; - } - else - ei_next (&ei); - } - if (cur_sec == 0) - prev_bb = bb; - } - } - cs->landing_pad = pad_map[idx]; - } - } - - sbitmap_free (pad_loc); - XDELETEVEC (pad_map); - } - htab_delete (ar_hash); return 0; } |