diff options
| author | hp <hp@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-10-23 01:05:25 +0000 |
|---|---|---|
| committer | hp <hp@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-10-23 01:05:25 +0000 |
| commit | 36a8ce77e2b453205a64e49d7ee443d14997f00b (patch) | |
| tree | 86348b8c9c7685079a971f61f3b53e883b7eda9a /gcc/stmt.c | |
| parent | 6809a216234e9b4045566d5dc891f1819ff58c51 (diff) | |
| download | ppe42-gcc-36a8ce77e2b453205a64e49d7ee443d14997f00b.tar.gz ppe42-gcc-36a8ce77e2b453205a64e49d7ee443d14997f00b.zip | |
PR middle-end/55030
Revert:
* stmt.c (expand_nl_goto_receiver): Remove almost-copy of
expand_builtin_setjmp_receiver.
(expand_label): Adjust, call expand_builtin_setjmp_receiver
with NULL for the label parameter.
* builtins.c (expand_builtin_setjmp_receiver): Don't clobber
the frame-pointer. Adjust comments.
[HAVE_builtin_setjmp_receiver]: Emit builtin_setjmp_receiver
only if LABEL is non-NULL.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@192701 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/stmt.c')
| -rw-r--r-- | gcc/stmt.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/gcc/stmt.c b/gcc/stmt.c index 07e7cc74159..14a28abcc58 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -106,6 +106,7 @@ extern basic_block label_to_block_fn (struct function *, tree); static int n_occurrences (int, const char *); static bool tree_conflicts_with_clobbers_p (tree, HARD_REG_SET *); +static void expand_nl_goto_receiver (void); static bool check_operand_nalternatives (tree, tree); static bool check_unique_operand_names (tree, tree, tree); static char *resolve_operand_name_1 (char *, tree, tree, tree); @@ -199,7 +200,7 @@ expand_label (tree label) if (DECL_NONLOCAL (label)) { - expand_builtin_setjmp_receiver (NULL); + expand_nl_goto_receiver (); nonlocal_goto_handler_labels = gen_rtx_EXPR_LIST (VOIDmode, label_r, nonlocal_goto_handler_labels); @@ -1555,6 +1556,77 @@ expand_return (tree retval) } } +/* Emit code to restore vital registers at the beginning of a nonlocal goto + handler. */ +static void +expand_nl_goto_receiver (void) +{ + rtx chain; + + /* Clobber the FP when we get here, so we have to make sure it's + marked as used by this function. */ + emit_use (hard_frame_pointer_rtx); + + /* Mark the static chain as clobbered here so life information + doesn't get messed up for it. */ + chain = targetm.calls.static_chain (current_function_decl, true); + if (chain && REG_P (chain)) + emit_clobber (chain); + +#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 !HARD_FRAME_POINTER_IS_ARG_POINTER + 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 const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS; + size_t i; + + for (i = 0; i < ARRAY_SIZE (elim_regs); i++) + if (elim_regs[i].from == ARG_POINTER_REGNUM + && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM) + break; + + if (i == ARRAY_SIZE (elim_regs)) +#endif + { + /* Now restore our arg pointer from the address at which it + was saved in our stack frame. */ + emit_move_insn (crtl->args.internal_arg_pointer, + copy_to_reg (get_arg_pointer_save_area ())); + } + } +#endif + +#ifdef HAVE_nonlocal_goto_receiver + if (HAVE_nonlocal_goto_receiver) + emit_insn (gen_nonlocal_goto_receiver ()); +#endif + + /* We must not allow the code we just generated to be reordered by + scheduling. Specifically, the update of the frame pointer must + happen immediately, not later. */ + emit_insn (gen_blockage ()); +} /* Emit code to save the current value of stack. */ rtx |

