@@ -6168,9 +6168,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
/* This is copied from the handling of non-local gotos. */
expand_builtin_setjmp_setup (buf_addr, label_r);
- nonlocal_goto_handler_labels
- = gen_rtx_EXPR_LIST (VOIDmode, label_r,
- nonlocal_goto_handler_labels);
+ note_nonlocal_goto_handler_label (label_r);
/* ??? Do not let expand_label treat us as such since we would
not want to be both on the list of non-local labels and on
the list of forced labels. */
@@ -6188,7 +6186,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
/* Remove the dispatcher label from the list of non-local labels
since the receiver labels have been added to it above. */
- remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
+ remove_from_nonlocal_goto_handler_labels (label_r);
return const0_rtx;
}
break;
@@ -338,7 +338,8 @@ make_edges (basic_block min, basic_block max, int update_p)
/* Add any appropriate EH edges. */
rtl_make_eh_edge (edge_cache, bb, insn);
- if (code == CALL_INSN && nonlocal_goto_handler_labels)
+ if (code == CALL_INSN
+ && !VEC_empty (rtx, nonlocal_goto_handler_labels))
{
/* ??? This could be made smarter: in some cases it's possible
to tell that certain calls will not do a nonlocal goto.
@@ -347,9 +348,13 @@ make_edges (basic_block min, basic_block max, int update_p)
those functions or to other nested functions that use them
could possibly do nonlocal gotos. */
if (can_nonlocal_goto (insn))
- for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
- make_label_edge (edge_cache, bb, XEXP (x, 0),
- EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+ {
+ unsigned int ix;
+ FOR_EACH_VEC_ELT_REVERSE (rtx, nonlocal_goto_handler_labels,
+ ix, x)
+ make_label_edge (edge_cache, bb, x,
+ EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+ }
}
}
@@ -1291,6 +1291,7 @@ cfg_layout_initialize (unsigned int flags)
{
rtx x;
basic_block bb;
+ unsigned int ix;
initialize_original_copy_tables ();
@@ -1299,9 +1300,9 @@ cfg_layout_initialize (unsigned int flags)
record_effective_endpoints ();
/* Make sure that the targets of non local gotos are marked. */
- for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
+ FOR_EACH_VEC_ELT_REVERSE (rtx, nonlocal_goto_handler_labels, ix, x)
{
- bb = BLOCK_FOR_INSN (XEXP (x, 0));
+ bb = BLOCK_FOR_INSN (x);
bb->flags |= BB_NON_LOCAL_GOTO_TARGET;
}
@@ -134,7 +134,7 @@ delete_insn (rtx insn)
NOTE_DELETED_LABEL_NAME (insn) = name;
}
- remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels);
+ remove_from_nonlocal_goto_handler_labels (insn);
}
if (really_delete)
@@ -1819,7 +1819,7 @@ insn_nothrow_p (const_rtx insn)
bool
can_nonlocal_goto (const_rtx insn)
{
- if (nonlocal_goto_handler_labels && CALL_P (insn))
+ if (!VEC_empty (rtx, nonlocal_goto_handler_labels) && CALL_P (insn))
{
rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
if (!note || INTVAL (XEXP (note, 0)) != INT_MIN)
@@ -268,9 +268,8 @@ struct GTY(()) rtl_data {
Used for detecting stack clobbers. */
tree stack_protect_guard;
- /* List (chain of EXPR_LIST) of labels heading the current handlers for
- nonlocal gotos. */
- rtx x_nonlocal_goto_handler_labels;
+ /* List of labels heading the current handlers for nonlocal gotos. */
+ VEC(rtx,gc) *x_nonlocal_goto_handler_labels;
/* Label that will go on function epilogue.
Jumping to this label serves as a "return" instruction
@@ -463,6 +462,30 @@ extern GTY(()) struct rtl_data x_rtl;
want to do differently. */
#define crtl (&x_rtl)
+/* Add X to the nonlocal_goto_handler_labels list. */
+
+static inline void
+note_nonlocal_goto_handler_label (rtx x)
+{
+ VEC_safe_push (rtx, gc, nonlocal_goto_handler_labels, x);
+}
+
+/* Remove X from the nonlocal_goto_handler_labels list. */
+
+static inline void
+remove_from_nonlocal_goto_handler_labels (rtx label)
+{
+ unsigned ix;
+ rtx x;
+
+ FOR_EACH_VEC_ELT_REVERSE (rtx, nonlocal_goto_handler_labels, ix, x)
+ if (x == label)
+ {
+ VEC_unordered_remove (rtx, nonlocal_goto_handler_labels, ix);
+ return;
+ }
+}
+
struct GTY(()) stack_usage
{
/* # of bytes of static stack space allocated by the function. */
@@ -3291,7 +3291,7 @@ peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt)
delete_insn_chain (insn, peep2_insn_data[i].insn, false);
/* Re-insert the EH_REGION notes. */
- if (note || (was_call && nonlocal_goto_handler_labels))
+ if (note || (was_call && !VEC_empty (rtx, nonlocal_goto_handler_labels)))
{
edge eh_edge;
edge_iterator ei;
@@ -255,7 +255,7 @@ is_cfg_nonregular (void)
/* If we have a label that could be the target of a nonlocal goto, then
the cfg is not well structured. */
- if (nonlocal_goto_handler_labels)
+ if (!VEC_empty (rtx, nonlocal_goto_handler_labels))
return 1;
/* If we have any forced labels, then the cfg is not well structured. */
@@ -212,9 +212,7 @@ expand_label (tree label)
if (DECL_NONLOCAL (label))
{
expand_nl_goto_receiver ();
- nonlocal_goto_handler_labels
- = gen_rtx_EXPR_LIST (VOIDmode, label_r,
- nonlocal_goto_handler_labels);
+ note_nonlocal_goto_handler_label (label_r);
}
if (FORCED_LABEL (label))