function.c (nonlocal_goto_handler_slots): Renamed from nonlocal_goto_handler_slot; now an EXPR_LIST chain.

* 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.

From-SVN: r23732
This commit is contained in:
Bernd Schmidt 1998-11-20 07:37:42 +00:00 committed by Jeff Law
parent 294377f8a5
commit ba716ac925
9 changed files with 265 additions and 164 deletions

View File

@ -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.

View File

@ -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 ();

View File

@ -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. */

View File

@ -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.

View File

@ -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;

View File

@ -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.

View File

@ -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. */

View File

@ -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;

View File

@ -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.) */