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,14 +3666,23 @@ delete_handlers () ...@@ -3664,14 +3666,23 @@ 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);
} }
}
} }
/* Return a list (chain of EXPR_LIST nodes) for the nonlocal labels /* Return a list (chain of EXPR_LIST nodes) for the nonlocal labels
...@@ -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,101 +3002,33 @@ remember_end_note (block) ...@@ -2992,101 +3002,33 @@ remember_end_note (block)
last_block_end_note = NULL_RTX; last_block_end_note = NULL_RTX;
} }
/* Generate RTL code to terminate a binding contour. /* Emit a handler label for a nonlocal goto handler.
VARS is the chain of VAR_DECL nodes Also emit code to store the handler label in SLOT before BEFORE_INSN. */
for the variables bound in this contour.
MARK_ENDS is nonzero if we should put a note at the beginning
and end of this binding contour.
DONT_JUMP_IN is nonzero if it is not valid to jump into this contour.
(That is true automatically if the contour has a saved stack level.) */
void static void
expand_end_bindings (vars, mark_ends, dont_jump_in) expand_nl_handler_label (slot, before_insn)
tree vars; rtx slot, before_insn;
int mark_ends;
int dont_jump_in;
{ {
register struct nesting *thisblock;
register tree decl;
while (block_stack->data.block.exception_region)
{
/* Because we don't need or want a new temporary level and
because we didn't create one in expand_eh_region_start,
create a fake one now to avoid removing one in
expand_end_bindings. */
push_temp_slots ();
block_stack->data.block.exception_region = 0;
expand_end_bindings (NULL_TREE, 0, 0);
}
/* Since expand_eh_region_start does an expand_start_bindings, we
have to first end all the bindings that were created by
expand_eh_region_start. */
thisblock = block_stack;
if (warn_unused)
for (decl = vars; decl; decl = TREE_CHAIN (decl))
if (! TREE_USED (decl) && TREE_CODE (decl) == VAR_DECL
&& ! DECL_IN_SYSTEM_HEADER (decl)
&& DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
warning_with_decl (decl, "unused variable `%s'");
if (thisblock->exit_label)
{
do_pending_stack_adjust ();
emit_label (thisblock->exit_label);
}
/* If necessary, make a handler for nonlocal gotos taking
place in the function calls in this block. */
if (function_call_count != thisblock->data.block.function_call_count
&& nonlocal_labels
/* Make handler for outermost block
if there were any nonlocal gotos to this function. */
&& (thisblock->next == 0 ? current_function_has_nonlocal_label
/* Make handler for inner block if it has something
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; rtx insns;
rtx handler_label = gen_label_rtx ();
/* Don't let jump_optimize delete the handler. */ /* Don't let jump_optimize delete the handler. */
LABEL_PRESERVE_P (handler_label) = 1; 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 (); start_sequence ();
emit_move_insn (nonlocal_goto_handler_slot, emit_move_insn (slot, gen_rtx_LABEL_REF (Pmode, handler_label));
gen_rtx_LABEL_REF (Pmode, handler_label));
insns = get_insns (); insns = get_insns ();
end_sequence (); end_sequence ();
emit_insns_before (insns, thisblock->data.block.first_insn); emit_insns_before (insns, before_insn);
/* Jump around the handler; it runs only when specially invoked. */
emit_jump (afterward);
emit_label (handler_label); 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 #ifdef HAVE_nonlocal_goto
if (! HAVE_nonlocal_goto) if (! HAVE_nonlocal_goto)
#endif #endif
...@@ -3142,31 +3084,142 @@ expand_end_bindings (vars, mark_ends, dont_jump_in) ...@@ -3142,31 +3084,142 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
if (HAVE_nonlocal_goto_receiver) if (HAVE_nonlocal_goto_receiver)
emit_insn (gen_nonlocal_goto_receiver ()); emit_insn (gen_nonlocal_goto_receiver ());
#endif #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);
/* The handler expects the desired label address in the static chain start_sequence ();
register. It tests the address and does an appropriate jump emit_move_insn (save_receiver, XEXP (slot, 0));
to whatever label is desired. */ insns = get_insns ();
for (link = nonlocal_labels; link; link = TREE_CHAIN (link)) end_sequence ();
/* Skip any labels we shouldn't be able to jump to from here. */ 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))) if (! DECL_TOO_LATE (TREE_VALUE (link)))
{ {
rtx not_this = gen_label_rtx (); expand_nl_handler_label (XEXP (slot, 0),
rtx this = gen_label_rtx (); thisblock->data.block.first_insn);
do_jump_if_equal (static_chain_rtx, expand_nl_goto_receiver ();
gen_rtx_LABEL_REF (Pmode, DECL_RTL (TREE_VALUE (link))),
this, 0); /* Jump to the "real" nonlocal label. */
emit_jump (not_this);
emit_label (this);
expand_goto (TREE_VALUE (link)); expand_goto (TREE_VALUE (link));
emit_label (not_this);
} }
/* If label is not recognized, abort. */
/* 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, emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "abort"), 0,
VOIDmode, 0); VOIDmode, 0);
emit_barrier (); emit_barrier ();
}
emit_label (afterward); 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.
MARK_ENDS is nonzero if we should put a note at the beginning
and end of this binding contour.
DONT_JUMP_IN is nonzero if it is not valid to jump into this contour.
(That is true automatically if the contour has a saved stack level.) */
void
expand_end_bindings (vars, mark_ends, dont_jump_in)
tree vars;
int mark_ends;
int dont_jump_in;
{
register struct nesting *thisblock;
register tree decl;
while (block_stack->data.block.exception_region)
{
/* Because we don't need or want a new temporary level and
because we didn't create one in expand_eh_region_start,
create a fake one now to avoid removing one in
expand_end_bindings. */
push_temp_slots ();
block_stack->data.block.exception_region = 0;
expand_end_bindings (NULL_TREE, 0, 0);
} }
/* Since expand_eh_region_start does an expand_start_bindings, we
have to first end all the bindings that were created by
expand_eh_region_start. */
thisblock = block_stack;
if (warn_unused)
for (decl = vars; decl; decl = TREE_CHAIN (decl))
if (! TREE_USED (decl) && TREE_CODE (decl) == VAR_DECL
&& ! DECL_IN_SYSTEM_HEADER (decl)
&& DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
warning_with_decl (decl, "unused variable `%s'");
if (thisblock->exit_label)
{
do_pending_stack_adjust ();
emit_label (thisblock->exit_label);
}
/* 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
/* Make handler for outermost block
if there were any nonlocal gotos to this function. */
&& (thisblock->next == 0 ? current_function_has_nonlocal_label
/* Make handler for inner block if it has something
special to do when you jump out of it. */
: (thisblock->data.block.cleanups != 0
|| thisblock->data.block.stack_level != 0)))
expand_nl_goto_receivers (thisblock);
/* 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. */
if (dont_jump_in if (dont_jump_in
...@@ -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);
} }
...@@ -3267,8 +3320,6 @@ expand_end_bindings (vars, mark_ends, dont_jump_in) ...@@ -3267,8 +3320,6 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
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