mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-28 22:11:21 +08:00
basic-block.h (make_eh_edge, [...]): Declare.
* basic-block.h (make_eh_edge, break_superblocks): Declare. * cfgbuild.c (make_eh_edge): Make global. * cfglayout.c (break_superblocks): Likewise; fix memory leak. * except.c (build_post_landing_pads, connect_post_landing_pads, dw2_build_landing_pads, sjlj_emit_function_enter, sjlj_emit_function_exit, sjlj_emit_dispatch_table, sjlj_build_landing_pads): Update CFG. (emit_to_new_bb_before): New function. (finish_eh_generation): Do not rebuild the CFG. From-SVN: r78448
This commit is contained in:
parent
b29610b3cf
commit
12c3874e62
@ -1,3 +1,15 @@
|
||||
2004-02-25 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* basic-block.h (make_eh_edge, break_superblocks): Declare.
|
||||
* cfgbuild.c (make_eh_edge): Make global.
|
||||
* cfglayout.c (break_superblocks): Likewise; fix memory leak.
|
||||
* except.c (build_post_landing_pads, connect_post_landing_pads,
|
||||
dw2_build_landing_pads, sjlj_emit_function_enter,
|
||||
sjlj_emit_function_exit, sjlj_emit_dispatch_table,
|
||||
sjlj_build_landing_pads): Update CFG.
|
||||
(emit_to_new_bb_before): New function.
|
||||
(finish_eh_generation): Do not rebuild the CFG.
|
||||
|
||||
2004-02-25 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
||||
|
||||
* config.gcc (hppa*-*-*, parisc*-*-*): Add MASK_BIG_SWITCH to all
|
||||
|
@ -566,6 +566,7 @@ extern bool purge_all_dead_edges (int);
|
||||
extern bool purge_dead_edges (basic_block);
|
||||
extern void find_sub_basic_blocks (basic_block);
|
||||
extern void find_many_sub_basic_blocks (sbitmap);
|
||||
extern void make_eh_edge (sbitmap *, basic_block, rtx);
|
||||
extern bool can_fallthru (basic_block, basic_block);
|
||||
extern void flow_nodes_print (const char *, const sbitmap, FILE *);
|
||||
extern void flow_edge_list_print (const char *, const edge *, int, FILE *);
|
||||
@ -649,6 +650,7 @@ extern void verify_dominators (enum cdi_direction);
|
||||
extern basic_block first_dom_son (enum cdi_direction, basic_block);
|
||||
extern basic_block next_dom_son (enum cdi_direction, basic_block);
|
||||
extern bool try_redirect_by_replacing_jump (edge, basic_block, bool);
|
||||
extern void break_superblocks (void);
|
||||
|
||||
#include "cfghooks.h"
|
||||
|
||||
|
@ -53,7 +53,6 @@ static void find_basic_blocks_1 (rtx);
|
||||
static rtx find_label_refs (rtx, rtx);
|
||||
static void make_edges (rtx, basic_block, basic_block, int);
|
||||
static void make_label_edge (sbitmap *, basic_block, rtx, int);
|
||||
static void make_eh_edge (sbitmap *, basic_block, rtx);
|
||||
static void find_bb_boundaries (basic_block);
|
||||
static void compute_outgoing_frequencies (basic_block);
|
||||
|
||||
@ -240,7 +239,7 @@ make_label_edge (sbitmap *edge_cache, basic_block src, rtx label, int flags)
|
||||
|
||||
/* Create the edges generated by INSN in REGION. */
|
||||
|
||||
static void
|
||||
void
|
||||
make_eh_edge (sbitmap *edge_cache, basic_block src, rtx insn)
|
||||
{
|
||||
int is_call = GET_CODE (insn) == CALL_INSN ? EDGE_ABNORMAL_CALL : 0;
|
||||
|
@ -56,7 +56,6 @@ static void change_scope (rtx, tree, tree);
|
||||
void verify_insn_chain (void);
|
||||
static void fixup_fallthru_exit_predecessor (void);
|
||||
static rtx duplicate_insn_chain (rtx, rtx);
|
||||
static void break_superblocks (void);
|
||||
static tree insn_scope (rtx);
|
||||
|
||||
rtx
|
||||
@ -1144,23 +1143,22 @@ cfg_layout_initialize (void)
|
||||
}
|
||||
|
||||
/* Splits superblocks. */
|
||||
static void
|
||||
void
|
||||
break_superblocks (void)
|
||||
{
|
||||
sbitmap superblocks;
|
||||
int i, need;
|
||||
bool need = false;
|
||||
basic_block bb;
|
||||
|
||||
superblocks = sbitmap_alloc (n_basic_blocks);
|
||||
superblocks = sbitmap_alloc (last_basic_block);
|
||||
sbitmap_zero (superblocks);
|
||||
|
||||
need = 0;
|
||||
|
||||
for (i = 0; i < n_basic_blocks; i++)
|
||||
if (BASIC_BLOCK(i)->flags & BB_SUPERBLOCK)
|
||||
FOR_EACH_BB (bb)
|
||||
if (bb->flags & BB_SUPERBLOCK)
|
||||
{
|
||||
BASIC_BLOCK(i)->flags &= ~BB_SUPERBLOCK;
|
||||
SET_BIT (superblocks, i);
|
||||
need = 1;
|
||||
bb->flags &= ~BB_SUPERBLOCK;
|
||||
SET_BIT (superblocks, bb->index);
|
||||
need = true;
|
||||
}
|
||||
|
||||
if (need)
|
||||
|
128
gcc/except.c
128
gcc/except.c
@ -1629,6 +1629,24 @@ assign_filter_values (void)
|
||||
htab_delete (ehspec);
|
||||
}
|
||||
|
||||
/* Emit SEQ into basic block just before INSN (that is assumed to be
|
||||
first instruction of some existing BB and return the newly
|
||||
produced block. */
|
||||
static basic_block
|
||||
emit_to_new_bb_before (rtx seq, rtx insn)
|
||||
{
|
||||
rtx last;
|
||||
basic_block bb;
|
||||
|
||||
last = emit_insn_before (seq, insn);
|
||||
if (GET_CODE (last) == BARRIER)
|
||||
last = PREV_INSN (last);
|
||||
bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->prev_bb);
|
||||
update_bb_for_insn (bb);
|
||||
bb->flags |= BB_SUPERBLOCK;
|
||||
return bb;
|
||||
}
|
||||
|
||||
/* Generate the code to actually handle exceptions, which will follow the
|
||||
landing pads. */
|
||||
|
||||
@ -1702,7 +1720,8 @@ build_post_landing_pads (void)
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
|
||||
emit_insn_before (seq, region->u.try.catch->label);
|
||||
emit_to_new_bb_before (seq, region->u.try.catch->label);
|
||||
|
||||
break;
|
||||
|
||||
case ERT_ALLOWED_EXCEPTIONS:
|
||||
@ -1726,7 +1745,7 @@ build_post_landing_pads (void)
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
|
||||
emit_insn_before (seq, region->label);
|
||||
emit_to_new_bb_before (seq, region->label);
|
||||
break;
|
||||
|
||||
case ERT_CLEANUP:
|
||||
@ -1758,6 +1777,7 @@ connect_post_landing_pads (void)
|
||||
struct eh_region *region = cfun->eh->region_array[i];
|
||||
struct eh_region *outer;
|
||||
rtx seq;
|
||||
rtx barrier;
|
||||
|
||||
/* Mind we don't process a region more than once. */
|
||||
if (!region || region->region_number != i)
|
||||
@ -1776,14 +1796,30 @@ connect_post_landing_pads (void)
|
||||
start_sequence ();
|
||||
|
||||
if (outer)
|
||||
emit_jump (outer->post_landing_pad);
|
||||
{
|
||||
edge e;
|
||||
basic_block src, dest;
|
||||
|
||||
emit_jump (outer->post_landing_pad);
|
||||
src = BLOCK_FOR_INSN (region->resume);
|
||||
dest = BLOCK_FOR_INSN (outer->post_landing_pad);
|
||||
while (src->succ)
|
||||
remove_edge (src->succ);
|
||||
e = make_edge (src, dest, 0);
|
||||
e->probability = REG_BR_PROB_BASE;
|
||||
e->count = src->count;
|
||||
}
|
||||
else
|
||||
emit_library_call (unwind_resume_libfunc, LCT_THROW,
|
||||
VOIDmode, 1, cfun->eh->exc_ptr, ptr_mode);
|
||||
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
emit_insn_before (seq, region->resume);
|
||||
barrier = emit_insn_before (seq, region->resume);
|
||||
/* Avoid duplicate barrier. */
|
||||
if (GET_CODE (barrier) != BARRIER)
|
||||
abort ();
|
||||
delete_insn (barrier);
|
||||
delete_insn (region->resume);
|
||||
}
|
||||
}
|
||||
@ -1799,7 +1835,9 @@ dw2_build_landing_pads (void)
|
||||
{
|
||||
struct eh_region *region = cfun->eh->region_array[i];
|
||||
rtx seq;
|
||||
basic_block bb;
|
||||
bool clobbers_hard_regs = false;
|
||||
edge e;
|
||||
|
||||
/* Mind we don't process a region more than once. */
|
||||
if (!region || region->region_number != i)
|
||||
@ -1859,7 +1897,10 @@ dw2_build_landing_pads (void)
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
|
||||
emit_insn_before (seq, region->post_landing_pad);
|
||||
bb = emit_to_new_bb_before (seq, region->post_landing_pad);
|
||||
e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
|
||||
e->count = bb->count;
|
||||
e->probability = REG_BR_PROB_BASE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2107,9 +2148,21 @@ sjlj_emit_function_enter (rtx dispatch_label)
|
||||
|
||||
for (fn_begin = get_insns (); ; fn_begin = NEXT_INSN (fn_begin))
|
||||
if (GET_CODE (fn_begin) == NOTE
|
||||
&& NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG)
|
||||
&& (NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG
|
||||
|| NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_BASIC_BLOCK))
|
||||
break;
|
||||
emit_insn_after (seq, fn_begin);
|
||||
if (NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG)
|
||||
insert_insn_on_edge (seq, ENTRY_BLOCK_PTR->succ);
|
||||
else
|
||||
{
|
||||
rtx last = BB_END (ENTRY_BLOCK_PTR->succ->dest);
|
||||
for (; ; fn_begin = NEXT_INSN (fn_begin))
|
||||
if ((GET_CODE (fn_begin) == NOTE
|
||||
&& NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG)
|
||||
|| fn_begin == last)
|
||||
break;
|
||||
emit_insn_after (seq, fn_begin);
|
||||
}
|
||||
}
|
||||
|
||||
/* Call back from expand_function_end to know where we should put
|
||||
@ -2125,6 +2178,7 @@ static void
|
||||
sjlj_emit_function_exit (void)
|
||||
{
|
||||
rtx seq;
|
||||
edge e;
|
||||
|
||||
start_sequence ();
|
||||
|
||||
@ -2138,7 +2192,31 @@ sjlj_emit_function_exit (void)
|
||||
post-dominates all can_throw_internal instructions. This is
|
||||
the last possible moment. */
|
||||
|
||||
emit_insn_after (seq, cfun->eh->sjlj_exit_after);
|
||||
for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
|
||||
if (e->flags & EDGE_FALLTHRU)
|
||||
break;
|
||||
if (e)
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
/* Figure out whether the place we are supposed to insert libcall
|
||||
is inside the last basic block or after it. In the other case
|
||||
we need to emit to edge. */
|
||||
if (e->src->next_bb != EXIT_BLOCK_PTR)
|
||||
abort ();
|
||||
for (insn = NEXT_INSN (BB_END (e->src)); insn; insn = NEXT_INSN (insn))
|
||||
if (insn == cfun->eh->sjlj_exit_after)
|
||||
break;
|
||||
if (insn)
|
||||
insert_insn_on_edge (seq, e);
|
||||
else
|
||||
{
|
||||
insn = cfun->eh->sjlj_exit_after;
|
||||
if (GET_CODE (insn) == CODE_LABEL)
|
||||
insn = NEXT_INSN (insn);
|
||||
emit_insn_after (seq, insn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2146,6 +2224,9 @@ sjlj_emit_dispatch_table (rtx dispatch_label, struct sjlj_lp_info *lp_info)
|
||||
{
|
||||
int i, first_reachable;
|
||||
rtx mem, dispatch, seq, fc;
|
||||
rtx before;
|
||||
basic_block bb;
|
||||
edge e;
|
||||
|
||||
fc = cfun->eh->sjlj_fc;
|
||||
|
||||
@ -2200,8 +2281,12 @@ sjlj_emit_dispatch_table (rtx dispatch_label, struct sjlj_lp_info *lp_info)
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
|
||||
emit_insn_before (seq, (cfun->eh->region_array[first_reachable]
|
||||
->post_landing_pad));
|
||||
before = cfun->eh->region_array[first_reachable]->post_landing_pad;
|
||||
|
||||
bb = emit_to_new_bb_before (seq, before);
|
||||
e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
|
||||
e->count = bb->count;
|
||||
e->probability = REG_BR_PROB_BASE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2235,6 +2320,8 @@ sjlj_build_landing_pads (void)
|
||||
void
|
||||
finish_eh_generation (void)
|
||||
{
|
||||
basic_block bb;
|
||||
|
||||
/* Nothing to do if no regions created. */
|
||||
if (cfun->eh->region_tree == NULL)
|
||||
return;
|
||||
@ -2269,8 +2356,25 @@ finish_eh_generation (void)
|
||||
|
||||
/* We've totally changed the CFG. Start over. */
|
||||
find_exception_handler_labels ();
|
||||
rebuild_jump_labels (get_insns ());
|
||||
find_basic_blocks (get_insns (), max_reg_num (), 0);
|
||||
break_superblocks ();
|
||||
if (USING_SJLJ_EXCEPTIONS)
|
||||
commit_edge_insertions ();
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
edge e, next;
|
||||
bool eh = false;
|
||||
for (e = bb->succ; e; e = next)
|
||||
{
|
||||
next = e->succ_next;
|
||||
if (e->flags & EDGE_EH)
|
||||
{
|
||||
remove_edge (e);
|
||||
eh = true;
|
||||
}
|
||||
}
|
||||
if (eh)
|
||||
make_eh_edge (NULL, bb, BB_END (bb));
|
||||
}
|
||||
cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user