Commit ba716ac9 by Bernd Schmidt Committed by Jeff Law

function.c (nonlocal_goto_handler_slots): Renamed from…

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
parent 294377f8
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. * expr.c (STACK_BYTES): Delete unused macro.
* calls.c: Provide default for PREFERRED_STACK_BOUNDARY. * calls.c: Provide default for PREFERRED_STACK_BOUNDARY.
......
...@@ -2204,7 +2204,7 @@ expand_call (exp, target, ignore) ...@@ -2204,7 +2204,7 @@ expand_call (exp, target, ignore)
Check for the handler slots since we might not have a save area Check for the handler slots since we might not have a save area
for non-local gotos. */ 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); emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
pop_temp_slots (); pop_temp_slots ();
......
...@@ -2343,6 +2343,7 @@ ...@@ -2343,6 +2343,7 @@
plus_constant (fp, 8)), plus_constant (fp, 8)),
new_pc); new_pc);
#if 0
/* Next, we put the value into the static chain register's save /* 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 area on the stack. After the ret below, this will be loaded into
r3 (the static chain). */ r3 (the static chain). */
...@@ -2350,6 +2351,7 @@ ...@@ -2350,6 +2351,7 @@
emit_move_insn (gen_rtx (MEM, SImode, emit_move_insn (gen_rtx (MEM, SImode,
plus_constant (fp, 12)), plus_constant (fp, 12)),
val); val);
#endif
/* We now load pfp (the previous frame pointer) with the value that /* We now load pfp (the previous frame pointer) with the value that
we want fp to be. */ we want fp to be. */
......
...@@ -7686,6 +7686,8 @@ ...@@ -7686,6 +7686,8 @@
really needed. */ really needed. */
/*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/ /*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/
emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
#if 0
/* Return, restoring reg window and jumping to goto handler. */ /* Return, restoring reg window and jumping to goto handler. */
if (TARGET_V9 && GET_CODE (chain) == CONST_INT if (TARGET_V9 && GET_CODE (chain) == CONST_INT
&& ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff)) && ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff))
...@@ -7697,6 +7699,8 @@ ...@@ -7697,6 +7699,8 @@
} }
/* Put in the static chain register the nonlocal label address. */ /* Put in the static chain register the nonlocal label address. */
emit_move_insn (static_chain_rtx, chain); emit_move_insn (static_chain_rtx, chain);
#endif
emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx)); emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
emit_insn (gen_goto_handler_and_restore (labreg)); emit_insn (gen_goto_handler_and_restore (labreg));
emit_barrier (); emit_barrier ();
...@@ -7718,27 +7722,27 @@ ...@@ -7718,27 +7722,27 @@
[(set_attr "type" "misc") [(set_attr "type" "misc")
(set_attr "length" "2")]) (set_attr "length" "2")])
(define_insn "goto_handler_and_restore_v9" ;;(define_insn "goto_handler_and_restore_v9"
[(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r") ;; [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
(match_operand:SI 1 "register_operand" "=r,r") ;; (match_operand:SI 1 "register_operand" "=r,r")
(match_operand:SI 2 "const_int_operand" "I,n")] 3)] ;; (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
"TARGET_V9 && ! TARGET_ARCH64" ;; "TARGET_V9 && ! TARGET_ARCH64"
"@ ;; "@
return\\t%0+0\\n\\tmov\\t%2, %Y1 ;; 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" ;; sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
[(set_attr "type" "misc") ;; [(set_attr "type" "misc")
(set_attr "length" "2,3")]) ;; (set_attr "length" "2,3")])
;;
(define_insn "*goto_handler_and_restore_v9_sp64" ;;(define_insn "*goto_handler_and_restore_v9_sp64"
[(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r") ;; [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
(match_operand:DI 1 "register_operand" "=r,r") ;; (match_operand:DI 1 "register_operand" "=r,r")
(match_operand:SI 2 "const_int_operand" "I,n")] 3)] ;; (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
"TARGET_V9 && TARGET_ARCH64" ;; "TARGET_V9 && TARGET_ARCH64"
"@ ;; "@
return\\t%0+0\\n\\tmov\\t%2, %Y1 ;; 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" ;; sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
[(set_attr "type" "misc") ;; [(set_attr "type" "misc")
(set_attr "length" "2,3")]) ;; (set_attr "length" "2,3")])
;; Pattern for use after a setjmp to store FP and the return register ;; Pattern for use after a setjmp to store FP and the return register
;; into the stack area. ;; into the stack area.
......
...@@ -1303,7 +1303,7 @@ allocate_dynamic_stack_space (size, target, known_align) ...@@ -1303,7 +1303,7 @@ allocate_dynamic_stack_space (size, target, known_align)
#endif #endif
/* Record the new stack level for nonlocal gotos. */ /* 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); emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
return target; return target;
......
...@@ -105,10 +105,12 @@ extern int inhibit_defer_pop; ...@@ -105,10 +105,12 @@ extern int inhibit_defer_pop;
extern int function_call_count; 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. */ 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 /* RTX for stack slot that holds the stack pointer value to restore
for a nonlocal goto. for a nonlocal goto.
......
...@@ -247,10 +247,12 @@ int function_call_count; ...@@ -247,10 +247,12 @@ int function_call_count;
tree nonlocal_labels; 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. */ 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 /* RTX for stack slot that holds the stack pointer value to restore
for a nonlocal goto. for a nonlocal goto.
...@@ -532,7 +534,7 @@ push_function_context_to (context) ...@@ -532,7 +534,7 @@ push_function_context_to (context)
p->parm_reg_stack_loc = parm_reg_stack_loc; p->parm_reg_stack_loc = parm_reg_stack_loc;
p->outgoing_args_size = current_function_outgoing_args_size; p->outgoing_args_size = current_function_outgoing_args_size;
p->return_rtx = current_function_return_rtx; 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_goto_stack_level = nonlocal_goto_stack_level;
p->nonlocal_labels = nonlocal_labels; p->nonlocal_labels = nonlocal_labels;
p->cleanup_label = cleanup_label; p->cleanup_label = cleanup_label;
...@@ -616,7 +618,7 @@ pop_function_context_from (context) ...@@ -616,7 +618,7 @@ pop_function_context_from (context)
parm_reg_stack_loc = p->parm_reg_stack_loc; parm_reg_stack_loc = p->parm_reg_stack_loc;
current_function_outgoing_args_size = p->outgoing_args_size; current_function_outgoing_args_size = p->outgoing_args_size;
current_function_return_rtx = p->return_rtx; 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_goto_stack_level = p->nonlocal_goto_stack_level;
nonlocal_labels = p->nonlocal_labels; nonlocal_labels = p->nonlocal_labels;
cleanup_label = p->cleanup_label; cleanup_label = p->cleanup_label;
...@@ -3664,13 +3666,22 @@ delete_handlers () ...@@ -3664,13 +3666,22 @@ delete_handlers ()
TREE_CHAIN (last_t) = TREE_CHAIN (t); TREE_CHAIN (last_t) = TREE_CHAIN (t);
} }
} }
if (GET_CODE (insn) == INSN if (GET_CODE (insn) == INSN)
&& ((nonlocal_goto_handler_slot != 0 {
&& reg_mentioned_p (nonlocal_goto_handler_slot, PATTERN (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 || (nonlocal_goto_stack_level != 0
&& reg_mentioned_p (nonlocal_goto_stack_level, && reg_mentioned_p (nonlocal_goto_stack_level,
PATTERN (insn))))) PATTERN (insn))))
delete_insn (insn); delete_insn (insn);
}
} }
} }
...@@ -5452,7 +5463,7 @@ init_function_start (subr, filename, line) ...@@ -5452,7 +5463,7 @@ init_function_start (subr, filename, line)
stack_slot_list = 0; stack_slot_list = 0;
/* There is no stack slot for handling nonlocal gotos. */ /* There is no stack slot for handling nonlocal gotos. */
nonlocal_goto_handler_slot = 0; nonlocal_goto_handler_slots = 0;
nonlocal_goto_stack_level = 0; nonlocal_goto_stack_level = 0;
/* No labels have been declared for nonlocal use. */ /* No labels have been declared for nonlocal use. */
...@@ -5972,7 +5983,8 @@ expand_function_end (filename, line, end_bindings) ...@@ -5972,7 +5983,8 @@ expand_function_end (filename, line, end_bindings)
} }
/* Delete handlers for nonlocal gotos if nothing uses them. */ /* 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 (); delete_handlers ();
/* End any sequences that failed to be closed due to syntax errors. */ /* End any sequences that failed to be closed due to syntax errors. */
......
...@@ -81,7 +81,7 @@ struct function ...@@ -81,7 +81,7 @@ struct function
int has_nonlocal_goto; int has_nonlocal_goto;
int contains_functions; int contains_functions;
int is_thunk; int is_thunk;
rtx nonlocal_goto_handler_slot; rtx nonlocal_goto_handler_slots;
rtx nonlocal_goto_stack_level; rtx nonlocal_goto_stack_level;
tree nonlocal_labels; tree nonlocal_labels;
int args_size; int args_size;
......
...@@ -428,6 +428,9 @@ static int using_eh_for_cleanups_p = 0; ...@@ -428,6 +428,9 @@ static int using_eh_for_cleanups_p = 0;
static int n_occurrences PROTO((int, char *)); static int n_occurrences PROTO((int, char *));
static void expand_goto_internal PROTO((tree, rtx, rtx)); static void expand_goto_internal PROTO((tree, rtx, rtx));
static int expand_fixup 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, static void fixup_gotos PROTO((struct nesting *, rtx, tree,
rtx, int)); rtx, int));
static void expand_null_return_1 PROTO((rtx, int)); static void expand_null_return_1 PROTO((rtx, int));
...@@ -632,16 +635,18 @@ void ...@@ -632,16 +635,18 @@ void
declare_nonlocal_label (label) declare_nonlocal_label (label)
tree label; tree label;
{ {
rtx slot = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
nonlocal_labels = tree_cons (NULL_TREE, label, nonlocal_labels); nonlocal_labels = tree_cons (NULL_TREE, label, nonlocal_labels);
LABEL_PRESERVE_P (label_rtx (label)) = 1; 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, emit_stack_save (SAVE_NONLOCAL,
&nonlocal_goto_stack_level, &nonlocal_goto_stack_level,
PREV_INSN (tail_recursion_reentry)); 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. /* Generate RTL code for a `goto' statement with target label LABEL.
...@@ -660,7 +665,15 @@ expand_goto (label) ...@@ -660,7 +665,15 @@ expand_goto (label)
{ {
struct function *p = find_function_data (context); struct function *p = find_function_data (context);
rtx label_ref = gen_rtx_LABEL_REF (Pmode, label_rtx (label)); 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; p->has_nonlocal_label = 1;
current_function_has_nonlocal_goto = 1; current_function_has_nonlocal_goto = 1;
...@@ -673,7 +686,7 @@ expand_goto (label) ...@@ -673,7 +686,7 @@ expand_goto (label)
#if HAVE_nonlocal_goto #if HAVE_nonlocal_goto
if (HAVE_nonlocal_goto) if (HAVE_nonlocal_goto)
emit_insn (gen_nonlocal_goto (lookup_static_chain (label), 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), copy_rtx (p->nonlocal_goto_stack_level),
label_ref)); label_ref));
else else
...@@ -695,7 +708,7 @@ expand_goto (label) ...@@ -695,7 +708,7 @@ expand_goto (label)
/* Get addr of containing function's current nonlocal goto handler, /* Get addr of containing function's current nonlocal goto handler,
which will do any cleanups and then jump to the label. */ 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, temp = copy_to_reg (replace_rtx (addr, virtual_stack_vars_rtx,
hard_frame_pointer_rtx)); hard_frame_pointer_rtx));
...@@ -708,13 +721,10 @@ expand_goto (label) ...@@ -708,13 +721,10 @@ expand_goto (label)
emit_stack_restore (SAVE_NONLOCAL, addr, NULL_RTX); 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 /* USE of hard_frame_pointer_rtx added for consistency; not clear if
really needed. */ really needed. */
emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); 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, stack_pointer_rtx));
emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
emit_indirect_jump (temp); emit_indirect_jump (temp);
} }
} }
...@@ -2992,6 +3002,161 @@ remember_end_note (block) ...@@ -2992,6 +3002,161 @@ remember_end_note (block)
last_block_end_note = NULL_RTX; 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. /* Generate RTL code to terminate a binding contour.
VARS is the chain of VAR_DECL nodes VARS is the chain of VAR_DECL nodes
for the variables bound in this contour. for the variables bound in this contour.
...@@ -3042,7 +3207,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in) ...@@ -3042,7 +3207,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
emit_label (thisblock->exit_label); 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. */ place in the function calls in this block. */
if (function_call_count != thisblock->data.block.function_call_count if (function_call_count != thisblock->data.block.function_call_count
&& nonlocal_labels && nonlocal_labels
...@@ -3053,119 +3218,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in) ...@@ -3053,119 +3218,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
special to do when you jump out of it. */ special to do when you jump out of it. */
: (thisblock->data.block.cleanups != 0 : (thisblock->data.block.cleanups != 0
|| thisblock->data.block.stack_level != 0))) || thisblock->data.block.stack_level != 0)))
{ expand_nl_goto_receivers (thisblock);
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);
}
/* Don't allow jumping into a block that has a stack level. /* Don't allow jumping into a block that has a stack level.
Cleanups are allowed, though. */ Cleanups are allowed, though. */
...@@ -3219,7 +3272,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in) ...@@ -3219,7 +3272,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
{ {
emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION, emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
thisblock->data.block.stack_level, NULL_RTX); 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, emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level,
NULL_RTX); NULL_RTX);
} }
...@@ -3266,8 +3319,6 @@ expand_end_bindings (vars, mark_ends, dont_jump_in) ...@@ -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 the stack slot nesting and free any slots at this level. */
pop_temp_slots (); pop_temp_slots ();
} }
/* Generate RTL for the automatic variable declaration DECL. /* Generate RTL for the automatic variable declaration DECL.
(Other kinds of declarations are simply ignored if seen here.) */ (Other kinds of declarations are simply ignored if seen here.) */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment