]> gcc.gnu.org Git - gcc.git/commitdiff
Implement dwarf2 exception handling for the ARM.
authorJason Merrill <jason@casey.cygnus.com>
Thu, 23 Mar 2000 00:29:55 +0000 (00:29 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 23 Mar 2000 00:29:55 +0000 (19:29 -0500)
        * config/arm/arm.h (INCOMING_RETURN_ADDR_RTX): Define.
        (DWARF_FRAME_RETURN_COLUMN): Define.
        * config/arm/arm.c (emit_multi_reg_push): Return rtx.  Attach
        REG_FRAME_RELATED_EXPR note.
        (emit_sfm): Likewise.
        (arm_expand_prologue): Set RTX_FRAME_RELATED_P on everything.
        * dwarf2out.c (reg_save): Handle saving a register to itself.
        (dwarf2out_frame_debug_expr): Handle an intermediate cfa reg.
        * except.c (eh_regs): Don't use the static chain reg if it's
        callee-saved.
        * frame.h (frame_state): Add cfa_saved field.
        * frame.c (execute_cfa_insn): Set it.
        * libgcc2.c (throw_helper): Don't adjust sp if it's restored in
        the epilogue.
        * function.c (ARG_POINTER_CFA_OFFSET): Default to FIRST_PARM_OFFSET.
        Now takes a parm.
        (instantiate_virtual_regs): Adjust.
        * tm.texi: Adjust.
        * config/m68k/m68k.h (ARG_POINTER_CFA_OFFSET): Don't define.
        * config/ns32k/ns32k.h (ARG_POINTER_CFA_OFFSET): Don't define.
        * config/sparc/sparc.h (ARG_POINTER_CFA_OFFSET): Take a parm.

        * dwarf2out.c (reg_number): Refer to FIRST_PSEUDO_REGISTER.
        (initial_return_save): Use DWARF_FRAME_REGNUM, not reg_number.

From-SVN: r32696

13 files changed:
gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/m68k/m68k.h
gcc/config/ns32k/ns32k.h
gcc/config/sparc/sparc.h
gcc/dwarf2out.c
gcc/except.c
gcc/frame.c
gcc/frame.h
gcc/function.c
gcc/libgcc2.c
gcc/tm.texi

index fddb52ad9c80a373ffb1d9b31a5da7a03d8a3c38..9a386b0e3bbac63ea1ec21b0e0dcaabdd5a6d26f 100644 (file)
@@ -1,3 +1,36 @@
+2000-03-22  Jason Merrill  <jason@casey.cygnus.com>
+
+       * config/rs6000/rs6000.h (DWARF_FRAME_RETURN_COLUMN): Define.
+       * config/alpha/alpha.h (DWARF_FRAME_RETURN_COLUMN): Define.
+       * config/sparc/sparc.h (DWARF_FRAME_RETURN_COLUMN): Define.
+       * dwarf2out.c (throw_helper): Adjust.
+
+       Implement dwarf2 exception handling for the ARM.
+       * config/arm/arm.h (INCOMING_RETURN_ADDR_RTX): Define.
+       (DWARF_FRAME_RETURN_COLUMN): Define.
+       * config/arm/arm.c (emit_multi_reg_push): Return rtx.  Attach
+       REG_FRAME_RELATED_EXPR note.
+       (emit_sfm): Likewise.
+       (arm_expand_prologue): Set RTX_FRAME_RELATED_P on everything.
+       * dwarf2out.c (reg_save): Handle saving a register to itself.
+       (dwarf2out_frame_debug_expr): Handle an intermediate cfa reg.
+       * except.c (eh_regs): Don't use the static chain reg if it's
+       callee-saved.
+       * frame.h (frame_state): Add cfa_saved field.
+       * frame.c (execute_cfa_insn): Set it.
+       * libgcc2.c (throw_helper): Don't adjust sp if it's restored in 
+       the epilogue.
+       * function.c (ARG_POINTER_CFA_OFFSET): Default to FIRST_PARM_OFFSET.
+       Now takes a parm.
+       (instantiate_virtual_regs): Adjust.
+       * tm.texi: Adjust.
+       * config/m68k/m68k.h (ARG_POINTER_CFA_OFFSET): Don't define.
+       * config/ns32k/ns32k.h (ARG_POINTER_CFA_OFFSET): Don't define.
+       * config/sparc/sparc.h (ARG_POINTER_CFA_OFFSET): Take a parm.
+
+       * dwarf2out.c (reg_number): Refer to FIRST_PSEUDO_REGISTER.
+       (initial_return_save): Use DWARF_FRAME_REGNUM, not reg_number.
+
 2000-03-22  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * builtins.def: New file.
index 6051cd1781a92a6d3e05f7b6a50d465b81d3c618..3177a64e5ea7bf7f3edac78d48bce462351f5eaf 100644 (file)
@@ -64,8 +64,8 @@ static int eliminate_lr2ip            PARAMS ((rtx *));
 static char * shift_op                         PARAMS ((rtx, HOST_WIDE_INT *));
 static int pattern_really_clobbers_lr  PARAMS ((rtx));
 static int function_really_clobbers_lr         PARAMS ((rtx));
-static void emit_multi_reg_push        PARAMS ((int));
-static void emit_sfm                   PARAMS ((int, int));
+static rtx emit_multi_reg_push         PARAMS ((int));
+static rtx emit_sfm                    PARAMS ((int, int));
 static enum arm_cond_code get_arm_condition_code PARAMS ((rtx));
 static int const_ok_for_op             PARAMS ((HOST_WIDE_INT, enum rtx_code));
 static void arm_add_gc_roots           PARAMS ((void));
@@ -6268,13 +6268,20 @@ output_func_epilogue (frame_size)
   after_arm_reorg = 0;
 }
 
-static void
+/* Generate and emit an insn that we will recognize as a push_multi.
+   Unfortunately, since this insn does not reflect very well the actual
+   semantics of the operation, we need to annotate the insn for the benefit
+   of DWARF2 frame unwind information.  */
+
+static rtx
 emit_multi_reg_push (mask)
      int mask;
 {
   int num_regs = 0;
   int i, j;
   rtx par;
+  rtx dwarf;
+  rtx tmp, reg;
 
   for (i = 0; i < 16; i++)
     if (mask & (1 << i))
@@ -6284,20 +6291,32 @@ emit_multi_reg_push (mask)
     abort ();
 
   par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs));
+  dwarf = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs));
+  RTX_FRAME_RELATED_P (dwarf) = 1;
 
   for (i = 0; i < 16; i++)
     {
       if (mask & (1 << i))
        {
+         reg = gen_rtx_REG (SImode, i);
+
          XVECEXP (par, 0, 0)
            = gen_rtx_SET (VOIDmode,
                           gen_rtx_MEM (BLKmode,
                                        gen_rtx_PRE_DEC (BLKmode,
                                                         stack_pointer_rtx)),
                           gen_rtx_UNSPEC (BLKmode,
-                                          gen_rtvec (1,
-                                                     gen_rtx_REG (SImode, i)),
+                                          gen_rtvec (1, reg),
                                           2));
+
+         tmp = gen_rtx_SET (VOIDmode,
+                            gen_rtx_MEM (SImode,
+                                         gen_rtx_PRE_DEC (BLKmode,
+                                                          stack_pointer_rtx)),
+                            reg);
+         RTX_FRAME_RELATED_P (tmp) = 1;
+         XVECEXP (dwarf, 0, num_regs - 1) = tmp;         
+
          break;
        }
     }
@@ -6306,38 +6325,77 @@ emit_multi_reg_push (mask)
     {
       if (mask & (1 << i))
        {
-         XVECEXP (par, 0, j)
-           = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, i));
+         reg = gen_rtx_REG (SImode, i);
+
+         XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);
+
+         tmp = gen_rtx_SET (VOIDmode,
+                            gen_rtx_MEM (SImode,
+                                         gen_rtx_PRE_DEC (BLKmode,
+                                                          stack_pointer_rtx)),
+                            reg);
+         RTX_FRAME_RELATED_P (tmp) = 1;
+         XVECEXP (dwarf, 0, num_regs - j - 1) = tmp;
+                          
          j++;
        }
     }
 
-  emit_insn (par);
+  par = emit_insn (par);
+  REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+                                      REG_NOTES (par));
+  return par;
 }
 
-static void
+static rtx
 emit_sfm (base_reg, count)
      int base_reg;
      int count;
 {
   rtx par;
+  rtx dwarf;
+  rtx tmp, reg;
   int i;
 
   par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+  dwarf = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+  RTX_FRAME_RELATED_P (dwarf) = 1;
+
+  reg = gen_rtx_REG (XFmode, base_reg++);
 
   XVECEXP (par, 0, 0)
     = gen_rtx_SET (VOIDmode, 
                   gen_rtx_MEM (BLKmode,
                                gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)),
                   gen_rtx_UNSPEC (BLKmode,
-                                  gen_rtvec (1, gen_rtx_REG (XFmode, 
-                                                             base_reg++)),
+                                  gen_rtvec (1, reg),
                                   2));
+  tmp
+    = gen_rtx_SET (VOIDmode, 
+                  gen_rtx_MEM (XFmode,
+                               gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)),
+                  reg);
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (dwarf, 0, count - 1) = tmp;   
+  
   for (i = 1; i < count; i++)
-    XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, 
-                                      gen_rtx_REG (XFmode, base_reg++));
+    {
+      reg = gen_rtx_REG (XFmode, base_reg++);
+      XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, reg);
+
+      tmp = gen_rtx_SET (VOIDmode, 
+                        gen_rtx_MEM (XFmode,
+                                     gen_rtx_PRE_DEC (BLKmode,
+                                                      stack_pointer_rtx)),
+                        reg);
+      RTX_FRAME_RELATED_P (tmp) = 1;
+      XVECEXP (dwarf, 0, count - i - 1) = tmp;   
+    }
 
-  emit_insn (par);
+  par = emit_insn (par);
+  REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+                                      REG_NOTES (par));
+  return par;
 }
 
 void
@@ -6352,6 +6410,7 @@ arm_expand_prologue ()
      the call-saved regs.  */
   int volatile_func = (optimize > 0
                       && TREE_THIS_VOLATILE (current_function_decl));
+  rtx insn;
 
   /* Naked functions don't have prologues.  */
   if (arm_naked_function_p (current_function_decl))
@@ -6376,18 +6435,21 @@ arm_expand_prologue ()
   if (frame_pointer_needed)
     {
       live_regs_mask |= 0xD800;
-      emit_insn (gen_movsi (gen_rtx_REG (SImode, IP_REGNUM),
-                           stack_pointer_rtx));
+      insn = emit_insn (gen_movsi (gen_rtx_REG (SImode, IP_REGNUM),
+                                  stack_pointer_rtx));
+      RTX_FRAME_RELATED_P (insn) = 1;
     }
 
   if (current_function_pretend_args_size)
     {
       if (store_arg_regs)
-       emit_multi_reg_push ((0xf0 >> (current_function_pretend_args_size / 4))
-                            & 0xf);
+       insn = emit_multi_reg_push
+         ((0xf0 >> (current_function_pretend_args_size / 4)) & 0xf);
       else
-       emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, 
-                              GEN_INT (-current_function_pretend_args_size)));
+       insn = emit_insn
+         (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, 
+                      GEN_INT (-current_function_pretend_args_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
     }
 
   if (live_regs_mask)
@@ -6395,10 +6457,11 @@ arm_expand_prologue ()
       /* If we have to push any regs, then we must push lr as well, or
         we won't get a proper return.  */
       live_regs_mask |= 1 << LR_REGNUM;
-      emit_multi_reg_push (live_regs_mask);
+      insn = emit_multi_reg_push (live_regs_mask);
+      RTX_FRAME_RELATED_P (insn) = 1;
     }
       
-  /* For now the integer regs are still pushed in output_func_epilogue ().  */
+  /* And now the floating point regs.  */
 
   if (! volatile_func)
     {
@@ -6406,12 +6469,13 @@ arm_expand_prologue ()
        {
          for (reg = 23; reg > 15; reg--)
            if (regs_ever_live[reg] && ! call_used_regs[reg])
-             emit_insn (gen_rtx_SET
-                        (VOIDmode, 
-                         gen_rtx_MEM (XFmode, 
-                                      gen_rtx_PRE_DEC (XFmode,
-                                                       stack_pointer_rtx)),
-                         gen_rtx_REG (XFmode, reg)));
+             {
+               insn = gen_rtx_PRE_DEC (XFmode, stack_pointer_rtx);
+               insn = gen_rtx_MEM (XFmode, insn);
+               insn = emit_insn (gen_rtx_SET (VOIDmode, insn,
+                                              gen_rtx_REG (XFmode, reg)));
+               RTX_FRAME_RELATED_P (insn) = 1;
+             }
        }
       else
        {
@@ -6423,31 +6487,44 @@ arm_expand_prologue ()
                {
                  if (start_reg - reg == 3)
                    {
-                     emit_sfm (reg, 4);
+                     insn = emit_sfm (reg, 4);
+                     RTX_FRAME_RELATED_P (insn) = 1;
                      start_reg = reg - 1;
                    }
                }
              else
                {
                  if (start_reg != reg)
-                   emit_sfm (reg + 1, start_reg - reg);
+                   {
+                     insn = emit_sfm (reg + 1, start_reg - reg);
+                     RTX_FRAME_RELATED_P (insn) = 1;
+                   }
                  start_reg = reg - 1;
                }
            }
 
          if (start_reg != reg)
-           emit_sfm (reg + 1, start_reg - reg);
+           {
+             insn = emit_sfm (reg + 1, start_reg - reg);
+             RTX_FRAME_RELATED_P (insn) = 1;
+           }
        }
     }
 
   if (frame_pointer_needed)
-    emit_insn (gen_addsi3 (hard_frame_pointer_rtx, gen_rtx_REG (SImode, IP_REGNUM),
-                          (GEN_INT
-                           (-(4 + current_function_pretend_args_size)))));
+    {
+      insn = GEN_INT (-(4 + current_function_pretend_args_size));
+      insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
+                                   gen_rtx_REG (SImode, IP_REGNUM),
+                                   insn));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
   if (amount != const0_rtx)
     {
-      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, amount));
+      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+                                   amount));
+      RTX_FRAME_RELATED_P (insn) = 1;
       emit_insn (gen_rtx_CLOBBER (VOIDmode, 
                                  gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
     }
index 23b5d887fe8b47cdc9fb1fad2353e28ac4cdfc1c..b748b745002434e4f842926558dfb7c2275ef226 100644 (file)
@@ -2275,6 +2275,13 @@ extern struct rtx_def * arm_compare_op1;
    ? gen_rtx_MEM (Pmode, plus_constant (FRAME, -4)) \
    : NULL_RTX)
 
+/* Pick up the return address upon entry to a procedure. Used for
+   dwarf2 unwind information.  This also enables the table driven
+   mechanism.  */
+
+#define INCOMING_RETURN_ADDR_RTX       gen_rtx_REG (Pmode, LR_REGNUM)
+#define DWARF_FRAME_RETURN_COLUMN      DWARF_FRAME_REGNUM (LR_REGNUM)
+
 /* Used to mask out junk bits from the return address, such as
    processor state, interrupt status, condition codes and the like.  */
 #define MASK_RETURN_ADDR \
index 9c5cd8258de86e7344e83983b4c3f0607db63c6f..5d170429bf0d94759f708f4fed4ed3b4cbf57ced 100644 (file)
@@ -925,9 +925,6 @@ 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 ac984c327308cb73c6d01015d222c1e073b4f86e..4a0bf43d69de63437dc1b5a4c238dcf797732a76 100644 (file)
@@ -552,9 +552,6 @@ enum reg_class
 
 #define INCOMING_FRAME_SP_OFFSET 4
 
-/* Offset of the CFA from the argument pointer register value.  */
-#define ARG_POINTER_CFA_OFFSET 8
-
 /* If we generate an insn to push BYTES bytes,
    this says how many the stack pointer really advances by.
    On the 32000, sp@- in a byte insn really pushes a BYTE.  */
index 1f8b61f6d9fa3e4f9362322be319e16f2cd0c573..0da6cd6a9c4de8dffeae441ad3045c2bb2237c93 100644 (file)
@@ -1603,9 +1603,11 @@ 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.  */
+/* Offset from the argument pointer register value to the CFA.
+   This is different from FIRST_PARM_OFFSET because the register window
+   comes between the CFA and the arguments.  */
 
-#define ARG_POINTER_CFA_OFFSET  SPARC_STACK_BIAS
+#define ARG_POINTER_CFA_OFFSET(FNDECL)  SPARC_STACK_BIAS
 
 /* When a parameter is passed in a register, stack space is still
    allocated for it.
index fb4679c477376a0e9e45e22b5531f961738ec497..f181f26b056f99ba30ca707010d6dac1f996cf09 100644 (file)
@@ -559,7 +559,7 @@ reg_number (rtl)
 {
   register unsigned regno = REGNO (rtl);
 
-  if (regno >= DWARF_FRAME_REGISTERS)
+  if (regno >= FIRST_PSEUDO_REGISTER)
     {
       warning ("internal regno botch: regno = %d\n", regno);
       regno = 0;
@@ -882,6 +882,9 @@ reg_save (label, reg, sreg, offset)
        }
       cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
     }
+  else if (sreg == reg)
+    /* We could emit a DW_CFA_same_value in this case, but don't bother.  */
+    return;
   else
     {
       cfi->dw_cfi_opc = DW_CFA_register;
@@ -975,7 +978,7 @@ initial_return_save (rtl)
     {
     case REG:
       /* RA is in a register.  */
-      reg = reg_number (rtl);
+      reg = DWARF_FRAME_REGNUM (REGNO (rtl));
       break;
     case MEM:
       /* RA is on the stack.  */
@@ -1174,10 +1177,11 @@ dwarf2out_frame_debug_expr (expr, label)
         case REG:
           if (cfa_reg != (unsigned) REGNO (src))
             abort ();
-          if (REGNO (dest) != STACK_POINTER_REGNUM
-             && !(frame_pointer_needed
-                  && REGNO (dest) == HARD_FRAME_POINTER_REGNUM))
-            abort ();
+
+         /* We used to require that dest be either SP or FP, but the
+            ARM copies SP to a temporary register, and from there to
+            FP.  So we just rely on the backends to only set
+            RTX_FRAME_RELATED_P on appropriate insns.  */
           cfa_reg = REGNO (dest);
           break;
 
@@ -1221,32 +1225,19 @@ dwarf2out_frame_debug_expr (expr, label)
             {
              /* Either setting the FP from an offset of the SP,
                 or adjusting the FP */
-             if (! frame_pointer_needed
-                 || REGNO (dest) != HARD_FRAME_POINTER_REGNUM)
+             if (! frame_pointer_needed)
                abort ();
 
-             if (XEXP (src, 0) == stack_pointer_rtx
+             if (GET_CODE (XEXP (src, 0)) == REG
+                 && (unsigned) REGNO (XEXP (src, 0)) == cfa_reg
                  && GET_CODE (XEXP (src, 1)) == CONST_INT)
                {
-                 if (cfa_reg != STACK_POINTER_REGNUM)
-                   abort ();
                  offset = INTVAL (XEXP (src, 1));
                  if (GET_CODE (src) == PLUS)
                    offset = -offset;
                  cfa_offset += offset;
                  cfa_reg = HARD_FRAME_POINTER_REGNUM;
                }
-             else if (XEXP (src, 0) == hard_frame_pointer_rtx
-                      && GET_CODE (XEXP (src, 1)) == CONST_INT)
-               {
-                 if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
-                   abort ();
-                 offset = INTVAL (XEXP (src, 1));
-                 if (GET_CODE (src) == PLUS)
-                   offset = -offset;
-                 cfa_offset += offset;
-               }
-
              else 
                abort();
             }
index 31467783b15efed4b15d88210c3a94d182ec09ec..7cf64cccd02c88e16ccf54d593d8e8cc72aae5e5 100644 (file)
@@ -2910,9 +2910,10 @@ expand_builtin_frob_return_addr (addr_tree)
    The first passes the exception context to the handler.  For this
    we use the return value register for a void*.
 
-   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.
+   The second holds the stack pointer value to be restored.  For this
+   we use the static chain register if it exists, is different from
+   the previous, and is call-clobbered; otherwise some arbitrary
+   call-clobbered register.
 
    The third holds the address of the handler itself.  Here we use
    some arbitrary call-clobbered register.  */
@@ -2939,7 +2940,8 @@ eh_regs (pcontext, psp, pra, outgoing)
     rsp = static_chain_incoming_rtx;
   else
     rsp = static_chain_rtx;
-  if (REGNO (rsp) == REGNO (rcontext))
+  if (REGNO (rsp) == REGNO (rcontext)
+      || ! call_used_regs [REGNO (rsp)])
 #endif /* STATIC_CHAIN_REGNUM */
     rsp = NULL_RTX;
 
index 79ba78ac149a9706cf3a385fe1701e8cf694f25d..688355a970d78d1f0ef2da95465534dffdca1790 100644 (file)
@@ -697,6 +697,8 @@ execute_cfa_insn (void *p, struct frame_state_internal *state,
       offset *= info->data_align;
       state->s.saved[reg] = REG_SAVED_OFFSET;
       state->s.reg_or_offset[reg] = offset;
+      if (reg == state->s.cfa_reg)
+       state->s.cfa_saved = 1;
     }
   else if (insn & DW_CFA_restore)
     {
@@ -728,6 +730,8 @@ execute_cfa_insn (void *p, struct frame_state_internal *state,
       offset *= info->data_align;
       state->s.saved[reg] = REG_SAVED_OFFSET;
       state->s.reg_or_offset[reg] = offset;
+      if (reg == state->s.cfa_reg)
+       state->s.cfa_saved = 1;
       break;
     case DW_CFA_restore_extended:
       p = decode_uleb128 (p, &reg);
index 330277c03f2390e652d234672f6a49bf62ac5f3a..ecaf6b08344ba6cd0c3b2a98b18457f28019edad 100644 (file)
@@ -1,6 +1,6 @@
 /* Header file for unwinding stack frames for exception handling.  */
 /* Compile this one with gcc.  */
-/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
    Contributed by Jason Merrill <jason@cygnus.com>.
 
 This file is part of GNU CC.
@@ -34,6 +34,7 @@ typedef struct frame_state
   long reg_or_offset[DWARF_FRAME_REGISTERS+1];
   unsigned short cfa_reg;
   unsigned short retaddr_column;
+  char cfa_saved;
   char saved[DWARF_FRAME_REGISTERS+1];
 } frame_state;
 
index 3308dbba564d5c8a6eef4ff82c5a93e293d734c9..ae04a5c604467856fce23162b874e6a37a36cad5 100644 (file)
@@ -2760,10 +2760,10 @@ static int cfa_offset;
 #endif
 #endif
 
-/* On a few machines, the CFA coincides with the arg pointer.  */
+/* On most machines, the CFA coincides with the first incoming parm.  */
 
 #ifndef ARG_POINTER_CFA_OFFSET
-#define ARG_POINTER_CFA_OFFSET 0
+#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL)
 #endif
 
 
@@ -3335,7 +3335,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;
+  cfa_offset = ARG_POINTER_CFA_OFFSET (fndecl);
 
   /* Scan all variables and parameters of this function.  For each that is
      in memory, instantiate all virtual registers if the result is a valid
index e2a852c185afc89c394b972fd796273a1efae91f..aafbe753339d67851f83e63e06615d659d887a54 100644 (file)
@@ -3679,6 +3679,7 @@ throw_helper (struct eh_context *eh, void *pc, frame_state *my_udata,
   void *handler;
   void *handler_p = 0;
   void *pc_p = 0;
+  void *restored_cfa = 0;
   frame_state saved_ustruct;
   int new_eh_model;
   int cleanup = 0;
@@ -3788,6 +3789,11 @@ throw_helper (struct eh_context *eh, void *pc, frame_state *my_udata,
       pc = saved_pc;
       memcpy (udata, my_udata, sizeof (*udata));
 
+      if (udata->cfa_saved)
+       /* We saved the CFA register into the stack in this frame, so we
+          will restore it in the __throw epilogue.  Remember the value.  */
+       restored_cfa = udata->cfa;
+
       while (pc != handler_pc)
        {
          frame_state *p = udata;
@@ -3808,6 +3814,9 @@ throw_helper (struct eh_context *eh, void *pc, frame_state *my_udata,
                copy_reg (i, udata, my_udata);
              }
 
+         if (udata->cfa_saved)
+           restored_cfa = udata->cfa;
+
          pc = get_return_addr (udata, sub_udata) - 1;
        }
 
@@ -3823,6 +3832,13 @@ throw_helper (struct eh_context *eh, void *pc, frame_state *my_udata,
     }
   /* udata now refers to the frame called by the handler frame.  */
 
+  if (my_udata->cfa_saved)
+    /* If we saved the CFA register into the stack (after it became the
+       CFA register), we'll restore that value into SP in the epilogue,
+       as on the ARM.  So calculate the adjustment based on the value that
+       will be restored.  */
+    my_udata->cfa = restored_cfa;
+
   /* We adjust SP by the difference between __throw's CFA and the CFA for
      the frame called by the handler frame, because those CFAs correspond
      to the SP values at the two call sites.  We need to further adjust by
index 633281a091eda34ff7023ab6141448b4cf2b8fee..3a1b9ebebf4d6518d2e533306b82d0f729939f48 100644 (file)
@@ -2292,6 +2292,9 @@ the stack.
 You only need to define this macro if you want to support call frame
 debugging information like that provided by DWARF 2.
 
+If this RTL is a @code{REG}, you should also define
+DWARF_FRAME_RETURN_COLUMN to @code{DWARF_FRAME_REGNUM (REGNO)}.
+
 @findex INCOMING_FRAME_SP_OFFSET
 @item INCOMING_FRAME_SP_OFFSET
 A C expression whose value is an integer giving the offset, in bytes,
@@ -2304,15 +2307,20 @@ 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
+@item ARG_POINTER_CFA_OFFSET (@var{fundecl})
 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.
+The default value for this macro is @code{FIRST_PARM_OFFSET (fundecl)},
+which is correct for most machines; in general, the arguments are found
+immediately before the stack frame.  See @file{function.c} for details.
+
+You only need to define this macro if this default is incorrect, and you
+want to support call frame debugging information like that provided by
+DWARF 2.
 
 @findex SMALL_STACK
 @item SMALL_STACK
This page took 0.1636 seconds and 5 git commands to generate.