From: Bernd Schmidt Date: Fri, 20 Nov 1998 07:37:42 +0000 (+0000) Subject: function.c (nonlocal_goto_handler_slots): Renamed from nonlocal_goto_handler_slot... X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ba716ac9252b1a97585420a02c4f3172902e4dd3;p=platform%2Fupstream%2Fgcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fff326d..efd0cd9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,34 @@ -Thu Nov 19 23:44:38 1998 Bernd Schmidt +Fri Nov 20 08:34:00 1998 Bernd Schmidt + + * 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 6f67b7c..79cae9f 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 c99c6c1..ef88484 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 69b68fd..59fcd59 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 0dbf002..e4ef27d 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 b1665aa..896bded 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 fa8b14a..d9575cc 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 d5e6cd0..e78b2e1 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 33702db..affd4b5 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.) */