summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1998-11-20 07:37:42 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1998-11-20 07:37:42 +0000
commit0deb06c7a40b6356e8cb63f9ad1179377312452d (patch)
treea92aab8090880174e955a4c9c4a9f38938ea2d05 /gcc
parente82e3e5268a59ad3589d45bbe5a4f552d3a65f17 (diff)
downloadgcc-0deb06c7a40b6356e8cb63f9ad1179377312452d.tar.gz
* function.c (nonlocal_goto_handler_slots): Renamed from
nonlocal_goto_handler_slot; now an EXPR_LIST chain. (push_function_context_to): Adjust for this change. (pop_function_context_from): Likewise. (init_function_start): Likewise. (expand_function_end): Likewise. * function.h (struct function): Likewise. * calls.c (expand_call): Likewise. * explow.c (allocate_dynamic_stack_space): Likewise. * expr.h (nonlocal_goto_handler_slots): Rename its declaration. * stmt.c (declare_nonlocal_label): Make a new handler slot for each label. (expand_goto): When doing a nonlocal goto, find corresponding handler slot for it. Don't put the label address in the static chain register. (expand_end_bindings): Break out nonlocal goto handling code into three new functions. (expand_nl_handler_label, expand_nl_goto_receiver, expand_nl_goto_receivers): New static functions, broken out of expand_end_bindings and adapted to create one handler per nonlocal label. * function.c (delete_handlers): Delete insn if it references any of the nonlocal goto handler slots. * i960.md (nonlocal_goto): Comment out code that modifies static_chain_rtx. * sparc.md (nonlocal_goto): Likewise. (goto_handler_and_restore_v9): Comment out. (goto_handler_and_restore_v9_sp64): Comment out. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@23732 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog32
-rw-r--r--gcc/calls.c2
-rw-r--r--gcc/config/i960/i960.md2
-rw-r--r--gcc/config/sparc/sparc.md46
-rw-r--r--gcc/explow.c2
-rw-r--r--gcc/expr.h6
-rw-r--r--gcc/function.c34
-rw-r--r--gcc/function.h2
-rw-r--r--gcc/stmt.c303
9 files changed, 265 insertions, 164 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fff326d2c7c..efd0cd9f4b7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,34 @@
-Thu Nov 19 23:44:38 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+Fri Nov 20 08:34:00 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * function.c (nonlocal_goto_handler_slots): Renamed from
+ nonlocal_goto_handler_slot; now an EXPR_LIST chain.
+ (push_function_context_to): Adjust for this change.
+ (pop_function_context_from): Likewise.
+ (init_function_start): Likewise.
+ (expand_function_end): Likewise.
+ * function.h (struct function): Likewise.
+ * calls.c (expand_call): Likewise.
+ * explow.c (allocate_dynamic_stack_space): Likewise.
+ * expr.h (nonlocal_goto_handler_slots): Rename its declaration.
+ * stmt.c (declare_nonlocal_label): Make a new handler slot for each
+ label.
+ (expand_goto): When doing a nonlocal goto, find corresponding handler
+ slot for it. Don't put the label address in the static chain register.
+ (expand_end_bindings): Break out nonlocal goto handling code into
+ three new functions.
+ (expand_nl_handler_label, expand_nl_goto_receiver,
+ expand_nl_goto_receivers): New static functions, broken out of
+ expand_end_bindings and adapted to create one handler per nonlocal
+ label.
+ * function.c (delete_handlers): Delete insn if it references any of
+ the nonlocal goto handler slots.
+ * i960.md (nonlocal_goto): Comment out code that modifies
+ static_chain_rtx.
+ * sparc.md (nonlocal_goto): Likewise.
+ (goto_handler_and_restore_v9): Comment out.
+ (goto_handler_and_restore_v9_sp64): Comment out.
+
+Thu Nov 19 23:44:38 1998
* expr.c (STACK_BYTES): Delete unused macro.
* calls.c: Provide default for PREFERRED_STACK_BOUNDARY.
diff --git a/gcc/calls.c b/gcc/calls.c
index 6f67b7c009f..79cae9f6998 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -2204,7 +2204,7 @@ expand_call (exp, target, ignore)
Check for the handler slots since we might not have a save area
for non-local gotos. */
- if (may_be_alloca && nonlocal_goto_handler_slot != 0)
+ if (may_be_alloca && nonlocal_goto_handler_slots != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
pop_temp_slots ();
diff --git a/gcc/config/i960/i960.md b/gcc/config/i960/i960.md
index c99c6c1fdc9..ef8848473d3 100644
--- a/gcc/config/i960/i960.md
+++ b/gcc/config/i960/i960.md
@@ -2343,6 +2343,7 @@
plus_constant (fp, 8)),
new_pc);
+#if 0
/* Next, we put the value into the static chain register's save
area on the stack. After the ret below, this will be loaded into
r3 (the static chain). */
@@ -2350,6 +2351,7 @@
emit_move_insn (gen_rtx (MEM, SImode,
plus_constant (fp, 12)),
val);
+#endif
/* We now load pfp (the previous frame pointer) with the value that
we want fp to be. */
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 69b68fdf86c..59fcd59afb5 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -7686,6 +7686,8 @@
really needed. */
/*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/
emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+
+#if 0
/* Return, restoring reg window and jumping to goto handler. */
if (TARGET_V9 && GET_CODE (chain) == CONST_INT
&& ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff))
@@ -7697,6 +7699,8 @@
}
/* Put in the static chain register the nonlocal label address. */
emit_move_insn (static_chain_rtx, chain);
+#endif
+
emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
emit_insn (gen_goto_handler_and_restore (labreg));
emit_barrier ();
@@ -7718,27 +7722,27 @@
[(set_attr "type" "misc")
(set_attr "length" "2")])
-(define_insn "goto_handler_and_restore_v9"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
- (match_operand:SI 1 "register_operand" "=r,r")
- (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
- "TARGET_V9 && ! TARGET_ARCH64"
- "@
- return\\t%0+0\\n\\tmov\\t%2, %Y1
- sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
- [(set_attr "type" "misc")
- (set_attr "length" "2,3")])
-
-(define_insn "*goto_handler_and_restore_v9_sp64"
- [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
- (match_operand:DI 1 "register_operand" "=r,r")
- (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
- "TARGET_V9 && TARGET_ARCH64"
- "@
- return\\t%0+0\\n\\tmov\\t%2, %Y1
- sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
- [(set_attr "type" "misc")
- (set_attr "length" "2,3")])
+;;(define_insn "goto_handler_and_restore_v9"
+;; [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
+;; (match_operand:SI 1 "register_operand" "=r,r")
+;; (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
+;; "TARGET_V9 && ! TARGET_ARCH64"
+;; "@
+;; return\\t%0+0\\n\\tmov\\t%2, %Y1
+;; sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
+;; [(set_attr "type" "misc")
+;; (set_attr "length" "2,3")])
+;;
+;;(define_insn "*goto_handler_and_restore_v9_sp64"
+;; [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
+;; (match_operand:DI 1 "register_operand" "=r,r")
+;; (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
+;; "TARGET_V9 && TARGET_ARCH64"
+;; "@
+;; return\\t%0+0\\n\\tmov\\t%2, %Y1
+;; sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
+;; [(set_attr "type" "misc")
+;; (set_attr "length" "2,3")])
;; Pattern for use after a setjmp to store FP and the return register
;; into the stack area.
diff --git a/gcc/explow.c b/gcc/explow.c
index 0dbf002b4d2..e4ef27dc37f 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -1303,7 +1303,7 @@ allocate_dynamic_stack_space (size, target, known_align)
#endif
/* Record the new stack level for nonlocal gotos. */
- if (nonlocal_goto_handler_slot != 0)
+ if (nonlocal_goto_handler_slots != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
return target;
diff --git a/gcc/expr.h b/gcc/expr.h
index b1665aa7de9..896bded1456 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -105,10 +105,12 @@ extern int inhibit_defer_pop;
extern int function_call_count;
-/* RTX for stack slot that holds the current handler for nonlocal gotos.
+/* List (chain of EXPR_LIST) of stack slots that hold the current handlers
+ for nonlocal gotos. There is one for every nonlocal label in the function;
+ this list matches the one in nonlocal_labels.
Zero when function does not have nonlocal labels. */
-extern rtx nonlocal_goto_handler_slot;
+extern rtx nonlocal_goto_handler_slots;
/* RTX for stack slot that holds the stack pointer value to restore
for a nonlocal goto.
diff --git a/gcc/function.c b/gcc/function.c
index fa8b14ae1c2..d9575cc0ca3 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -247,10 +247,12 @@ int function_call_count;
tree nonlocal_labels;
-/* RTX for stack slot that holds the current handler for nonlocal gotos.
+/* List (chain of EXPR_LIST) of stack slots that hold the current handlers
+ for nonlocal gotos. There is one for every nonlocal label in the function;
+ this list matches the one in nonlocal_labels.
Zero when function does not have nonlocal labels. */
-rtx nonlocal_goto_handler_slot;
+rtx nonlocal_goto_handler_slots;
/* RTX for stack slot that holds the stack pointer value to restore
for a nonlocal goto.
@@ -532,7 +534,7 @@ push_function_context_to (context)
p->parm_reg_stack_loc = parm_reg_stack_loc;
p->outgoing_args_size = current_function_outgoing_args_size;
p->return_rtx = current_function_return_rtx;
- p->nonlocal_goto_handler_slot = nonlocal_goto_handler_slot;
+ p->nonlocal_goto_handler_slots = nonlocal_goto_handler_slots;
p->nonlocal_goto_stack_level = nonlocal_goto_stack_level;
p->nonlocal_labels = nonlocal_labels;
p->cleanup_label = cleanup_label;
@@ -616,7 +618,7 @@ pop_function_context_from (context)
parm_reg_stack_loc = p->parm_reg_stack_loc;
current_function_outgoing_args_size = p->outgoing_args_size;
current_function_return_rtx = p->return_rtx;
- nonlocal_goto_handler_slot = p->nonlocal_goto_handler_slot;
+ nonlocal_goto_handler_slots = p->nonlocal_goto_handler_slots;
nonlocal_goto_stack_level = p->nonlocal_goto_stack_level;
nonlocal_labels = p->nonlocal_labels;
cleanup_label = p->cleanup_label;
@@ -3664,13 +3666,22 @@ delete_handlers ()
TREE_CHAIN (last_t) = TREE_CHAIN (t);
}
}
- if (GET_CODE (insn) == INSN
- && ((nonlocal_goto_handler_slot != 0
- && reg_mentioned_p (nonlocal_goto_handler_slot, PATTERN (insn)))
+ if (GET_CODE (insn) == INSN)
+ {
+ int can_delete = 0;
+ rtx t;
+ for (t = nonlocal_goto_handler_slots; t != 0; t = XEXP (t, 1))
+ if (reg_mentioned_p (t, PATTERN (insn)))
+ {
+ can_delete = 1;
+ break;
+ }
+ if (can_delete
|| (nonlocal_goto_stack_level != 0
&& reg_mentioned_p (nonlocal_goto_stack_level,
- PATTERN (insn)))))
- delete_insn (insn);
+ PATTERN (insn))))
+ delete_insn (insn);
+ }
}
}
@@ -5452,7 +5463,7 @@ init_function_start (subr, filename, line)
stack_slot_list = 0;
/* There is no stack slot for handling nonlocal gotos. */
- nonlocal_goto_handler_slot = 0;
+ nonlocal_goto_handler_slots = 0;
nonlocal_goto_stack_level = 0;
/* No labels have been declared for nonlocal use. */
@@ -5972,7 +5983,8 @@ expand_function_end (filename, line, end_bindings)
}
/* Delete handlers for nonlocal gotos if nothing uses them. */
- if (nonlocal_goto_handler_slot != 0 && !current_function_has_nonlocal_label)
+ if (nonlocal_goto_handler_slots != 0
+ && ! current_function_has_nonlocal_label)
delete_handlers ();
/* End any sequences that failed to be closed due to syntax errors. */
diff --git a/gcc/function.h b/gcc/function.h
index d5e6cd06abc..e78b2e1be9b 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -81,7 +81,7 @@ struct function
int has_nonlocal_goto;
int contains_functions;
int is_thunk;
- rtx nonlocal_goto_handler_slot;
+ rtx nonlocal_goto_handler_slots;
rtx nonlocal_goto_stack_level;
tree nonlocal_labels;
int args_size;
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 33702dbecf3..affd4b588a4 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -428,6 +428,9 @@ static int using_eh_for_cleanups_p = 0;
static int n_occurrences PROTO((int, char *));
static void expand_goto_internal PROTO((tree, rtx, rtx));
static int expand_fixup PROTO((tree, rtx, rtx));
+static void expand_nl_handler_label PROTO((rtx, rtx));
+static void expand_nl_goto_receiver PROTO((void));
+static void expand_nl_goto_receivers PROTO((struct nesting *));
static void fixup_gotos PROTO((struct nesting *, rtx, tree,
rtx, int));
static void expand_null_return_1 PROTO((rtx, int));
@@ -632,16 +635,18 @@ void
declare_nonlocal_label (label)
tree label;
{
+ rtx slot = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
+
nonlocal_labels = tree_cons (NULL_TREE, label, nonlocal_labels);
LABEL_PRESERVE_P (label_rtx (label)) = 1;
- if (nonlocal_goto_handler_slot == 0)
+ if (nonlocal_goto_handler_slots == 0)
{
- nonlocal_goto_handler_slot
- = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
emit_stack_save (SAVE_NONLOCAL,
&nonlocal_goto_stack_level,
PREV_INSN (tail_recursion_reentry));
}
+ nonlocal_goto_handler_slots
+ = gen_rtx_EXPR_LIST (VOIDmode, slot, nonlocal_goto_handler_slots);
}
/* Generate RTL code for a `goto' statement with target label LABEL.
@@ -660,7 +665,15 @@ expand_goto (label)
{
struct function *p = find_function_data (context);
rtx label_ref = gen_rtx_LABEL_REF (Pmode, label_rtx (label));
- rtx temp;
+ rtx temp, handler_slot;
+ tree link;
+
+ /* Find the corresponding handler slot for this label. */
+ handler_slot = p->nonlocal_goto_handler_slots;
+ for (link = p->nonlocal_labels; TREE_VALUE (link) != label;
+ link = TREE_CHAIN (link))
+ handler_slot = XEXP (handler_slot, 1);
+ handler_slot = XEXP (handler_slot, 0);
p->has_nonlocal_label = 1;
current_function_has_nonlocal_goto = 1;
@@ -673,7 +686,7 @@ expand_goto (label)
#if HAVE_nonlocal_goto
if (HAVE_nonlocal_goto)
emit_insn (gen_nonlocal_goto (lookup_static_chain (label),
- copy_rtx (p->nonlocal_goto_handler_slot),
+ copy_rtx (handler_slot),
copy_rtx (p->nonlocal_goto_stack_level),
label_ref));
else
@@ -695,7 +708,7 @@ expand_goto (label)
/* Get addr of containing function's current nonlocal goto handler,
which will do any cleanups and then jump to the label. */
- addr = copy_rtx (p->nonlocal_goto_handler_slot);
+ addr = copy_rtx (handler_slot);
temp = copy_to_reg (replace_rtx (addr, virtual_stack_vars_rtx,
hard_frame_pointer_rtx));
@@ -708,13 +721,10 @@ expand_goto (label)
emit_stack_restore (SAVE_NONLOCAL, addr, NULL_RTX);
- /* Put in the static chain register the nonlocal label address. */
- emit_move_insn (static_chain_rtx, label_ref);
/* USE of hard_frame_pointer_rtx added for consistency; not clear if
really needed. */
emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
- emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
emit_indirect_jump (temp);
}
}
@@ -2992,6 +3002,161 @@ remember_end_note (block)
last_block_end_note = NULL_RTX;
}
+/* Emit a handler label for a nonlocal goto handler.
+ Also emit code to store the handler label in SLOT before BEFORE_INSN. */
+
+static void
+expand_nl_handler_label (slot, before_insn)
+ rtx slot, before_insn;
+{
+ rtx insns;
+ rtx handler_label = gen_label_rtx ();
+
+ /* Don't let jump_optimize delete the handler. */
+ LABEL_PRESERVE_P (handler_label) = 1;
+
+ start_sequence ();
+ emit_move_insn (slot, gen_rtx_LABEL_REF (Pmode, handler_label));
+ insns = get_insns ();
+ end_sequence ();
+ emit_insns_before (insns, before_insn);
+
+ emit_label (handler_label);
+}
+
+/* Emit code to restore vital registers at the beginning of a nonlocal goto
+ handler. */
+static void
+expand_nl_goto_receiver ()
+{
+#ifdef HAVE_nonlocal_goto
+ if (! HAVE_nonlocal_goto)
+#endif
+ /* First adjust our frame pointer to its actual value. It was
+ previously set to the start of the virtual area corresponding to
+ the stacked variables when we branched here and now needs to be
+ adjusted to the actual hardware fp value.
+
+ Assignments are to virtual registers are converted by
+ instantiate_virtual_regs into the corresponding assignment
+ to the underlying register (fp in this case) that makes
+ the original assignment true.
+ So the following insn will actually be
+ decrementing fp by STARTING_FRAME_OFFSET. */
+ emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
+
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ if (fixed_regs[ARG_POINTER_REGNUM])
+ {
+#ifdef ELIMINABLE_REGS
+ /* If the argument pointer can be eliminated in favor of the
+ frame pointer, we don't need to restore it. We assume here
+ that if such an elimination is present, it can always be used.
+ This is the case on all known machines; if we don't make this
+ assumption, we do unnecessary saving on many machines. */
+ static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
+ size_t i;
+
+ for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
+ if (elim_regs[i].from == ARG_POINTER_REGNUM
+ && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
+ break;
+
+ if (i == sizeof elim_regs / sizeof elim_regs [0])
+#endif
+ {
+ /* Now restore our arg pointer from the address at which it
+ was saved in our stack frame.
+ If there hasn't be space allocated for it yet, make
+ some now. */
+ if (arg_pointer_save_area == 0)
+ arg_pointer_save_area
+ = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
+ emit_move_insn (virtual_incoming_args_rtx,
+ /* We need a pseudo here, or else
+ instantiate_virtual_regs_1 complains. */
+ copy_to_reg (arg_pointer_save_area));
+ }
+ }
+#endif
+
+#ifdef HAVE_nonlocal_goto_receiver
+ if (HAVE_nonlocal_goto_receiver)
+ emit_insn (gen_nonlocal_goto_receiver ());
+#endif
+}
+
+/* Make handlers for nonlocal gotos taking place in the function calls in
+ block THISBLOCK. */
+
+static void
+expand_nl_goto_receivers (thisblock)
+ struct nesting *thisblock;
+{
+ tree link;
+ rtx afterward = gen_label_rtx ();
+ rtx insns, slot;
+ int any_invalid;
+
+ /* Record the handler address in the stack slot for that purpose,
+ during this block, saving and restoring the outer value. */
+ if (thisblock->next != 0)
+ for (slot = nonlocal_goto_handler_slots; slot; slot = XEXP (slot, 1))
+ {
+ rtx save_receiver = gen_reg_rtx (Pmode);
+ emit_move_insn (XEXP (slot, 0), save_receiver);
+
+ start_sequence ();
+ emit_move_insn (save_receiver, XEXP (slot, 0));
+ insns = get_insns ();
+ end_sequence ();
+ emit_insns_before (insns, thisblock->data.block.first_insn);
+ }
+
+ /* Jump around the handlers; they run only when specially invoked. */
+ emit_jump (afterward);
+
+ /* Make a separate handler for each label. */
+ link = nonlocal_labels;
+ slot = nonlocal_goto_handler_slots;
+ for (; link; link = TREE_CHAIN (link), slot = XEXP (slot, 1))
+ /* Skip any labels we shouldn't be able to jump to from here,
+ we generate one special handler for all of them below which just calls
+ abort. */
+ if (! DECL_TOO_LATE (TREE_VALUE (link)))
+ {
+ expand_nl_handler_label (XEXP (slot, 0),
+ thisblock->data.block.first_insn);
+ expand_nl_goto_receiver ();
+
+ /* Jump to the "real" nonlocal label. */
+ expand_goto (TREE_VALUE (link));
+ }
+
+ /* A second pass over all nonlocal labels; this time we handle those
+ we should not be able to jump to at this point. */
+ link = nonlocal_labels;
+ slot = nonlocal_goto_handler_slots;
+ any_invalid = 0;
+ for (; link; link = TREE_CHAIN (link), slot = XEXP (slot, 1))
+ if (DECL_TOO_LATE (TREE_VALUE (link)))
+ {
+ expand_nl_handler_label (XEXP (slot, 0),
+ thisblock->data.block.first_insn);
+ any_invalid = 1;
+ }
+
+ if (any_invalid)
+ {
+ expand_nl_goto_receiver ();
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "abort"), 0,
+ VOIDmode, 0);
+ emit_barrier ();
+ }
+
+ emit_label (afterward);
+}
+
/* Generate RTL code to terminate a binding contour.
VARS is the chain of VAR_DECL nodes
for the variables bound in this contour.
@@ -3042,7 +3207,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
emit_label (thisblock->exit_label);
}
- /* If necessary, make a handler for nonlocal gotos taking
+ /* If necessary, make handlers for nonlocal gotos taking
place in the function calls in this block. */
if (function_call_count != thisblock->data.block.function_call_count
&& nonlocal_labels
@@ -3053,119 +3218,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
special to do when you jump out of it. */
: (thisblock->data.block.cleanups != 0
|| thisblock->data.block.stack_level != 0)))
- {
- tree link;
- rtx afterward = gen_label_rtx ();
- rtx handler_label = gen_label_rtx ();
- rtx save_receiver = gen_reg_rtx (Pmode);
- rtx insns;
-
- /* Don't let jump_optimize delete the handler. */
- LABEL_PRESERVE_P (handler_label) = 1;
-
- /* Record the handler address in the stack slot for that purpose,
- during this block, saving and restoring the outer value. */
- if (thisblock->next != 0)
- {
- emit_move_insn (nonlocal_goto_handler_slot, save_receiver);
-
- start_sequence ();
- emit_move_insn (save_receiver, nonlocal_goto_handler_slot);
- insns = get_insns ();
- end_sequence ();
- emit_insns_before (insns, thisblock->data.block.first_insn);
- }
-
- start_sequence ();
- emit_move_insn (nonlocal_goto_handler_slot,
- gen_rtx_LABEL_REF (Pmode, handler_label));
- insns = get_insns ();
- end_sequence ();
- emit_insns_before (insns, thisblock->data.block.first_insn);
-
- /* Jump around the handler; it runs only when specially invoked. */
- emit_jump (afterward);
- emit_label (handler_label);
-
-#ifdef HAVE_nonlocal_goto
- if (! HAVE_nonlocal_goto)
-#endif
- /* First adjust our frame pointer to its actual value. It was
- previously set to the start of the virtual area corresponding to
- the stacked variables when we branched here and now needs to be
- adjusted to the actual hardware fp value.
-
- Assignments are to virtual registers are converted by
- instantiate_virtual_regs into the corresponding assignment
- to the underlying register (fp in this case) that makes
- the original assignment true.
- So the following insn will actually be
- decrementing fp by STARTING_FRAME_OFFSET. */
- emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
-
-#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- if (fixed_regs[ARG_POINTER_REGNUM])
- {
-#ifdef ELIMINABLE_REGS
- /* If the argument pointer can be eliminated in favor of the
- frame pointer, we don't need to restore it. We assume here
- that if such an elimination is present, it can always be used.
- This is the case on all known machines; if we don't make this
- assumption, we do unnecessary saving on many machines. */
- static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
- size_t i;
-
- for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
- if (elim_regs[i].from == ARG_POINTER_REGNUM
- && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
- break;
-
- if (i == sizeof elim_regs / sizeof elim_regs [0])
-#endif
- {
- /* Now restore our arg pointer from the address at which it
- was saved in our stack frame.
- If there hasn't be space allocated for it yet, make
- some now. */
- if (arg_pointer_save_area == 0)
- arg_pointer_save_area
- = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
- emit_move_insn (virtual_incoming_args_rtx,
- /* We need a pseudo here, or else
- instantiate_virtual_regs_1 complains. */
- copy_to_reg (arg_pointer_save_area));
- }
- }
-#endif
-
-#ifdef HAVE_nonlocal_goto_receiver
- if (HAVE_nonlocal_goto_receiver)
- emit_insn (gen_nonlocal_goto_receiver ());
-#endif
-
- /* The handler expects the desired label address in the static chain
- register. It tests the address and does an appropriate jump
- to whatever label is desired. */
- for (link = nonlocal_labels; link; link = TREE_CHAIN (link))
- /* Skip any labels we shouldn't be able to jump to from here. */
- if (! DECL_TOO_LATE (TREE_VALUE (link)))
- {
- rtx not_this = gen_label_rtx ();
- rtx this = gen_label_rtx ();
- do_jump_if_equal (static_chain_rtx,
- gen_rtx_LABEL_REF (Pmode, DECL_RTL (TREE_VALUE (link))),
- this, 0);
- emit_jump (not_this);
- emit_label (this);
- expand_goto (TREE_VALUE (link));
- emit_label (not_this);
- }
- /* If label is not recognized, abort. */
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "abort"), 0,
- VOIDmode, 0);
- emit_barrier ();
- emit_label (afterward);
- }
+ expand_nl_goto_receivers (thisblock);
/* Don't allow jumping into a block that has a stack level.
Cleanups are allowed, though. */
@@ -3219,7 +3272,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
{
emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
thisblock->data.block.stack_level, NULL_RTX);
- if (nonlocal_goto_handler_slot != 0)
+ if (nonlocal_goto_handler_slots != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level,
NULL_RTX);
}
@@ -3266,8 +3319,6 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
/* Pop the stack slot nesting and free any slots at this level. */
pop_temp_slots ();
}
-
-
/* Generate RTL for the automatic variable declaration DECL.
(Other kinds of declarations are simply ignored if seen here.) */