aboutsummaryrefslogtreecommitdiff
path: root/gcc/except.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>1998-09-15 12:19:12 -0700
committerRichard Henderson <rth@gcc.gnu.org>1998-09-15 12:19:12 -0700
commit710384268d9df98e595cd68c5e8db84d766d5513 (patch)
tree5f8b92560efd1078cbd16601e8b3502296539971 /gcc/except.c
parentdfb16e8307d6ca6f9ddf22dea3400324355a60a7 (diff)
downloadgcc-710384268d9df98e595cd68c5e8db84d766d5513.zip
gcc-710384268d9df98e595cd68c5e8db84d766d5513.tar.gz
gcc-710384268d9df98e595cd68c5e8db84d766d5513.tar.bz2
tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
* tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill. (BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill. (BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill. (BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New. * c-decl.c (init_decl_processing): Update accordingly. * expr.c (expand_builtin): Likewise. * cp/decl.c (init_decl_processing): Likewise. * rtl.h (global_rtl): Add cfa entry. (virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New. (LAST_VIRTUAL_REGISTER): Update. * emit-rtl.c (global_rtl): Add cfa entry. (init_emit): Initialize it. * function.c (cfa_offset): New. (instantiate_virtual_regs): Initialize it. (instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx. (expand_function_end): Call expand_eh_return. * tm.texi (ARG_POINTER_CFA_OFFSET): New. * except.c (current_function_eh_stub_label): Kill. (current_function_eh_old_stub_label): Likwise; update all references. (expand_builtin_set_return_addr_reg): Kill. (expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill. (expand_builtin_set_eh_regs): Kill. (eh_regs): Produce a third reg for the actual handler address. (eh_return_context, eh_return_stack_adjust): New. (eh_return_handler, eh_return_stub_label): New. (init_eh_for_function): Initialize them. (expand_builtin_eh_return, expand_eh_return): New. * except.h: Update prototypes. * flow.c (find_basic_blocks_1): Update references to the stub label. * function.h (struct function): Kill stub label elements. * libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the register number is one that would be in the previous window. Provide a dummy definition for non-windowed targets. (get_reg_addr): New function. (get_reg, put_reg, copy_reg): Use it. (__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa. * alpha.c (alpha_eh_epilogue_sp_ofs): New. (alpha_init_expanders): Initialize it. (alpha_expand_epilogue): Use it. * alpha.h: Declare it. * alpha.md (eh_epilogue): New. * m68h.h (ARG_POINTER_CFA_OFFSET): New. * sparc.h (ARG_POINTER_CFA_OFFSET): New. From-SVN: r22436
Diffstat (limited to 'gcc/except.c')
-rw-r--r--gcc/except.c242
1 files changed, 121 insertions, 121 deletions
diff --git a/gcc/except.c b/gcc/except.c
index f0d0009..d1e8220 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -431,12 +431,6 @@ rtx exception_handler_labels;
rtx current_function_ehc;
-/* The labels generated by expand_builtin_eh_stub and
- expand_builtin_eh_stub_old. */
-
-rtx current_function_eh_stub_label;
-rtx current_function_eh_old_stub_label;
-
/* A stack used for keeping track of the currently active exception
handling region. As each exception region is started, an entry
describing the region is pushed onto this stack. The current
@@ -496,6 +490,20 @@ struct label_node *outer_context_label_stack = NULL;
struct label_node *false_label_stack = NULL;
+/* Pseudos used to hold exception return data in the interim between
+ __builtin_eh_return and the end of the function. */
+
+static rtx eh_return_context;
+static rtx eh_return_stack_adjust;
+static rtx eh_return_handler;
+
+/* Used to mark the eh return stub for flow, so that the Right Thing
+ happens with the values for the hardregs therin. */
+
+rtx eh_return_stub_label;
+
+/* Prototypes for local functions. */
+
static void push_eh_entry PROTO((struct eh_stack *));
static struct eh_entry * pop_eh_entry PROTO((struct eh_stack *));
static void enqueue_eh_entry PROTO((struct eh_queue *, struct eh_entry *));
@@ -507,13 +515,12 @@ static void expand_rethrow PROTO((rtx));
static void output_exception_table_entry PROTO((FILE *, int));
static int can_throw PROTO((rtx));
static rtx scan_region PROTO((rtx, int, int *));
-static void eh_regs PROTO((rtx *, rtx *, int));
+static void eh_regs PROTO((rtx *, rtx *, rtx *, int));
static void set_insn_eh_region PROTO((rtx *, int));
#ifdef DONT_USE_BUILTIN_SETJMP
static void jumpif_rtx PROTO((rtx, rtx));
#endif
-
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
/* Various support routines to manipulate the various data structures
@@ -2203,8 +2210,10 @@ init_eh_for_function ()
caught_return_label_stack = 0;
protect_list = NULL_TREE;
current_function_ehc = NULL_RTX;
- current_function_eh_stub_label = NULL_RTX;
- current_function_eh_old_stub_label = NULL_RTX;
+ eh_return_context = NULL_RTX;
+ eh_return_stack_adjust = NULL_RTX;
+ eh_return_handler = NULL_RTX;
+ eh_return_stub_label = NULL_RTX;
}
/* Save some of the per-function EH info into the save area denoted by
@@ -2227,8 +2236,6 @@ save_eh_status (p)
p->caught_return_label_stack = caught_return_label_stack;
p->protect_list = protect_list;
p->ehc = current_function_ehc;
- p->eh_stub_label = current_function_eh_stub_label;
- p->eh_old_stub_label = current_function_eh_old_stub_label;
init_eh_for_function ();
}
@@ -2252,8 +2259,6 @@ restore_eh_status (p)
ehstack = p->ehstack;
catchstack = p->catchstack;
current_function_ehc = p->ehc;
- current_function_eh_stub_label = p->eh_stub_label;
- current_function_eh_old_stub_label = p->eh_old_stub_label;
}
/* This section is for the exception handling specific optimization
@@ -2465,79 +2470,72 @@ expand_builtin_frob_return_addr (addr_tree)
return addr;
}
-/* Given an actual address in addr_tree, set the return address register up
- so the epilogue will return to that address. If the return address is
- not in a register, do nothing. */
+/* Choose three registers for communication between the main body of
+ __throw and the epilogue (or eh stub) and the exception handler.
+ We must do this with hard registers because the epilogue itself
+ will be generated after reload, at which point we may not reference
+ pseudos at all.
-void
-expand_builtin_set_return_addr_reg (addr_tree)
- tree addr_tree;
-{
- rtx tmp;
- rtx ra = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
- 0, hard_frame_pointer_rtx);
-
- if (GET_CODE (ra) != REG || REGNO (ra) >= FIRST_PSEUDO_REGISTER)
- return;
-
- tmp = force_operand (expand_builtin_frob_return_addr (addr_tree), ra);
- if (tmp != ra)
- emit_move_insn (ra, tmp);
-}
+ The first passes the exception context to the handler. For this
+ we use the return value register for a void*.
-/* Choose two registers for communication between the main body of
- __throw and the stub for adjusting the stack pointer. The first register
- is used to pass the address of the exception handler; the second register
- is used to pass the stack pointer offset.
+ The second holds the stack pointer value to be restored. For
+ this we use the static chain register if it exists and is different
+ from the previous, otherwise some arbitrary call-clobbered register.
- For register 1 we use the return value register for a void *.
- For register 2 we use the static chain register if it exists and is
- different from register 1, otherwise some arbitrary call-clobbered
- register. */
+ The third holds the address of the handler itself. Here we use
+ some arbitrary call-clobbered register. */
static void
-eh_regs (r1, r2, outgoing)
- rtx *r1, *r2;
+eh_regs (pcontext, psp, pra, outgoing)
+ rtx *pcontext, *psp, *pra;
int outgoing;
{
- rtx reg1, reg2;
+ rtx rcontext, rsp, rra;
+ int i;
#ifdef FUNCTION_OUTGOING_VALUE
if (outgoing)
- reg1 = FUNCTION_OUTGOING_VALUE (build_pointer_type (void_type_node),
- current_function_decl);
+ rcontext = FUNCTION_OUTGOING_VALUE (build_pointer_type (void_type_node),
+ current_function_decl);
else
#endif
- reg1 = FUNCTION_VALUE (build_pointer_type (void_type_node),
- current_function_decl);
+ rcontext = FUNCTION_VALUE (build_pointer_type (void_type_node),
+ current_function_decl);
#ifdef STATIC_CHAIN_REGNUM
if (outgoing)
- reg2 = static_chain_incoming_rtx;
+ rsp = static_chain_incoming_rtx;
else
- reg2 = static_chain_rtx;
- if (REGNO (reg2) == REGNO (reg1))
+ rsp = static_chain_rtx;
+ if (REGNO (rsp) == REGNO (rcontext))
#endif /* STATIC_CHAIN_REGNUM */
- reg2 = NULL_RTX;
+ rsp = NULL_RTX;
- if (reg2 == NULL_RTX)
+ if (rsp == NULL_RTX)
{
- int i;
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
- if (call_used_regs[i] && ! fixed_regs[i] && i != REGNO (reg1))
- {
- reg2 = gen_rtx_REG (Pmode, i);
- break;
- }
+ if (call_used_regs[i] && ! fixed_regs[i] && i != REGNO (rcontext))
+ break;
+ if (i == FIRST_PSEUDO_REGISTER)
+ abort();
- if (reg2 == NULL_RTX)
- abort ();
+ rsp = gen_rtx_REG (Pmode, i);
}
- *r1 = reg1;
- *r2 = reg2;
-}
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (call_used_regs[i] && ! fixed_regs[i]
+ && i != REGNO (rcontext) && i != REGNO (rsp))
+ break;
+ if (i == FIRST_PSEUDO_REGISTER)
+ abort();
+
+ rra = gen_rtx_REG (Pmode, i);
+ *pcontext = rcontext;
+ *psp = rsp;
+ *pra = rra;
+}
/* Retrieve the register which contains the pointer to the eh_context
structure set the __throw. */
@@ -2551,83 +2549,85 @@ get_reg_for_handler ()
return reg1;
}
+/* Set up the epilogue with the magic bits we'll need to return to the
+ exception handler. */
-/* Emit inside of __throw a stub which adjusts the stack pointer and jumps
- to the exception handler. __throw will set up the necessary values
- and then return to the stub. */
-
-rtx
-expand_builtin_eh_stub_old ()
+void
+expand_builtin_eh_return (context, stack, handler)
+ tree context, stack, handler;
{
- rtx stub_start = gen_label_rtx ();
- rtx after_stub = gen_label_rtx ();
- rtx handler, offset;
+ if (eh_return_context)
+ error("Duplicate call to __builtin_eh_return");
- current_function_eh_old_stub_label = stub_start;
-
- emit_jump (after_stub);
- emit_label (stub_start);
-
- eh_regs (&handler, &offset, 0);
-
- adjust_stack (offset);
- emit_indirect_jump (handler);
- emit_label (after_stub);
- return gen_rtx_LABEL_REF (Pmode, stub_start);
+ eh_return_context
+ = copy_to_reg (expand_expr (context, NULL_RTX, VOIDmode, 0));
+ eh_return_stack_adjust
+ = copy_to_reg (expand_expr (stack, NULL_RTX, VOIDmode, 0));
+ eh_return_handler
+ = copy_to_reg (expand_expr (handler, NULL_RTX, VOIDmode, 0));
}
-rtx
-expand_builtin_eh_stub ()
+void
+expand_eh_return ()
{
- rtx stub_start = gen_label_rtx ();
- rtx after_stub = gen_label_rtx ();
- rtx handler, offset;
- rtx temp;
-
- current_function_eh_stub_label = stub_start;
-
- emit_jump (after_stub);
- emit_label (stub_start);
+ rtx reg1, reg2, reg3;
+ rtx stub_start, after_stub;
+ rtx ra, tmp;
- eh_regs (&handler, &offset, 0);
+ if (!eh_return_context)
+ return;
- adjust_stack (offset);
+ eh_regs (&reg1, &reg2, &reg3, 1);
+ emit_move_insn (reg1, eh_return_context);
+ emit_move_insn (reg2, eh_return_stack_adjust);
+ emit_move_insn (reg3, eh_return_handler);
- /* Handler is in fact a pointer to the _eh_context structure, we need
- to pick out the handler field (first element), and jump to there,
- leaving the pointer to _eh_conext in the same hardware register. */
+ /* Talk directly to the target's epilogue code when possible. */
- temp = gen_rtx_MEM (Pmode, handler);
- MEM_IN_STRUCT_P (temp) = 1;
- RTX_UNCHANGING_P (temp) = 1;
- emit_move_insn (offset, temp);
- emit_insn (gen_rtx_USE (Pmode, handler));
+#ifdef HAVE_eh_epilogue
+ if (HAVE_eh_epilogue)
+ {
+ emit_insn (gen_eh_epilogue (reg1, reg2, reg3));
+ return;
+ }
+#endif
- emit_indirect_jump (offset);
-
- emit_label (after_stub);
- return gen_rtx_LABEL_REF (Pmode, stub_start);
-}
+ /* Otherwise, use the same stub technique we had before. */
-/* Set up the registers for passing the handler address and stack offset
- to the stub above. */
+ eh_return_stub_label = stub_start = gen_label_rtx ();
+ after_stub = gen_label_rtx ();
-void
-expand_builtin_set_eh_regs (handler, offset)
- tree handler, offset;
-{
- rtx reg1, reg2;
+ /* Set the return address to the stub label. */
- eh_regs (&reg1, &reg2, 1);
+ ra = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
+ 0, hard_frame_pointer_rtx);
+ if (GET_CODE (ra) == REG && REGNO (ra) >= FIRST_PSEUDO_REGISTER)
+ abort();
- store_expr (offset, reg2, 0);
- store_expr (handler, reg1, 0);
+ tmp = memory_address (Pmode, gen_rtx_LABEL_REF (Pmode, stub_start));
+#ifdef RETURN_ADDR_OFFSET
+ tmp = plus_constant (tmp, -RETURN_ADDR_OFFSET);
+#endif
+ emit_move_insn (ra, tmp);
- /* These will be used by the stub. */
+ /* Indicate that the registers are in fact used. */
emit_insn (gen_rtx_USE (VOIDmode, reg1));
emit_insn (gen_rtx_USE (VOIDmode, reg2));
-}
+ emit_insn (gen_rtx_USE (VOIDmode, reg3));
+ if (GET_CODE (ra) == REG)
+ emit_insn (gen_rtx_USE (VOIDmode, ra));
+ /* Generate the stub. */
+
+ emit_jump (after_stub);
+ emit_label (stub_start);
+
+ eh_regs (&reg1, &reg2, &reg3, 0);
+ adjust_stack (reg2);
+ emit_indirect_jump (reg3);
+
+ emit_label (after_stub);
+}
/* This contains the code required to verify whether arbitrary instructions