dwarf2out.c (dw_cfi_oprnd_struct): Reduce dw_cfi_reg_num to int.
authorRichard Henderson <rth@redhat.com>
Fri, 18 Nov 2005 01:19:10 +0000 (17:19 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 18 Nov 2005 01:19:10 +0000 (17:19 -0800)
        * dwarf2out.c (dw_cfi_oprnd_struct): Reduce dw_cfi_reg_num to int.
        (lookup_cfa_1): Apply data alignment to DW_CFA_def_cfa_offset_sf
        and DW_CFA_def_cfa_sf.
        (def_cfa_1): Use DW_CFA_def_cfa_offset_sf with negative values.
        (dbx_reg_number): Don't assert particular registers here.
        (based_loc_descr): ... do it here instead.  Fold in ...
        (eliminate_reg_to_offset): ... this function.
        (compute_frame_pointer_to_cfa_displacement): Fold in the effects
        of eliminate_reg_to_offset; use FRAME_POINTER_CFA_OFFSET.
        * unwind-dw2.c (execute_cfa_program): Apply data align factor
        to DW_CFA_def_cfa_offset_sf and DW_CFA_def_cfa_sf.
        * function.c (instantiate_new_reg): Use FRAME_POINTER_CFA_OFFSET.
        (instantiate_virtual_regs): Likewise.
        * var-tracking.c (adjust_stack_reference): Likewise.
        * doc/tm.texi (FRAME_POINTER_CFA_OFFSET): New.

From-SVN: r107154

gcc/ChangeLog
gcc/doc/tm.texi
gcc/dwarf2out.c
gcc/function.c
gcc/unwind-dw2.c
gcc/var-tracking.c

index 21a7e5d30a968a10912b1a87c3c06d03f9f6f968..ca612fb0fe624e91f3d1f5677981f5d8d142f9dc 100644 (file)
@@ -1,3 +1,21 @@
+2005-11-17  Richard Henderson  <rth@redhat.com>
+
+       * dwarf2out.c (dw_cfi_oprnd_struct): Reduce dw_cfi_reg_num to int.
+       (lookup_cfa_1): Apply data alignment to DW_CFA_def_cfa_offset_sf
+       and DW_CFA_def_cfa_sf.
+       (def_cfa_1): Use DW_CFA_def_cfa_offset_sf with negative values.
+       (dbx_reg_number): Don't assert particular registers here.
+       (based_loc_descr): ... do it here instead.  Fold in ...
+       (eliminate_reg_to_offset): ... this function.
+       (compute_frame_pointer_to_cfa_displacement): Fold in the effects
+       of eliminate_reg_to_offset; use FRAME_POINTER_CFA_OFFSET.
+       * unwind-dw2.c (execute_cfa_program): Apply data align factor
+       to DW_CFA_def_cfa_offset_sf and DW_CFA_def_cfa_sf.
+       * function.c (instantiate_new_reg): Use FRAME_POINTER_CFA_OFFSET.
+       (instantiate_virtual_regs): Likewise.
+       * var-tracking.c (adjust_stack_reference): Likewise.
+       * doc/tm.texi (FRAME_POINTER_CFA_OFFSET): New.
+
 2005-11-17  Bernd Schmidt  <bernd.schmidt@analog.com>
 
        * config/bfin/elf.h (STARTFILE_SPEC): Add "crtlibid%O%s"
index b339c4ccdc0554eee591015489e9148621f42d09..b229ee823ddc4f84afc146e4f9a0290aa59defa0 100644 (file)
@@ -2926,6 +2926,21 @@ want to support call frame debugging information like that provided by
 DWARF 2.
 @end defmac
 
+@defmac FRAME_POINTER_CFA_OFFSET (@var{fundecl})
+If defined, a C expression whose value is an integer giving the offset
+in bytes from the frame pointer to the canonical frame address (cfa).
+The final value should conincide with that calculated by
+@code{INCOMING_FRAME_SP_OFFSET}.
+
+Normally the CFA is calculated as an offset from the argument pointer,
+via @code{ARG_POINTER_CFA_OFFSET}, but if the argument pointer is 
+variable due to the ABI, this may not be possible.  If this macro is
+defined, it imples that the virtual register instantiation should be
+based on the frame pointer instead of the argument pointer.  Only one
+of @code{FRAME_POINTER_CFA_OFFSET} and @code{ARG_POINTER_CFA_OFFSET}
+should be defined.
+@end defmac
+
 @node Exception Handling
 @subsection Exception Handling Support
 @cindex exception handling
index f7a006e8980d41d6668f3cc3741aaa77bd5dc2e8..60a7d558084fb3f75cb73ee7cdb61b2581012bc4 100644 (file)
@@ -214,7 +214,7 @@ enum dw_cfi_oprnd_type {
 
 typedef union dw_cfi_oprnd_struct GTY(())
 {
-  unsigned long GTY ((tag ("dw_cfi_oprnd_reg_num"))) dw_cfi_reg_num;
+  unsigned int GTY ((tag ("dw_cfi_oprnd_reg_num"))) dw_cfi_reg_num;
   HOST_WIDE_INT GTY ((tag ("dw_cfi_oprnd_offset"))) dw_cfi_offset;
   const char * GTY ((tag ("dw_cfi_oprnd_addr"))) dw_cfi_addr;
   struct dw_loc_descr_struct * GTY ((tag ("dw_cfi_oprnd_loc"))) dw_cfi_loc;
@@ -671,6 +671,10 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc)
     case DW_CFA_def_cfa_offset:
       loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset;
       break;
+    case DW_CFA_def_cfa_offset_sf:
+      loc->offset
+       = cfi->dw_cfi_oprnd1.dw_cfi_offset * DWARF_CIE_DATA_ALIGNMENT;
+      break;
     case DW_CFA_def_cfa_register:
       loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
       break;
@@ -678,6 +682,11 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc)
       loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
       loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset;
       break;
+    case DW_CFA_def_cfa_sf:
+      loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
+      loc->offset
+       = cfi->dw_cfi_oprnd2.dw_cfi_offset * DWARF_CIE_DATA_ALIGNMENT;
+      break;
     case DW_CFA_def_cfa_expression:
       get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc);
       break;
@@ -775,11 +784,21 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p)
 
   if (loc.reg == old_cfa.reg && !loc.indirect)
     {
-      /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction,
-        indicating the CFA register did not change but the offset
-        did.  */
-      cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
-      cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset;
+      /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, indicating
+        the CFA register did not change but the offset did.  */
+      if (loc.offset < 0)
+       {
+         HOST_WIDE_INT f_offset = loc.offset / DWARF_CIE_DATA_ALIGNMENT;
+         gcc_assert (f_offset * DWARF_CIE_DATA_ALIGNMENT == loc.offset);
+
+         cfi->dw_cfi_opc = DW_CFA_def_cfa_offset_sf;
+         cfi->dw_cfi_oprnd1.dw_cfi_offset = f_offset;
+       }
+      else
+       {
+         cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
+         cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset;
+       }
     }
 
 #ifndef MIPS_DEBUGGING_INFO  /* SGI dbx thinks this means no offset.  */
@@ -800,9 +819,21 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p)
       /* Construct a "DW_CFA_def_cfa <register> <offset>" instruction,
         indicating the CFA register has changed to <register> with
         the specified offset.  */
-      cfi->dw_cfi_opc = DW_CFA_def_cfa;
-      cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
-      cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset;
+      if (loc.offset < 0)
+       {
+         HOST_WIDE_INT f_offset = loc.offset / DWARF_CIE_DATA_ALIGNMENT;
+         gcc_assert (f_offset * DWARF_CIE_DATA_ALIGNMENT == loc.offset);
+
+         cfi->dw_cfi_opc = DW_CFA_def_cfa_sf;
+         cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
+         cfi->dw_cfi_oprnd2.dw_cfi_offset = f_offset;
+       }
+      else
+       {
+         cfi->dw_cfi_opc = DW_CFA_def_cfa;
+         cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
+         cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset;
+       }
     }
   else
     {
@@ -8460,12 +8491,6 @@ dbx_reg_number (rtx rtl)
 {
   unsigned regno = REGNO (rtl);
 
-  /* We do not want to see registers that should have been eliminated.  */
-  gcc_assert (HARD_FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM
-             || rtl != arg_pointer_rtx);
-  gcc_assert (HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM
-             || rtl != frame_pointer_rtx);
-
   gcc_assert (regno < FIRST_PSEUDO_REGISTER);
 
 #ifdef LEAF_REG_REMAP
@@ -8619,32 +8644,12 @@ int_loc_descriptor (HOST_WIDE_INT i)
   return new_loc_descr (op, i, 0);
 }
 
-/* Return an offset from an eliminable register to the post-prologue
-   frame pointer.  */
-
-static HOST_WIDE_INT
-eliminate_reg_to_offset (rtx reg)
-{
-  HOST_WIDE_INT offset = 0;
-
-  reg = eliminate_regs (reg, VOIDmode, NULL_RTX);
-  if (GET_CODE (reg) == PLUS)
-    {
-      offset = INTVAL (XEXP (reg, 1));
-      reg = XEXP (reg, 0);
-    }
-  gcc_assert (reg == (frame_pointer_needed ? hard_frame_pointer_rtx
-                     : stack_pointer_rtx));
-
-  return offset;
-}
-
 /* Return a location descriptor that designates a base+offset location.  */
 
 static dw_loc_descr_ref
 based_loc_descr (rtx reg, HOST_WIDE_INT offset)
 {
-  dw_loc_descr_ref loc_result;
+  unsigned int regno;
 
   /* We only use "frame base" when we're sure we're talking about the
      post-prologue local stack frame.  We do this by *not* running
@@ -8652,22 +8657,28 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset)
      argument pointer and soft frame pointer rtx's.  */
   if (reg == arg_pointer_rtx || reg == frame_pointer_rtx)
     {
-      offset += eliminate_reg_to_offset (reg);
-      offset += frame_pointer_cfa_offset;
+      rtx elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
 
-      loc_result = new_loc_descr (DW_OP_fbreg, offset, 0);
-    }
-  else
-    {
-      unsigned int regno = dbx_reg_number (reg);
+      if (elim != reg)
+       {
+         if (GET_CODE (elim) == PLUS)
+           {
+             offset += INTVAL (XEXP (elim, 1));
+             elim = XEXP (elim, 0);
+           }
+         gcc_assert (elim == (frame_pointer_needed ? hard_frame_pointer_rtx
+                     : stack_pointer_rtx));
+          offset += frame_pointer_cfa_offset;
 
-      if (regno <= 31)
-       loc_result = new_loc_descr (DW_OP_breg0 + regno, offset, 0);
-      else
-       loc_result = new_loc_descr (DW_OP_bregx, regno, offset);
+          return new_loc_descr (DW_OP_fbreg, offset, 0);
+       }
     }
 
-  return loc_result;
+  regno = dbx_reg_number (reg);
+  if (regno <= 31)
+    return new_loc_descr (DW_OP_breg0 + regno, offset, 0);
+  else
+    return new_loc_descr (DW_OP_bregx, regno, offset);
 }
 
 /* Return true if this RTL expression describes a base+offset calculation.  */
@@ -10406,9 +10417,24 @@ static void
 compute_frame_pointer_to_cfa_displacement (void)
 {
   HOST_WIDE_INT offset;
+  rtx reg, elim;
+
+#ifdef FRAME_POINTER_CFA_OFFSET
+  reg = frame_pointer_rtx;
+  offset = FRAME_POINTER_CFA_OFFSET (current_function_decl);
+#else
+  reg = arg_pointer_rtx;
+  offset = ARG_POINTER_CFA_OFFSET (current_function_decl);
+#endif
 
-  offset = eliminate_reg_to_offset (arg_pointer_rtx);
-  offset += ARG_POINTER_CFA_OFFSET (current_function_decl);
+  elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
+  if (GET_CODE (elim) == PLUS)
+    {
+      offset += INTVAL (XEXP (elim, 1));
+      elim = XEXP (elim, 0);
+    }
+  gcc_assert (elim == (frame_pointer_needed ? hard_frame_pointer_rtx
+                      : stack_pointer_rtx));
 
   frame_pointer_cfa_offset = -offset;
 }
index dbf9df74ade0400397dec99cdf87b571b2428b85..c0339b8950e54b84fa2ea37feb10e9a014522de5 100644 (file)
@@ -1246,7 +1246,14 @@ instantiate_new_reg (rtx x, HOST_WIDE_INT *poffset)
   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;
+    {
+#ifdef FRAME_POINTER_CFA_OFFSET
+      new = frame_pointer_rtx;
+#else
+      new = arg_pointer_rtx;
+#endif
+      offset = cfa_offset;
+    }
   else
     return NULL_RTX;
 
@@ -1632,7 +1639,11 @@ instantiate_virtual_regs (void)
   var_offset = STARTING_FRAME_OFFSET;
   dynamic_offset = STACK_DYNAMIC_OFFSET (current_function_decl);
   out_arg_offset = STACK_POINTER_OFFSET;
+#ifdef FRAME_POINTER_CFA_OFFSET
+  cfa_offset = FRAME_POINTER_CFA_OFFSET (current_function_decl);
+#else
   cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl);
+#endif
 
   /* Initialize recognition, indicating that volatile is OK.  */
   init_recog ();
index 4626ec6d84cbe364441dcf54041ab6918110541a..930f02f37992003479123d4a757b504c744f30ab 100644 (file)
@@ -902,7 +902,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
          insn_ptr += utmp;
          break;
 
-         /* From the 2.1 draft.  */
+         /* From the dwarf3 draft.  */
        case DW_CFA_offset_extended_sf:
          insn_ptr = read_uleb128 (insn_ptr, &reg);
          insn_ptr = read_sleb128 (insn_ptr, &stmp);
@@ -916,10 +916,12 @@ execute_cfa_program (const unsigned char *insn_ptr,
          insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
          insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset);
          fs->cfa_how = CFA_REG_OFFSET;
+         fs->cfa_offset *= fs->data_align;
          break;
 
        case DW_CFA_def_cfa_offset_sf:
          insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset);
+         fs->cfa_offset *= fs->data_align;
          /* cfa_how deliberately not set.  */
          break;
 
index d69ca139c42457ef77520a2c9fc4bc757e21a0b1..fb4a1813218fe7d1e3bed25c16e220eb905de9c4 100644 (file)
@@ -557,8 +557,13 @@ adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment)
 {
   rtx addr, cfa, tmp;
 
+#ifdef FRAME_POINTER_CFA_OFFSET
+  adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl);
+  cfa = plus_constant (frame_pointer_rtx, adjustment);
+#else
   adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl);
   cfa = plus_constant (arg_pointer_rtx, adjustment);
+#endif
 
   addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa);
   tmp = simplify_rtx (addr);