tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused.
authorRichard Henderson <rth@cygnus.com>
Tue, 15 Sep 1998 19:19:12 +0000 (12:19 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 15 Sep 1998 19:19:12 +0000 (12:19 -0700)
* 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

20 files changed:
gcc/ChangeLog
gcc/c-decl.c
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/alpha/alpha.md
gcc/config/m68k/m68k.h
gcc/config/sparc/sparc.h
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/emit-rtl.c
gcc/except.c
gcc/except.h
gcc/expr.c
gcc/flow.c
gcc/function.c
gcc/function.h
gcc/libgcc2.c
gcc/rtl.h
gcc/tm.texi
gcc/tree.h

index fd810b06868d8f9cf3ae778c5487931b827c1cb9..5e646cdae0657eacf68055610b31c0d227798eeb 100644 (file)
@@ -1,3 +1,54 @@
+Tue Sep 15 19:09:06 1998  Richard Henderson  <rth@cygnus.com>
+
+       * 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.
+
+       * 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.
+
 Tue Sep 15 19:31:58 1998  Michael Meissner  <meissner@cygnus.com>
 
        * i960.h (CONST_COSTS): Fix thinko.  Test flag, not the constant
index 168400bd7f5ada0c1605a00af6b0911c52f8d719..f05dc27a1a775f66507a891c17d60e75d2f80ae4 100644 (file)
@@ -3291,8 +3291,8 @@ init_decl_processing ()
   builtin_function ("__builtin_unwind_init",
                    build_function_type (void_type_node, endlink),
                    BUILT_IN_UNWIND_INIT, NULL_PTR);
-  builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
-  builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
+  builtin_function ("__builtin_dwarf_cfa", ptr_ftype_void,
+                   BUILT_IN_DWARF_CFA, NULL_PTR);
   builtin_function ("__builtin_dwarf_fp_regnum",
                    build_function_type (unsigned_type_node, endlink),
                    BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
@@ -3302,24 +3302,16 @@ init_decl_processing ()
                    BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
   builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
                    BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
-  builtin_function ("__builtin_set_return_addr_reg",
-                   build_function_type (void_type_node, 
-                                        tree_cons (NULL_TREE,
-                                                   ptr_type_node,
-                                                   endlink)),
-                   BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR);
-  builtin_function ("__builtin_eh_stub_old", ptr_ftype_void,
-                   BUILT_IN_EH_STUB_OLD, NULL_PTR);
-  builtin_function ("__builtin_eh_stub", ptr_ftype_void,
-                   BUILT_IN_EH_STUB, NULL_PTR);
   builtin_function
-    ("__builtin_set_eh_regs",
+    ("__builtin_eh_return",
      build_function_type (void_type_node,
                          tree_cons (NULL_TREE, ptr_type_node,
                                     tree_cons (NULL_TREE,
                                                type_for_mode (ptr_mode, 0),
-                                               endlink))),
-     BUILT_IN_SET_EH_REGS, NULL_PTR);
+                                               tree_cons (NULL_TREE,
+                                                          ptr_type_node,
+                                                          endlink)))),
+     BUILT_IN_EH_RETURN, NULL_PTR);
 
   builtin_function ("__builtin_alloca",
                    build_function_type (ptr_type_node,
index f0795f3fa54c77e1b252ee55128a671481dddbd4..2b2971452a70cdc9eb87835ce88b519155c72325 100644 (file)
@@ -79,6 +79,10 @@ char *alpha_mlat_string;     /* -mmemory-latency= */
 rtx alpha_compare_op0, alpha_compare_op1;
 int alpha_compare_fp_p;
 
+/* Define the information needed to modify the epilogue for EH.  */
+
+rtx alpha_eh_epilogue_sp_ofs;
+
 /* Non-zero if inside of a function, because the Alpha asm can't
    handle .files inside of functions.  */
 
@@ -2431,6 +2435,7 @@ void
 alpha_init_expanders ()
 {
   alpha_return_addr_rtx = NULL_RTX;
+  alpha_eh_epilogue_sp_ofs = NULL_RTX;
 
   /* Arrange to save and restore machine status around nested functions.  */
   save_machine_status = alpha_save_machine_status;
@@ -3731,9 +3736,13 @@ alpha_expand_epilogue ()
          
       /* Restore registers in order, excepting a true frame pointer. */
 
-      FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA),
-                          gen_rtx_MEM (DImode, plus_constant(sa_reg,
-                                                             reg_offset))));
+      if (! alpha_eh_epilogue_sp_ofs)
+       {
+          FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA),
+                              gen_rtx_MEM (DImode,
+                                           plus_constant(sa_reg,
+                                                         reg_offset))));
+       }
       reg_offset += 8;
       imask &= ~(1L << REG_RA);
 
@@ -3763,21 +3772,28 @@ alpha_expand_epilogue ()
          }
     }
 
-  if (frame_size)
+  if (frame_size || alpha_eh_epilogue_sp_ofs)
     {
+      sp_adj1 = stack_pointer_rtx;
+
+      if (alpha_eh_epilogue_sp_ofs)
+       {
+         sp_adj1 = gen_rtx_REG (DImode, 23);
+         emit_move_insn (sp_adj1,
+                         gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+                                       alpha_eh_epilogue_sp_ofs));
+       }
+
       /* If the stack size is large, begin computation into a temporary
         register so as not to interfere with a potential fp restore,
         which must be consecutive with an SP restore.  */
       if (frame_size < 32768)
-       {
-         sp_adj1 = stack_pointer_rtx;
-         sp_adj2 = GEN_INT (frame_size);
-       }
+       sp_adj2 = GEN_INT (frame_size);
       else if (frame_size < 0x40007fffL)
        {
          int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
 
-         sp_adj2 = plus_constant (stack_pointer_rtx, frame_size - low);
+         sp_adj2 = plus_constant (sp_adj1, frame_size - low);
          if (sa_reg_exp && rtx_equal_p (sa_reg_exp, sp_adj2))
            sp_adj1 = sa_reg;
          else
@@ -3789,21 +3805,20 @@ alpha_expand_epilogue ()
        }
       else
        {
-         sp_adj2 = gen_rtx_REG (DImode, 23);
-         FRP (sp_adj1 = alpha_emit_set_const (sp_adj2, DImode, frame_size, 3));
-         if (!sp_adj1)
+         rtx tmp = gen_rtx_REG (DImode, 23);
+         FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size, 3));
+         if (!sp_adj2)
            {
              /* We can't drop new things to memory this late, afaik,
                 so build it up by pieces.  */
 #if HOST_BITS_PER_WIDE_INT == 64
-             FRP (sp_adj1 = alpha_emit_set_long_const (sp_adj2, frame_size));
-             if (!sp_adj1)
+             FRP (sp_adj2 = alpha_emit_set_long_const (tmp, frame_size));
+             if (!sp_adj2)
                abort ();
 #else
              abort ();
 #endif
            }
-         sp_adj2 = stack_pointer_rtx;
        }
 
       /* From now on, things must be in order.  So emit blockages.  */
index 2021e677895282a68f234789a28d44d9dd416829..0a99e07a556e74d57901e01f7cad4a23f5f0f176 100644 (file)
@@ -1180,6 +1180,10 @@ extern struct rtx_def *alpha_builtin_saveregs ();
 extern struct rtx_def *alpha_compare_op0, *alpha_compare_op1;
 extern int alpha_compare_fp_p;
 
+/* Define the information needed to modify the epilogue for EH.  */
+
+extern struct rtx_def *alpha_eh_epilogue_sp_ofs;
+
 /* Make (or fake) .linkage entry for function call.
    IS_LOCAL is 0 if name is used in call, 1 if name is used in definition.  */
 extern void alpha_need_linkage ();
index 232fb01def14ba1aafca04bf733fd789ff4aa8d0..a214cc487c1bb8a6223d113f60aa4a02225eb14b 100644 (file)
   ""
   "alpha_expand_epilogue (); DONE;")
 
+(define_expand "eh_epilogue"
+  [(use (match_operand:DI 0 "register_operand" "r"))
+   (use (match_operand:DI 1 "register_operand" "r"))
+   (use (match_operand:DI 2 "register_operand" "r"))]
+  "! TARGET_OPEN_VMS"
+  "
+{
+  alpha_eh_epilogue_sp_ofs = operands[1];
+  if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 26)
+    {
+      rtx ra = gen_rtx_REG (Pmode, 26);
+      emit_move_insn (ra, operands[2]);
+      operands[2] = ra;
+    }
+}")
+
 (define_expand "builtin_longjmp"
   [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)]
   "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
index 1c17e28e4cef4b1082624116bd653b4f7d60586a..a4bfef9a638419d04decc464297b8d291094ff3a 100644 (file)
@@ -858,6 +858,9 @@ extern enum reg_class regno_reg_class[];
 /* Offset of first parameter from the argument pointer register value.  */
 #define FIRST_PARM_OFFSET(FNDECL) 8
 
+/* Offset of the CFA from the argument pointer register value.  */
+#define ARG_POINTER_CFA_OFFSET 8
+
 /* Value is the number of byte of arguments automatically
    popped when returning from a subroutine call.
    FUNDECL is the declaration node of the function (as a tree),
index c68c3d02916836551c2af9ac8c2d01465142e84f..d5812d0dbdd3abc87befc936c7df840a95aa9646 100644 (file)
@@ -1478,6 +1478,10 @@ extern char leaf_reg_remap[];
   (TARGET_ARCH64 ? (SPARC_STACK_BIAS + 16 * UNITS_PER_WORD) \
    : (STRUCT_VALUE_OFFSET + UNITS_PER_WORD))
 
+/* Offset from the argument pointer register value to the CFA.  */
+
+#define ARG_POINTER_CFA_OFFSET  SPARC_STACK_BIAS
+
 /* When a parameter is passed in a register, stack space is still
    allocated for it.
    !v9: All 6 possible integer registers have backing store allocated.
index d1d68ac821b10032679bf19980722a625e46bea6..f1af3744c394f2b5fb38cb426e8ed13aeb63d72f 100644 (file)
@@ -1,3 +1,7 @@
+1998-09-16  Richard Henderson  <rth@cygnus.com>
+
+        * decl.c (init_decl_processing): Kill __builtin_fp and __builtin_sp.
+
 1998-09-15  Alexandre Oliva  <oliva@dcc.unicamp.br>
 
        * call.c (build_field_call): handle static data members too
index 98f933607b7daf7d3651779a683262d4c2254648..ee094e5d419d0ffccff42b824f113d4ff0aeee1e 100644 (file)
@@ -5891,10 +5891,6 @@ init_decl_processing ()
   builtin_function ("__builtin_frame_address", ptr_ftype_unsigned,
                    BUILT_IN_FRAME_ADDRESS, NULL_PTR);
 
-  ptr_ftype_void = build_function_type (ptr_type_node, endlink);
-  builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
-  builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
-
   builtin_function ("__builtin_alloca", ptr_ftype_sizetype,
                    BUILT_IN_ALLOCA, "alloca");
   builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
index a59437b41031f04ba62c2fca6bd216ffbbc95952..e5510a6dbebdcede123635af4acbe76d0626a16d 100644 (file)
@@ -103,6 +103,7 @@ struct _global_rtl global_rtl =
   {REG},                               /* virtual_stack_vars_rtx */
   {REG},                               /* virtual_stack_dynamic_rtx */
   {REG},                               /* virtual_outgoing_args_rtx */
+  {REG},                               /* virtual_cfa_rtx */
 };
 
 /* We record floating-point CONST_DOUBLEs in each floating-point mode for
@@ -3342,6 +3343,7 @@ init_emit ()
   regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx;
   regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx;
   regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx;
+  regno_reg_rtx[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx;
 
   /* Indicate that the virtual registers and stack locations are
      all pointers.  */
@@ -3354,6 +3356,7 @@ init_emit ()
   REGNO_POINTER_FLAG (VIRTUAL_STACK_VARS_REGNUM) = 1;
   REGNO_POINTER_FLAG (VIRTUAL_STACK_DYNAMIC_REGNUM) = 1;
   REGNO_POINTER_FLAG (VIRTUAL_OUTGOING_ARGS_REGNUM) = 1;
+  REGNO_POINTER_FLAG (VIRTUAL_CFA_REGNUM) = 1;
 
 #ifdef STACK_BOUNDARY
   REGNO_POINTER_ALIGN (STACK_POINTER_REGNUM) = STACK_BOUNDARY / BITS_PER_UNIT;
@@ -3370,6 +3373,7 @@ init_emit ()
     = STACK_BOUNDARY / BITS_PER_UNIT;
   REGNO_POINTER_ALIGN (VIRTUAL_OUTGOING_ARGS_REGNUM)
     = STACK_BOUNDARY / BITS_PER_UNIT;
+  REGNO_POINTER_ALIGN (VIRTUAL_CFA_REGNUM) = UNITS_PER_WORD;
 #endif
 
 #ifdef INIT_EXPANDERS
@@ -3504,6 +3508,8 @@ init_emit_once (line_numbers)
   PUT_MODE (virtual_stack_dynamic_rtx, Pmode);
   REGNO (virtual_outgoing_args_rtx) = VIRTUAL_OUTGOING_ARGS_REGNUM;
   PUT_MODE (virtual_outgoing_args_rtx, Pmode);
+  REGNO (virtual_cfa_rtx) = VIRTUAL_CFA_REGNUM;
+  PUT_MODE (virtual_cfa_rtx, Pmode);
 
 #ifdef RETURN_ADDRESS_POINTER_REGNUM
   return_address_pointer_rtx
index f0d00094f8595a687e3698c51a6f0620abbcee85..d1e82208d42205c78430bf1e2f3fb4c26465e922 100644 (file)
@@ -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));
 \f
 /* 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;
 }
 \f
 /* 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);
+}
 \f
 
 /* This contains the code required to verify whether arbitrary instructions
index 5416e5987605e593afecdbeffd80421f28fff993..540044bde02812e2c21f169db05b4c751b693f5f 100644 (file)
@@ -24,11 +24,9 @@ typedef struct rtx_def *_except_rtx;
 #define rtx _except_rtx
 #endif
 
-/* The labels generated by expand_builtin_eh_stub and
-   expand_builtin_eh_stub_old.  */
+/* The label generated by expand_builtin_eh_return.  */
 
-extern rtx current_function_eh_stub_label;
-extern rtx current_function_eh_old_stub_label;
+extern rtx eh_return_stub_label;
 
 #ifdef TREE_CODE
 
@@ -377,15 +375,13 @@ extern void expand_fixup_region_end       PROTO((tree));
 
 void expand_builtin_unwind_init                PROTO((void));
 rtx expand_builtin_dwarf_fp_regnum     PROTO((void));
-rtx expand_builtin_eh_stub             PROTO((void));
-rtx expand_builtin_eh_stub_old          PROTO((void));
 #ifdef TREE_CODE
 rtx expand_builtin_frob_return_addr    PROTO((tree));
 rtx expand_builtin_extract_return_addr PROTO((tree));
-void expand_builtin_set_return_addr_reg PROTO((tree));
-void expand_builtin_set_eh_regs                PROTO((tree, tree));
 rtx expand_builtin_dwarf_reg_size      PROTO((tree, rtx));
+void expand_builtin_eh_return          PROTO((tree, tree, tree));
 #endif
+void expand_eh_return                  PROTO((void));
 
 
 /* Checking whether 2 instructions are within the same exception region. */
index dbf19ff102d158f22ffc9f4acc0cc03890b82854..028f9b21cfda28e73651d81caa8a95e58c745607 100644 (file)
@@ -9370,10 +9370,8 @@ expand_builtin (exp, target, subtarget, mode, ignore)
     case BUILT_IN_UNWIND_INIT:
       expand_builtin_unwind_init ();
       return const0_rtx;
-    case BUILT_IN_FP:
-      return frame_pointer_rtx;
-    case BUILT_IN_SP:
-      return stack_pointer_rtx;
+    case BUILT_IN_DWARF_CFA:
+      return virtual_cfa_rtx;
 #ifdef DWARF2_UNWIND_INFO
     case BUILT_IN_DWARF_FP_REGNUM:
       return expand_builtin_dwarf_fp_regnum ();
@@ -9384,16 +9382,10 @@ expand_builtin (exp, target, subtarget, mode, ignore)
       return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
     case BUILT_IN_EXTRACT_RETURN_ADDR:
       return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
-    case BUILT_IN_SET_RETURN_ADDR_REG:
-      expand_builtin_set_return_addr_reg (TREE_VALUE (arglist));
-      return const0_rtx;
-    case BUILT_IN_EH_STUB_OLD:
-      return expand_builtin_eh_stub_old ();
-    case BUILT_IN_EH_STUB:
-      return expand_builtin_eh_stub ();
-    case BUILT_IN_SET_EH_REGS:
-      expand_builtin_set_eh_regs (TREE_VALUE (arglist),
-                                 TREE_VALUE (TREE_CHAIN (arglist)));
+    case BUILT_IN_EH_RETURN:
+      expand_builtin_eh_return (TREE_VALUE (arglist),
+                               TREE_VALUE (TREE_CHAIN (arglist)),
+                               TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
       return const0_rtx;
 
     default:                   /* just do library call, if unknown builtin */
index a7ce4a367e003ada7559de55b5362fbc5bb65bfb..fb309be735a9b580865b652f8071585fe561f3aa 100644 (file)
@@ -485,8 +485,7 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
          /* Make a list of all labels referred to other than by jumps.  */
          for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
            if (REG_NOTE_KIND (note) == REG_LABEL
-               && XEXP (note, 0) != current_function_eh_stub_label
-               && XEXP (note, 0) != current_function_eh_old_stub_label)
+               && XEXP (note, 0) != eh_return_stub_label)
              label_value_list = gen_rtx_EXPR_LIST (VOIDmode, XEXP (note, 0),
                                                    label_value_list);
        }
@@ -619,8 +618,7 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
                             note = XEXP (note, 1))
                          {
                            if (REG_NOTE_KIND (note) == REG_LABEL
-                               && XEXP (note, 0) != current_function_eh_stub_label
-                               && XEXP (note, 0) != current_function_eh_old_stub_label)
+                               && XEXP (note, 0) != eh_return_stub_label)
                              {
                                x = XEXP (note, 0);
                                block_live[BLOCK_NUM (x)] = 1;
@@ -708,13 +706,10 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
                   within it.  So we have to make additional edges in the
                   flow graph.  */
                if (i + 1 == n_basic_blocks
-                   && current_function_eh_stub_label != 0)
+                   && eh_return_stub_label != 0)
                  {
                    mark_label_ref (gen_rtx_LABEL_REF (VOIDmode,
-                                                      current_function_eh_stub_label),
-                                   basic_block_end[i], 0);
-                   mark_label_ref (gen_rtx_LABEL_REF (VOIDmode,
-                                                      current_function_eh_old_stub_label),
+                                                      eh_return_stub_label),
                                    basic_block_end[i], 0);
                  }
              }
index 5bd012fc1356c8aa8f5f51ccfe583dbcfa590684..a5f8f0591c1ec84638e14273e90237caab12e525 100644 (file)
@@ -2688,6 +2688,7 @@ static int in_arg_offset;
 static int var_offset;
 static int dynamic_offset;
 static int out_arg_offset;
+static int cfa_offset;
 
 /* In most machines, the stack pointer register is equivalent to the bottom
    of the stack.  */
@@ -2726,6 +2727,13 @@ static int out_arg_offset;
 #endif
 #endif
 
+/* On a few machines, the CFA coincides with the arg pointer.  */
+
+#ifndef ARG_POINTER_CFA_OFFSET
+#define ARG_POINTER_CFA_OFFSET 0
+#endif
+
+
 /* Build up a (MEM (ADDRESSOF (REG))) rtx for a register REG that just had
    its address taken.  DECL is the decl for the object stored in the
    register, for later use if we do need to force REG into the stack.
@@ -2910,6 +2918,7 @@ instantiate_virtual_regs (fndecl, insns)
   var_offset = STARTING_FRAME_OFFSET;
   dynamic_offset = STACK_DYNAMIC_OFFSET (fndecl);
   out_arg_offset = STACK_POINTER_OFFSET;
+  cfa_offset = ARG_POINTER_CFA_OFFSET;
 
   /* Scan all variables and parameters of this function.  For each that is
      in memory, instantiate all virtual registers if the result is a valid
@@ -3143,6 +3152,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
        new = stack_pointer_rtx, offset = - dynamic_offset;
       else if (SET_DEST (x) == virtual_outgoing_args_rtx)
        new = stack_pointer_rtx, offset = - out_arg_offset;
+      else if (SET_DEST (x) == virtual_cfa_rtx)
+       new = arg_pointer_rtx, offset = - cfa_offset;
 
       if (new)
        {
@@ -3194,6 +3205,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
                new = stack_pointer_rtx, offset = dynamic_offset;
              else if (inner == virtual_outgoing_args_rtx)
                new = stack_pointer_rtx, offset = out_arg_offset;
+             else if (inner == virtual_cfa_rtx)
+               new = arg_pointer_rtx, offset = cfa_offset;
              else
                {
                  loc = &XEXP (x, 0);
@@ -3213,6 +3226,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
            new = stack_pointer_rtx, offset = dynamic_offset;
          else if (XEXP (x, 0) == virtual_outgoing_args_rtx)
            new = stack_pointer_rtx, offset = out_arg_offset;
+          else if (XEXP (x, 0) == virtual_cfa_rtx)
+            new = arg_pointer_rtx, offset = cfa_offset;
          else
            {
              /* We know the second operand is a constant.  Unless the
@@ -3420,6 +3435,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
        new = stack_pointer_rtx, offset = dynamic_offset;
       else if (x == virtual_outgoing_args_rtx)
        new = stack_pointer_rtx, offset = out_arg_offset;
+      else if (x == virtual_cfa_rtx)
+        new = arg_pointer_rtx, offset = cfa_offset;
 
       if (new)
        {
@@ -5981,6 +5998,10 @@ expand_function_end (filename, line, end_bindings)
       use_variable (outgoing);
     }
 
+  /* If this is an implementation of __throw, do what's necessary to 
+     communicate between __builtin_eh_return and the epilogue.  */
+  expand_eh_return ();
+
   /* Output a return insn if we are using one.
      Otherwise, let the rtl chain end here, to drop through
      into the epilogue.  */
index 786e062a4872d7db2e75af0bf2780c62a21be499..06e90dc88aa34b759d7a097090b52922059e1c6f 100644 (file)
@@ -142,8 +142,6 @@ struct function
   rtx catch_clauses;
   struct label_node *false_label_stack;
   struct label_node *caught_return_label_stack;
-  rtx eh_stub_label;
-  rtx eh_old_stub_label;
   tree protect_list;
   rtx ehc;
 
index 6f2fcfd97962d5df6db871ce97cddd8c8604ddb5..821387b396040301f77a4500dca6f3a31ba52c97 100644 (file)
@@ -3492,31 +3492,71 @@ find_exception_handler (void *pc, exception_descriptor *table, void *eh_info)
 
 typedef int ptr_type __attribute__ ((mode (pointer)));
 
-/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
+#ifdef INCOMING_REGNO
+/* Is the saved value for register REG in frame UDATA stored in a register
+   window in the previous frame?  */
+
+/* ??? The Sparc INCOMING_REGNO references TARGET_FLAT.  This allows us
+   to use the macro here.  One wonders, though, that perhaps TARGET_FLAT
+   compiled functions won't work with the frame-unwind stuff here.  
+   Perhaps the entireity of in_reg_window should be conditional on having
+   seen a DW_CFA_GNU_window_save?  */
+#define target_flags 0
+
+static int
+in_reg_window (int reg, frame_state *udata)
+{
+  if (udata->saved[reg] == REG_SAVED_REG)
+    return INCOMING_REGNO (reg) == reg;
+  if (udata->saved[reg] != REG_SAVED_OFFSET)
+    return 0;
+
+#ifdef STACK_GROWS_DOWNWARD
+  return udata->reg_or_offset[reg] > 0;
+#else
+  return udata->reg_or_offset[reg] < 0;
+#endif
+}
+#else
+static inline int in_reg_window (int reg, frame_state *udata) { return 0; }
+#endif /* INCOMING_REGNO */
+
+/* Get the address of register REG as saved in UDATA, where SUB_UDATA is a
    frame called by UDATA or 0.  */
 
-static void*
-get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
+static word_type *
+get_reg_addr (unsigned reg, frame_state *udata, frame_state *sub_udata)
 {
+  while (udata->saved[reg] == REG_SAVED_REG)
+    {
+      reg = udata->reg_or_offset[reg];
+      if (in_reg_window (reg, udata))
+       {
+          udata = sub_udata;
+         sub_udata = NULL;
+       }
+    }
   if (udata->saved[reg] == REG_SAVED_OFFSET)
-    return (void *)(ptr_type)
-      *(word_type *)(udata->cfa + udata->reg_or_offset[reg]);
-  else if (udata->saved[reg] == REG_SAVED_REG && sub_udata)
-    return get_reg (udata->reg_or_offset[reg], sub_udata, 0);
+    return (word_type *)(udata->cfa + udata->reg_or_offset[reg]);
   else
     abort ();
 }
 
+/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
+   frame called by UDATA or 0.  */
+
+static inline void *
+get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
+{
+  return (void *)(ptr_type) *get_reg_addr (reg, udata, sub_udata);
+}
+
 /* Overwrite the saved value for register REG in frame UDATA with VAL.  */
 
-static void
+static inline void
 put_reg (unsigned reg, void *val, frame_state *udata)
 {
-  if (udata->saved[reg] == REG_SAVED_OFFSET)
-    *(word_type *)(udata->cfa + udata->reg_or_offset[reg])
-      = (word_type)(ptr_type) val;
-  else
-    abort ();
+  *get_reg_addr (reg, udata, NULL) = (word_type)(ptr_type) val;
 }
 
 /* Copy the saved value for register REG from frame UDATA to frame
@@ -3526,17 +3566,13 @@ put_reg (unsigned reg, void *val, frame_state *udata)
 static void
 copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
 {
-  if (udata->saved[reg] == REG_SAVED_OFFSET
-      && target_udata->saved[reg] == REG_SAVED_OFFSET)
-    memcpy (target_udata->cfa + target_udata->reg_or_offset[reg],
-           udata->cfa + udata->reg_or_offset[reg],
-           __builtin_dwarf_reg_size (reg));
-  else
-    abort ();
+  word_type *preg = get_reg_addr (reg, udata, NULL);
+  word_type *ptreg = get_reg_addr (reg, target_udata, NULL);
+
+  memcpy (ptreg, preg, __builtin_dwarf_reg_size (reg));
 }
 
-/* Retrieve the return address for frame UDATA, where SUB_UDATA is a
-   frame called by UDATA or 0.  */
+/* Retrieve the return address for frame UDATA.  */
 
 static inline void *
 get_return_addr (frame_state *udata, frame_state *sub_udata)
@@ -3576,24 +3612,6 @@ next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
   return caller_udata;
 }
 
-#ifdef INCOMING_REGNO
-/* Is the saved value for register REG in frame UDATA stored in a register
-   window in the previous frame?  */
-
-static int
-in_reg_window (int reg, frame_state *udata)
-{
-  if (udata->saved[reg] != REG_SAVED_OFFSET)
-    return 0;
-
-#ifdef STACK_GROWS_DOWNWARD
-  return udata->reg_or_offset[reg] > 0;
-#else
-  return udata->reg_or_offset[reg] < 0;
-#endif
-}
-#endif /* INCOMING_REGNO */
-
 /* We first search for an exception handler, and if we don't find
    it, we call __terminate on the current stack frame so that we may
    use the debugger to walk the stack and understand why no handler
@@ -3606,7 +3624,7 @@ void
 __throw ()
 {
   struct eh_context *eh = (*get_eh_context) ();
-  void *saved_pc, *pc, *handler, *retaddr;
+  void *saved_pc, *pc, *handler;
   frame_state ustruct, ustruct2;
   frame_state *udata = &ustruct;
   frame_state *sub_udata = &ustruct2;
@@ -3626,14 +3644,8 @@ label:
   if (! udata)
     __terminate ();
 
-  /* We need to get the value from the CFA register.  At this point in
-     compiling __throw we don't know whether or not we will use the frame
-     pointer register for the CFA, so we check our unwind info.  */
-  if (udata->cfa_reg == __builtin_dwarf_fp_regnum ())
-    udata->cfa = __builtin_fp ();
-  else
-    udata->cfa = __builtin_sp ();
-  udata->cfa += udata->cfa_offset;
+  /* We need to get the value from the CFA register. */
+  udata->cfa = __builtin_dwarf_cfa ();
 
   memcpy (my_udata, udata, sizeof (*udata));
 
@@ -3712,7 +3724,6 @@ label:
          for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
            if (i != udata->retaddr_column && udata->saved[i])
              {
-#ifdef INCOMING_REGNO
                /* If you modify the saved value of the return address
                   register on the SPARC, you modify the return address for
                   your caller's frame.  Don't do that here, as it will
@@ -3721,14 +3732,12 @@ label:
                    && udata->saved[udata->retaddr_column] == REG_SAVED_REG
                    && udata->reg_or_offset[udata->retaddr_column] == i)
                  continue;
-#endif
                copy_reg (i, udata, my_udata);
              }
 
          pc = get_return_addr (udata, sub_udata) - 1;
        }
 
-#ifdef INCOMING_REGNO
       /* But we do need to update the saved return address register from
         the last frame we unwind, or the handler frame will have the wrong
         return address.  */
@@ -3738,42 +3747,17 @@ label:
          if (in_reg_window (i, udata))
            copy_reg (i, udata, my_udata);
        }
-#endif
     }
-  /* udata now refers to the frame called by the handler frame.  */
 
-  /* Emit the stub to adjust sp and jump to the handler.  */
-  if (new_exception_model)
-    retaddr = __builtin_eh_stub ();
-  else
-    retaddr =  __builtin_eh_stub_old ();
-
-  /* And then set our return address to point to the stub.  */
-  if (my_udata->saved[my_udata->retaddr_column] == REG_SAVED_OFFSET)
-    put_return_addr (retaddr, my_udata);
-  else
-    __builtin_set_return_addr_reg (retaddr);
-
-  /* Set up the registers we use to communicate with the stub.
-     We check STACK_GROWS_DOWNWARD so the stub can use adjust_stack.  */
-
-  if (new_exception_model)
-    __builtin_set_eh_regs ((void *)eh,
-#ifdef STACK_GROWS_DOWNWARD
-                        udata->cfa - my_udata->cfa
-#else
-                        my_udata->cfa - udata->cfa
-#endif
-                        + args_size);
-  else
-    __builtin_set_eh_regs (handler,
+  /* Now go!  */
 
+  __builtin_eh_return ((void *)eh,
 #ifdef STACK_GROWS_DOWNWARD
-                        udata->cfa - my_udata->cfa
+                      udata->cfa - my_udata->cfa,
 #else
-                        my_udata->cfa - udata->cfa
+                      my_udata->cfa - udata->cfa,
 #endif
-                        + args_size);
+                      handler);
 
   /* Epilogue:  restore the handler frame's register values and return
      to the stub.  */
index eac66714e45c6cbc8b918aeb5468cb9f8a699f5f..e72fd60259677670cd7b25d6a467418e40843f40 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1055,6 +1055,7 @@ extern struct _global_rtl
   struct rtx_def virtual_stack_vars_val;
   struct rtx_def virtual_stack_dynamic_val;
   struct rtx_def virtual_outgoing_args_val;
+  struct rtx_def virtual_cfa_val;
 } global_rtl;
 
 /* All references to certain hard regs, except those created
@@ -1159,7 +1160,17 @@ extern rtx gen_rtx_MEM PROTO((enum machine_mode, rtx));
 
 #define VIRTUAL_OUTGOING_ARGS_REGNUM   ((FIRST_VIRTUAL_REGISTER) + 3)
 
-#define LAST_VIRTUAL_REGISTER  ((FIRST_VIRTUAL_REGISTER) + 3)
+/* This points to the Canonical Frame Address of the function.  This
+   should corrospond to the CFA produced by INCOMING_FRAME_SP_OFFSET,
+   but is calculated relative to the arg pointer for simplicity; the
+   frame pointer nor stack pointer are necessarily fixed relative to 
+   the CFA until after reload.  */
+
+#define virtual_cfa_rtx                        (&global_rtl.virtual_cfa_val)
+
+#define VIRTUAL_CFA_REGNUM             ((FIRST_VIRTUAL_REGISTER) + 4)
+
+#define LAST_VIRTUAL_REGISTER          ((FIRST_VIRTUAL_REGISTER) + 4)
 
 extern rtx find_next_ref               PROTO((rtx, rtx));
 extern rtx *find_single_use            PROTO((rtx, rtx, rtx *));
index bf6fdd155b1ef00403dc359b5a67a8efa8ef67e0..ea3e8b3110a97e89e5669a4082be7599a3e85a2e 100644 (file)
@@ -2275,6 +2275,17 @@ frame at the beginning of any function, before the prologue.  The top of
 the frame is defined to be the value of the stack pointer in the
 previous frame, just before the call instruction.
 
+You only need to define this macro if you want to support call frame
+debugging information like that provided by DWARF 2.
+
+@findex ARG_POINTER_CFA_OFFSET
+@item ARG_POINTER_CFA_OFFSET
+A C expression whose value is an integer giving the offset, in bytes,
+from the argument pointer to the canonical frame address (cfa).  The
+final value should coincide with that calculated by 
+@code{INCOMING_FRAME_SP_OFFSET}.  Which is unfortunately not usable
+during virtual register instantiation.
+
 You only need to define this macro if you want to support call frame
 debugging information like that provided by DWARF 2.
 @end table
index aee712fc97fdf24d4d0ecd415eb440c39b76b702..58293e49d5e71c5da5e8541c4c013ca36457404c 100644 (file)
@@ -101,7 +101,6 @@ enum built_in_function
   BUILT_IN_FRAME_ADDRESS,
   BUILT_IN_RETURN_ADDRESS,
   BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
-  BUILT_IN_CALLER_RETURN_ADDRESS,
   BUILT_IN_APPLY_ARGS,
   BUILT_IN_APPLY,
   BUILT_IN_RETURN,
@@ -110,16 +109,13 @@ enum built_in_function
   BUILT_IN_TRAP,
 
   /* Various hooks for the DWARF 2 __throw routine.  */
-  BUILT_IN_FP, BUILT_IN_SP,
   BUILT_IN_UNWIND_INIT,
+  BUILT_IN_DWARF_CFA,
   BUILT_IN_DWARF_FP_REGNUM,
   BUILT_IN_DWARF_REG_SIZE,
   BUILT_IN_FROB_RETURN_ADDR,
   BUILT_IN_EXTRACT_RETURN_ADDR,
-  BUILT_IN_SET_RETURN_ADDR_REG,
-  BUILT_IN_EH_STUB_OLD,
-  BUILT_IN_EH_STUB,
-  BUILT_IN_SET_EH_REGS,
+  BUILT_IN_EH_RETURN,
 
   /* C++ extensions */
   BUILT_IN_NEW,