cfgrtl.c (rtl_delete_block): Fix comment.
* cfgrtl.c (rtl_delete_block): Fix comment. * emit-rtl.c (remove_unnecessary_notes): Die if we see BLOCK_BEG or BLOCK_END insn notes. * jump.c (squeeze_notes): Likewise. * haifa-sched.c (reemit_notes): Don't "re-emit" EH_REGION_BEG and EH_REGION_END notes, we never have them to begin with. * sched-deps.c (sched_analyze_insn): When updating loop notes, verify that we have indeed only recorded loop notes. (sched_analyze): Die if we see EH_REGION_BEG or EH_REGION_END notes. Only record loop notes. * cfgexpand.c (tree_expand_cfg): Fix comment. * passes.c (rest_of_compilation): Don't do a second call to convert_from_eh_region_ranges from here, it's already called from cfgexpand.c. * except.c (resolve_fixup_regions): Remove. (remove_fixup_regions): Remove. (convert_from_eh_region_ranges_1): Remove. (convert_from_eh_region_ranges): Remove the case where EH is not already lowered at the tree level. We always lower there. From-SVN: r91148
This commit is contained in:
parent
b4345a57d8
commit
f39e46bac1
|
@ -1,7 +1,30 @@
|
|||
2004-11-24 Steven Bosscher <stevenb@suse.de>
|
||||
|
||||
* cfgrtl.c (rtl_delete_block): Fix comment.
|
||||
* emit-rtl.c (remove_unnecessary_notes): Die if we see BLOCK_BEG
|
||||
or BLOCK_END insn notes.
|
||||
* jump.c (squeeze_notes): Likewise.
|
||||
* haifa-sched.c (reemit_notes): Don't "re-emit" EH_REGION_BEG and
|
||||
EH_REGION_END notes, we never have them to begin with.
|
||||
* sched-deps.c (sched_analyze_insn): When updating loop notes,
|
||||
verify that we have indeed only recorded loop notes.
|
||||
(sched_analyze): Die if we see EH_REGION_BEG or EH_REGION_END notes.
|
||||
Only record loop notes.
|
||||
|
||||
* cfgexpand.c (tree_expand_cfg): Fix comment.
|
||||
|
||||
* passes.c (rest_of_compilation): Don't do a second call to
|
||||
convert_from_eh_region_ranges from here, it's already called
|
||||
from cfgexpand.c.
|
||||
* except.c (resolve_fixup_regions): Remove.
|
||||
(remove_fixup_regions): Remove.
|
||||
(convert_from_eh_region_ranges_1): Remove.
|
||||
(convert_from_eh_region_ranges): Remove the case where EH is
|
||||
not already lowered at the tree level. We always lower there.
|
||||
|
||||
2004-11-24 Paolo Bonzini <bonzini@gnu.org>
|
||||
|
||||
PR c++/16882
|
||||
|
||||
* tree.c (make_vector_type): Move qualifiers to the vector type,
|
||||
use the inner type's main variant and build a main variant for
|
||||
the vector type if necessary.
|
||||
|
|
|
@ -1310,8 +1310,8 @@ tree_expand_cfg (void)
|
|||
/* We're done expanding trees to RTL. */
|
||||
currently_expanding_to_rtl = 0;
|
||||
|
||||
/* Convert from NOTE_INSN_EH_REGION style notes, and do other
|
||||
sorts of eh initialization. */
|
||||
/* Convert tree EH labels to RTL EH labels, and clean out any unreachable
|
||||
EH regions. */
|
||||
convert_from_eh_region_ranges ();
|
||||
|
||||
rebuild_jump_labels (get_insns ());
|
||||
|
|
|
@ -368,14 +368,9 @@ rtl_delete_block (basic_block b)
|
|||
rtx insn, end, tmp;
|
||||
|
||||
/* If the head of this block is a CODE_LABEL, then it might be the
|
||||
label for an exception handler which can't be reached.
|
||||
|
||||
We need to remove the label from the exception_handler_label list
|
||||
and remove the associated NOTE_INSN_EH_REGION_BEG and
|
||||
NOTE_INSN_EH_REGION_END notes. */
|
||||
|
||||
label for an exception handler which can't be reached. We need
|
||||
to remove the label from the exception_handler_label list. */
|
||||
insn = BB_HEAD (b);
|
||||
|
||||
if (LABEL_P (insn))
|
||||
maybe_remove_eh_handler (insn);
|
||||
|
||||
|
|
|
@ -3728,7 +3728,6 @@ find_line_note (rtx insn)
|
|||
void
|
||||
remove_unnecessary_notes (void)
|
||||
{
|
||||
rtx block_stack = NULL_RTX;
|
||||
rtx eh_stack = NULL_RTX;
|
||||
rtx insn;
|
||||
rtx next;
|
||||
|
@ -3767,66 +3766,17 @@ remove_unnecessary_notes (void)
|
|||
break;
|
||||
|
||||
case NOTE_INSN_BLOCK_BEG:
|
||||
/* By now, all notes indicating lexical blocks should have
|
||||
NOTE_BLOCK filled in. */
|
||||
gcc_assert (NOTE_BLOCK (insn));
|
||||
block_stack = alloc_INSN_LIST (insn, block_stack);
|
||||
break;
|
||||
|
||||
case NOTE_INSN_BLOCK_END:
|
||||
/* Too many end notes. */
|
||||
gcc_assert (block_stack);
|
||||
/* Mismatched nesting. */
|
||||
gcc_assert (NOTE_BLOCK (XEXP (block_stack, 0)) == NOTE_BLOCK (insn));
|
||||
tmp = block_stack;
|
||||
block_stack = XEXP (block_stack, 1);
|
||||
free_INSN_LIST_node (tmp);
|
||||
/* BLOCK_END and BLOCK_BEG notes only exist in the `final' pass. */
|
||||
gcc_unreachable ();
|
||||
|
||||
/* Scan back to see if there are any non-note instructions
|
||||
between INSN and the beginning of this block. If not,
|
||||
then there is no PC range in the generated code that will
|
||||
actually be in this block, so there's no point in
|
||||
remembering the existence of the block. */
|
||||
for (tmp = PREV_INSN (insn); tmp; tmp = PREV_INSN (tmp))
|
||||
{
|
||||
/* This block contains a real instruction. Note that we
|
||||
don't include labels; if the only thing in the block
|
||||
is a label, then there are still no PC values that
|
||||
lie within the block. */
|
||||
if (INSN_P (tmp))
|
||||
break;
|
||||
|
||||
/* We're only interested in NOTEs. */
|
||||
if (!NOTE_P (tmp))
|
||||
continue;
|
||||
|
||||
if (NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BLOCK_BEG)
|
||||
{
|
||||
/* We just verified that this BLOCK matches us with
|
||||
the block_stack check above. Never delete the
|
||||
BLOCK for the outermost scope of the function; we
|
||||
can refer to names from that scope even if the
|
||||
block notes are messed up. */
|
||||
if (! is_body_block (NOTE_BLOCK (insn))
|
||||
&& (*debug_hooks->ignore_block) (NOTE_BLOCK (insn)))
|
||||
{
|
||||
remove_insn (tmp);
|
||||
remove_insn (insn);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BLOCK_END)
|
||||
/* There's a nested block. We need to leave the
|
||||
current block in place since otherwise the debugger
|
||||
wouldn't be able to show symbols from our block in
|
||||
the nested block. */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Too many begin notes. */
|
||||
gcc_assert (!block_stack && !eh_stack);
|
||||
/* Too many EH_REGION_BEG notes. */
|
||||
gcc_assert (!eh_stack);
|
||||
}
|
||||
|
||||
|
||||
|
|
230
gcc/except.c
230
gcc/except.c
|
@ -260,10 +260,7 @@ static hashval_t t2r_hash (const void *);
|
|||
static void add_type_for_runtime (tree);
|
||||
static tree lookup_type_for_runtime (tree);
|
||||
|
||||
static void resolve_fixup_regions (void);
|
||||
static void remove_fixup_regions (void);
|
||||
static void remove_unreachable_regions (rtx);
|
||||
static void convert_from_eh_region_ranges_1 (rtx *, int *, int);
|
||||
|
||||
static int ttypes_filter_eq (const void *, const void *);
|
||||
static hashval_t ttypes_filter_hash (const void *);
|
||||
|
@ -668,123 +665,6 @@ collect_eh_region_array (void)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resolve_one_fixup_region (struct eh_region *fixup)
|
||||
{
|
||||
struct eh_region *cleanup, *real;
|
||||
int j, n;
|
||||
|
||||
n = cfun->eh->last_region_number;
|
||||
cleanup = 0;
|
||||
|
||||
for (j = 1; j <= n; ++j)
|
||||
{
|
||||
cleanup = cfun->eh->region_array[j];
|
||||
if (cleanup && cleanup->type == ERT_CLEANUP
|
||||
&& cleanup->u.cleanup.exp == fixup->u.fixup.cleanup_exp)
|
||||
break;
|
||||
}
|
||||
gcc_assert (j <= n);
|
||||
|
||||
real = cleanup->outer;
|
||||
if (real && real->type == ERT_FIXUP)
|
||||
{
|
||||
if (!real->u.fixup.resolved)
|
||||
resolve_one_fixup_region (real);
|
||||
real = real->u.fixup.real_region;
|
||||
}
|
||||
|
||||
fixup->u.fixup.real_region = real;
|
||||
fixup->u.fixup.resolved = true;
|
||||
}
|
||||
|
||||
static void
|
||||
resolve_fixup_regions (void)
|
||||
{
|
||||
int i, n = cfun->eh->last_region_number;
|
||||
|
||||
for (i = 1; i <= n; ++i)
|
||||
{
|
||||
struct eh_region *fixup = cfun->eh->region_array[i];
|
||||
|
||||
if (!fixup || fixup->type != ERT_FIXUP || fixup->u.fixup.resolved)
|
||||
continue;
|
||||
|
||||
resolve_one_fixup_region (fixup);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now that we've discovered what region actually encloses a fixup,
|
||||
we can shuffle pointers and remove them from the tree. */
|
||||
|
||||
static void
|
||||
remove_fixup_regions (void)
|
||||
{
|
||||
int i;
|
||||
rtx insn, note;
|
||||
struct eh_region *fixup;
|
||||
|
||||
/* Walk the insn chain and adjust the REG_EH_REGION numbers
|
||||
for instructions referencing fixup regions. This is only
|
||||
strictly necessary for fixup regions with no parent, but
|
||||
doesn't hurt to do it for all regions. */
|
||||
for (insn = get_insns(); insn ; insn = NEXT_INSN (insn))
|
||||
if (INSN_P (insn)
|
||||
&& (note = find_reg_note (insn, REG_EH_REGION, NULL))
|
||||
&& INTVAL (XEXP (note, 0)) > 0
|
||||
&& (fixup = cfun->eh->region_array[INTVAL (XEXP (note, 0))])
|
||||
&& fixup->type == ERT_FIXUP)
|
||||
{
|
||||
if (fixup->u.fixup.real_region)
|
||||
XEXP (note, 0) = GEN_INT (fixup->u.fixup.real_region->region_number);
|
||||
else
|
||||
remove_note (insn, note);
|
||||
}
|
||||
|
||||
/* Remove the fixup regions from the tree. */
|
||||
for (i = cfun->eh->last_region_number; i > 0; --i)
|
||||
{
|
||||
fixup = cfun->eh->region_array[i];
|
||||
if (! fixup)
|
||||
continue;
|
||||
|
||||
/* Allow GC to maybe free some memory. */
|
||||
if (fixup->type == ERT_CLEANUP)
|
||||
fixup->u.cleanup.exp = NULL_TREE;
|
||||
|
||||
if (fixup->type != ERT_FIXUP)
|
||||
continue;
|
||||
|
||||
if (fixup->inner)
|
||||
{
|
||||
struct eh_region *parent, *p, **pp;
|
||||
|
||||
parent = fixup->u.fixup.real_region;
|
||||
|
||||
/* Fix up the children's parent pointers; find the end of
|
||||
the list. */
|
||||
for (p = fixup->inner; ; p = p->next_peer)
|
||||
{
|
||||
p->outer = parent;
|
||||
if (! p->next_peer)
|
||||
break;
|
||||
}
|
||||
|
||||
/* In the tree of cleanups, only outer-inner ordering matters.
|
||||
So link the children back in anywhere at the correct level. */
|
||||
if (parent)
|
||||
pp = &parent->inner;
|
||||
else
|
||||
pp = &cfun->eh->region_tree;
|
||||
p->next_peer = *pp;
|
||||
*pp = fixup->inner;
|
||||
fixup->inner = NULL;
|
||||
}
|
||||
|
||||
remove_eh_handler (fixup);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove all regions whose labels are not reachable from insns. */
|
||||
|
||||
static void
|
||||
|
@ -868,113 +748,23 @@ remove_unreachable_regions (rtx insns)
|
|||
free (uid_region_num);
|
||||
}
|
||||
|
||||
/* Turn NOTE_INSN_EH_REGION notes into REG_EH_REGION notes for each
|
||||
can_throw instruction in the region. */
|
||||
|
||||
static void
|
||||
convert_from_eh_region_ranges_1 (rtx *pinsns, int *orig_sp, int cur)
|
||||
{
|
||||
int *sp = orig_sp;
|
||||
rtx insn, next;
|
||||
|
||||
for (insn = *pinsns; insn ; insn = next)
|
||||
{
|
||||
next = NEXT_INSN (insn);
|
||||
if (NOTE_P (insn))
|
||||
{
|
||||
int kind = NOTE_LINE_NUMBER (insn);
|
||||
if (kind == NOTE_INSN_EH_REGION_BEG
|
||||
|| kind == NOTE_INSN_EH_REGION_END)
|
||||
{
|
||||
if (kind == NOTE_INSN_EH_REGION_BEG)
|
||||
{
|
||||
struct eh_region *r;
|
||||
|
||||
*sp++ = cur;
|
||||
cur = NOTE_EH_HANDLER (insn);
|
||||
|
||||
r = cfun->eh->region_array[cur];
|
||||
if (r->type == ERT_FIXUP)
|
||||
{
|
||||
r = r->u.fixup.real_region;
|
||||
cur = r ? r->region_number : 0;
|
||||
}
|
||||
else if (r->type == ERT_CATCH)
|
||||
{
|
||||
r = r->outer;
|
||||
cur = r ? r->region_number : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
cur = *--sp;
|
||||
|
||||
if (insn == *pinsns)
|
||||
*pinsns = next;
|
||||
remove_insn (insn);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (INSN_P (insn))
|
||||
{
|
||||
if (cur > 0
|
||||
&& ! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
|
||||
/* Calls can always potentially throw exceptions, unless
|
||||
they have a REG_EH_REGION note with a value of 0 or less.
|
||||
Which should be the only possible kind so far. */
|
||||
&& (CALL_P (insn)
|
||||
/* If we wanted exceptions for non-call insns, then
|
||||
any may_trap_p instruction could throw. */
|
||||
|| (flag_non_call_exceptions
|
||||
&& GET_CODE (PATTERN (insn)) != CLOBBER
|
||||
&& GET_CODE (PATTERN (insn)) != USE
|
||||
&& may_trap_p (PATTERN (insn)))))
|
||||
{
|
||||
REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION, GEN_INT (cur),
|
||||
REG_NOTES (insn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gcc_assert (sp == orig_sp);
|
||||
}
|
||||
|
||||
static void
|
||||
collect_rtl_labels_from_trees (void)
|
||||
{
|
||||
int i, n = cfun->eh->last_region_number;
|
||||
for (i = 1; i <= n; ++i)
|
||||
{
|
||||
struct eh_region *reg = cfun->eh->region_array[i];
|
||||
if (reg && reg->tree_label)
|
||||
reg->label = DECL_RTL_IF_SET (reg->tree_label);
|
||||
}
|
||||
}
|
||||
/* Set up EH labels for RTL. */
|
||||
|
||||
void
|
||||
convert_from_eh_region_ranges (void)
|
||||
{
|
||||
rtx insns = get_insns ();
|
||||
int i, n = cfun->eh->last_region_number;
|
||||
|
||||
if (cfun->eh->region_array)
|
||||
/* Most of the work is already done at the tree level. All we need to
|
||||
do is collect the rtl labels that correspond to the tree labels that
|
||||
collect the rtl labels that correspond to the tree labels
|
||||
we allocated earlier. */
|
||||
for (i = 1; i <= n; ++i)
|
||||
{
|
||||
/* If the region array already exists, assume we're coming from
|
||||
optimize_function_tree. In this case all we need to do is
|
||||
collect the rtl labels that correspond to the tree labels
|
||||
that we allocated earlier. */
|
||||
collect_rtl_labels_from_trees ();
|
||||
}
|
||||
else
|
||||
{
|
||||
int *stack;
|
||||
|
||||
collect_eh_region_array ();
|
||||
resolve_fixup_regions ();
|
||||
|
||||
stack = xmalloc (sizeof (int) * (cfun->eh->last_region_number + 1));
|
||||
convert_from_eh_region_ranges_1 (&insns, stack, 0);
|
||||
free (stack);
|
||||
|
||||
remove_fixup_regions ();
|
||||
struct eh_region *region = cfun->eh->region_array[i];
|
||||
if (region && region->tree_label)
|
||||
region->label = DECL_RTL_IF_SET (region->tree_label);
|
||||
}
|
||||
|
||||
remove_unreachable_regions (insns);
|
||||
|
|
|
@ -1648,11 +1648,6 @@ reemit_notes (rtx insn, rtx last)
|
|||
|
||||
last = emit_note_before (note_type, last);
|
||||
remove_note (insn, note);
|
||||
note = XEXP (note, 1);
|
||||
if (note_type == NOTE_INSN_EH_REGION_BEG
|
||||
|| note_type == NOTE_INSN_EH_REGION_END)
|
||||
NOTE_EH_HANDLER (last) = INTVAL (XEXP (note, 0));
|
||||
remove_note (insn, note);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
|
|
|
@ -248,6 +248,10 @@ squeeze_notes (rtx* startp, rtx* endp)
|
|||
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|
||||
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
|
||||
{
|
||||
/* BLOCK_BEG or BLOCK_END notes only exist in the `final' pass. */
|
||||
gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG
|
||||
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END);
|
||||
|
||||
if (insn == start)
|
||||
start = next;
|
||||
else
|
||||
|
|
|
@ -1538,10 +1538,6 @@ rest_of_clean_state (void)
|
|||
static void
|
||||
rest_of_compilation (void)
|
||||
{
|
||||
/* Convert from NOTE_INSN_EH_REGION style notes, and do other
|
||||
sorts of eh initialization. */
|
||||
convert_from_eh_region_ranges ();
|
||||
|
||||
/* If we're emitting a nested function, make sure its parent gets
|
||||
emitted as well. Doing otherwise confuses debug info. */
|
||||
{
|
||||
|
|
|
@ -976,18 +976,14 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn, rtx loop_notes)
|
|||
{
|
||||
rtx link;
|
||||
|
||||
/* Update loop_notes with any notes from this insn. Also determine
|
||||
if any of the notes on the list correspond to instruction scheduling
|
||||
barriers (loop, eh & setjmp notes, but not range notes). */
|
||||
/* Update loop_notes with any notes from this insn. */
|
||||
link = loop_notes;
|
||||
while (XEXP (link, 1))
|
||||
{
|
||||
if (INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_BEG
|
||||
|| INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_END
|
||||
|| INTVAL (XEXP (link, 0)) == NOTE_INSN_EH_REGION_BEG
|
||||
|| INTVAL (XEXP (link, 0)) == NOTE_INSN_EH_REGION_END)
|
||||
reg_pending_barrier = MOVE_BARRIER;
|
||||
gcc_assert (INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_BEG
|
||||
|| INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_END);
|
||||
|
||||
reg_pending_barrier = MOVE_BARRIER;
|
||||
link = XEXP (link, 1);
|
||||
}
|
||||
XEXP (link, 1) = REG_NOTES (insn);
|
||||
|
@ -1323,26 +1319,19 @@ sched_analyze (struct deps *deps, rtx head, rtx tail)
|
|||
deps->in_post_call_group_p = post_call;
|
||||
}
|
||||
|
||||
/* EH_REGION insn notes can not appear until well after we complete
|
||||
scheduling. */
|
||||
if (NOTE_P (insn))
|
||||
gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
|
||||
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END);
|
||||
|
||||
/* See comments on reemit_notes as to why we do this.
|
||||
??? Actually, the reemit_notes just say what is done, not why. */
|
||||
|
||||
if (NOTE_P (insn)
|
||||
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|
||||
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
|
||||
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
|
||||
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
|
||||
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|
||||
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
|
||||
{
|
||||
rtx rtx_region;
|
||||
|
||||
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
|
||||
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
|
||||
rtx_region = GEN_INT (NOTE_EH_HANDLER (insn));
|
||||
else
|
||||
rtx_region = const0_rtx;
|
||||
|
||||
loop_notes = alloc_EXPR_LIST (REG_SAVE_NOTE,
|
||||
rtx_region,
|
||||
loop_notes);
|
||||
loop_notes = alloc_EXPR_LIST (REG_SAVE_NOTE,
|
||||
GEN_INT (NOTE_LINE_NUMBER (insn)),
|
||||
loop_notes);
|
||||
|
|
Loading…
Reference in New Issue