OSDN Git Service

x
authormerrill <merrill@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 Dec 1996 01:31:47 +0000 (01:31 +0000)
committermerrill <merrill@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 Dec 1996 01:31:47 +0000 (01:31 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@13305 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/dwarf2out.c
gcc/final.c
gcc/rtl.h

index d0b3ac0..d9edb71 100644 (file)
@@ -1832,6 +1832,7 @@ ix86_expand_prologue ()
   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
                                  || current_function_uses_const_pool);
   long tsize = get_frame_size ();
+  rtx insn;
 
   if (!TARGET_SCHEDULE_PROLOGUE)
     return;
@@ -1841,17 +1842,23 @@ ix86_expand_prologue ()
   xops[2] = GEN_INT (tsize);
   if (frame_pointer_needed)
     {
-      emit_insn (gen_rtx (SET, 0,
-                         gen_rtx (MEM, SImode,
-                                  gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
-                         frame_pointer_rtx));
-      emit_move_insn (xops[1], xops[0]);
+      insn = emit_insn
+       (gen_rtx (SET, 0,
+                 gen_rtx (MEM, SImode,
+                          gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
+                 frame_pointer_rtx));
+      RTX_FRAME_RELATED_P (insn) = 1;
+      insn = emit_move_insn (xops[1], xops[0]);
+      RTX_FRAME_RELATED_P (insn) = 1;
     }
 
   if (tsize == 0)
     ;
   else if (! TARGET_STACK_PROBE || tsize < CHECK_STACK_LIMIT)
-    emit_insn (gen_subsi3 (xops[0], xops[0], xops[2]));
+    {
+      insn = emit_insn (gen_subsi3 (xops[0], xops[0], xops[2]));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
   else 
     {
       xops[3] = gen_rtx (REG, SImode, 0);
@@ -1877,10 +1884,13 @@ ix86_expand_prologue ()
        || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
       {
        xops[0] = gen_rtx (REG, SImode, regno);
-       emit_insn (gen_rtx (SET, 0,
-                           gen_rtx (MEM, SImode,
-                                    gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
-                         xops[0]));
+       insn = emit_insn
+         (gen_rtx (SET, 0,
+                   gen_rtx (MEM, SImode,
+                            gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
+                   xops[0]));
+       
+       RTX_FRAME_RELATED_P (insn) = 1;
       }
 
   if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION)
index 241650f..ac08c45 100644 (file)
@@ -2331,6 +2331,13 @@ number as al, and ax.
  (n) == 7 ? 5 : \
  (n) + 4)
 
+/* Before the prologue, RA is at 0(%esp).  */
+#define INCOMING_RETURN_ADDR_RTX \
+  gen_rtx (MEM, VOIDmode, gen_rtx (REG, VOIDmode, STACK_POINTER_REGNUM))
+
+/* PC is dbx register 8; let's use that column for RA. */
+#define DWARF_FRAME_RETURN_COLUMN      8
+
 /* This is how to output the definition of a user-level label named NAME,
    such as the label on a static function or variable NAME.  */
 
index c3a3b2d..cacbf1f 100644 (file)
@@ -5068,22 +5068,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
                  if (store_p)
                    {
                      rtx insn = emit_move_insn (mem_rtx, reg_rtx);
-
-                     if (write_symbols == DWARF2_DEBUG)
-                       {
-                         int offset = (gp_offset
-                                       - current_frame_info.total_size);
-                         if (regno == GP_REG_FIRST + 31)
-                           REG_NOTES (insn)
-                             = gen_rtx (EXPR_LIST, REG_RETURN_SAVE,
-                                        GEN_INT (offset), REG_NOTES (insn));
-                         else
-                           REG_NOTES (insn)
-                             = gen_rtx (EXPR_LIST, REG_SAVE,
-                                        gen_rtx (EXPR_LIST, VOIDmode, reg_rtx,
-                                                 GEN_INT (offset)),
-                                        REG_NOTES (insn));
-                       }
+                     RTX_FRAME_RELATED_P (insn) = 1;
                    }
                  else if (!TARGET_ABICALLS || mips_abi != ABI_32
                           || regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
@@ -5199,17 +5184,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
                  if (store_p)
                    {
                      rtx insn = emit_move_insn (mem_rtx, reg_rtx);
-
-                     if (write_symbols == DWARF2_DEBUG)
-                       {
-                         int offset = (gp_offset
-                                       - current_frame_info.total_size);
-                         REG_NOTES (insn)
-                           = gen_rtx (EXPR_LIST, REG_SAVE,
-                                      gen_rtx (EXPR_LIST, VOIDmode, reg_rtx,
-                                               GEN_INT (offset)),
-                                      REG_NOTES (insn));
-                       }
+                     RTX_FRAME_RELATED_P (insn) = 1;
                    }
                  else
                    emit_move_insn (reg_rtx, mem_rtx);
@@ -5452,12 +5427,7 @@ mips_expand_prologue ()
            insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
                                          tsize_rtx));
 
-         if (write_symbols == DWARF2_DEBUG)
-           REG_NOTES (insn)
-             = gen_rtx (EXPR_LIST, REG_FRAME,
-                        gen_rtx (PLUS, VOIDmode, stack_pointer_rtx,
-                                 GEN_INT (tsize)),
-                        REG_NOTES (insn));
+         RTX_FRAME_RELATED_P (insn) = 1;
        }
 
       save_restore_insns (TRUE, tmp_rtx, tsize, (FILE *)0);
@@ -5471,12 +5441,7 @@ mips_expand_prologue ()
          else
            insn= emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
 
-         if (write_symbols == DWARF2_DEBUG)
-           REG_NOTES (insn)
-             = gen_rtx (EXPR_LIST, REG_FRAME,
-                        gen_rtx (PLUS, VOIDmode, frame_pointer_rtx,
-                                 GEN_INT (tsize)),
-                        REG_NOTES (insn));
+         RTX_FRAME_RELATED_P (insn) = 1;
        }
 
       if (TARGET_ABICALLS && mips_abi != ABI_32)
index f1b4d05..9b430ab 100644 (file)
@@ -927,11 +927,16 @@ while (0)
    This mapping does not allow for tracking DBX register 0, since column 0
    is used for the frame address, but since register 0 is fixed this is
    not really a problem.  */
-#define DWARF_FRAME_REGNUM(REG) (DBX_REGISTER_NUMBER (REG))
+#define DWARF_FRAME_REGNUM(REG)                                \
+  (REG == GP_REG_FIRST + 31 ? DWARF_FRAME_RETURN_COLUMN        \
+   : DBX_REGISTER_NUMBER (REG))
 
 /* The DWARF 2 CFA column which tracks the return address.  */
 #define DWARF_FRAME_RETURN_COLUMN (FP_REG_LAST + 1)
 
+/* Before the prologue, RA lives in r31.  */
+#define INCOMING_RETURN_ADDR_RTX  gen_rtx (REG, VOIDmode, GP_REG_FIRST + 31)
+
 /* Overrides for the COFF debug format.  */
 #define PUT_SDB_SCL(a)                                 \
 do {                                                   \
index dd8276c..99007b3 100644 (file)
@@ -2,6 +2,7 @@
    Copyright (C) 1992, 1993, 1995, 1996 Free Software Foundation, Inc.
    Contributed by Gary Funck (gary@intrepid.com).  Derived from the
    DWARF 1 implementation written by Ron Guilmette (rfg@monkeys.com).
+   Extensively modified by Jason Merrill (jason@cygnus.com).
 
 This file is part of GNU CC.
 
@@ -23,6 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #ifdef DWARF2_DEBUGGING_INFO
 #include <stdio.h>
+#include <setjmp.h>
 #include "dwarf2.h"
 #include "tree.h"
 #include "flags.h"
@@ -67,7 +69,8 @@ typedef enum
     dw_val_class_loc,
     dw_val_class_const,
     dw_val_class_unsigned_const,
-    dw_val_class_double_const,
+    dw_val_class_long_long,
+    dw_val_class_float,
     dw_val_class_flag,
     dw_val_class_die_ref,
     dw_val_class_fde_ref,
@@ -95,12 +98,20 @@ typedef struct pubname_struct *pubname_ref;
 typedef dw_die_ref *arange_ref;
 
 /* Describe a double word constant value.  */
-typedef struct dw_double_const_struct
+typedef struct dw_long_long_struct
   {
-    unsigned long dw_dbl_hi;
-    unsigned long dw_dbl_low;
+    unsigned long hi;
+    unsigned long low;
   }
-dw_dbl_const;
+dw_long_long_const;
+
+/* Describe a floating point constant value.  */
+typedef struct dw_fp_struct
+  {
+    long *array;
+    unsigned length;
+  }
+dw_float_const;
 
 /* Each entry in the line_info_table maintains the file and
    line nuber associated with the label generated for that
@@ -134,7 +145,8 @@ typedef struct dw_val_struct
        dw_loc_descr_ref val_loc;
        long int val_int;
        long unsigned val_unsigned;
-       dw_dbl_const val_dbl_const;
+       dw_long_long_const val_long_long;
+       dw_float_const val_float;
        dw_die_ref val_die_ref;
        unsigned val_fde_index;
        char *val_str;
@@ -301,7 +313,11 @@ extern char *language_string;
 static unsigned cie_size;
 
 /* Offsets recorded in opcodes are a multiple of this alignment factor.  */
-#define DWARF_CIE_DATA_ALIGNMENT -4
+#ifdef STACK_GROWS_DOWNWARD
+#define DWARF_CIE_DATA_ALIGNMENT (-UNITS_PER_WORD)
+#else
+#define DWARF_CIE_DATA_ALIGNMENT UNITS_PER_WORD
+#endif
 
 /* Fixed size portion of the FDE.  */
 #define DWARF_FDE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2 * PTR_SIZE)
@@ -830,9 +846,9 @@ char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 #endif
 
 /* The mapping from gcc register number to DWARF 2 CFA column number.  By
-   default, we provide columns for all registers after the CFA column.  */
+   default, we just provide columns for all registers.  */
 #ifndef DWARF_FRAME_REGNUM
-#define DWARF_FRAME_REGNUM(REG) (DBX_REGISTER_NUMBER (REG) + 1)
+#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
 #endif
 \f
 /************************ general utility functions **************************/
@@ -1948,7 +1964,7 @@ add_AT_unsigned (die, attr_kind, unsigned_val)
 
 /* Add an unsigned double integer attribute value to a DIE.  */
 inline void
-add_AT_double (die, attr_kind, val_hi, val_low)
+add_AT_long_long (die, attr_kind, val_hi, val_low)
      register dw_die_ref die;
      register enum dwarf_attribute attr_kind;
      register unsigned long val_hi;
@@ -1959,9 +1975,29 @@ add_AT_double (die, attr_kind, val_hi, val_low)
     {
       attr->dw_attr_next = NULL;
       attr->dw_attr = attr_kind;
-      attr->dw_attr_val.val_class = dw_val_class_double_const;
-      attr->dw_attr_val.v.val_dbl_const.dw_dbl_hi = val_hi;
-      attr->dw_attr_val.v.val_dbl_const.dw_dbl_low = val_low;
+      attr->dw_attr_val.val_class = dw_val_class_long_long;
+      attr->dw_attr_val.v.val_long_long.hi = val_hi;
+      attr->dw_attr_val.v.val_long_long.low = val_low;
+      add_dwarf_attr (die, attr);
+    }
+}
+
+/* Add a floating point attribute value to a DIE and return it.  */
+inline void
+add_AT_float (die, attr_kind, length, array)
+     register dw_die_ref die;
+     register enum dwarf_attribute attr_kind;
+     register unsigned length;
+     register long *array;
+{
+  register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  if (attr != NULL)
+    {
+      attr->dw_attr_next = NULL;
+      attr->dw_attr = attr_kind;
+      attr->dw_attr_val.val_class = dw_val_class_float;
+      attr->dw_attr_val.v.val_float.length = length;
+      attr->dw_attr_val.v.val_float.array = array;
       add_dwarf_attr (die, attr);
     }
 }
@@ -2502,10 +2538,13 @@ print_die (die, outfile)
        case dw_val_class_unsigned_const:
          fprintf (outfile, "%u", a->dw_attr_val.v.val_unsigned);
          break;
-       case dw_val_class_double_const:
+       case dw_val_class_long_long:
          fprintf (outfile, "constant (%u,%u)",
-                 a->dw_attr_val.v.val_dbl_const.dw_dbl_hi,
-                 a->dw_attr_val.v.val_dbl_const.dw_dbl_low);
+                 a->dw_attr_val.v.val_long_long.hi,
+                 a->dw_attr_val.v.val_long_long.low);
+         break;
+       case dw_val_class_float:
+         fprintf (outfile, "floating-point constant");
          break;
        case dw_val_class_flag:
          fprintf (outfile, "%u", a->dw_attr_val.v.val_flag);
@@ -2909,8 +2948,11 @@ size_of_die (die)
        case dw_val_class_unsigned_const:
          size += constant_size (a->dw_attr_val.v.val_unsigned);
          break;
-       case dw_val_class_double_const:
-         size += 8;
+       case dw_val_class_long_long:
+         size += 1 + 8; /* block */
+         break;
+       case dw_val_class_float:
+         size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */
          break;
        case dw_val_class_flag:
          size += 1;
@@ -3237,8 +3279,10 @@ value_format (v)
        default:
          abort ();
        }
-    case dw_val_class_double_const:
-      return DW_FORM_data8;
+    case dw_val_class_long_long:
+      return DW_FORM_block1;
+    case dw_val_class_float:
+      return DW_FORM_block1;
     case dw_val_class_flag:
       return DW_FORM_flag;
     case dw_val_class_die_ref:
@@ -3342,9 +3386,7 @@ output_loc_operands (loc)
       break;
     case DW_OP_const8u:
     case DW_OP_const8s:
-      ASM_OUTPUT_DWARF_DATA8 (asm_out_file,
-                             val1->v.val_dbl_const.dw_dbl_hi,
-                             val2->v.val_dbl_const.dw_dbl_low);
+      abort ();
       fputc ('\n', asm_out_file);
       break;
     case DW_OP_constu:
@@ -3459,6 +3501,8 @@ output_die (die)
   register unsigned long ref_offset;
   register unsigned long size;
   register dw_loc_descr_ref loc;
+  register int i;
+
   output_uleb128 (die->die_abbrev);
   if (flag_verbose_asm)
     fprintf (asm_out_file, " (DIE (0x%x) %s)",
@@ -3530,10 +3574,36 @@ output_die (die)
              abort ();
            }
          break;
-       case dw_val_class_double_const:
+       case dw_val_class_long_long:
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 8);
+         if (flag_verbose_asm)
+           fprintf (asm_out_file, "\t%s %s",
+                    ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
+         fputc ('\n', asm_out_file);
          ASM_OUTPUT_DWARF_DATA8 (asm_out_file,
-                                 a->dw_attr_val.v.val_dbl_const.dw_dbl_hi,
-                                 a->dw_attr_val.v.val_dbl_const.dw_dbl_low);
+                                 a->dw_attr_val.v.val_long_long.hi,
+                                 a->dw_attr_val.v.val_long_long.low);
+         if (flag_verbose_asm)
+           fprintf (asm_out_file, "\t%s long long constant",
+                    ASM_COMMENT_START);
+         fputc ('\n', asm_out_file);
+         break;
+       case dw_val_class_float:
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+                                 a->dw_attr_val.v.val_float.length * 4);
+         if (flag_verbose_asm)
+           fprintf (asm_out_file, "\t%s %s",
+                    ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
+         fputc ('\n', asm_out_file);
+         for (i = 0; i < a->dw_attr_val.v.val_float.length; ++i)
+           {
+             ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
+                                     a->dw_attr_val.v.val_float.array[i]);
+             if (flag_verbose_asm)
+               fprintf (asm_out_file, "\t%s fp constant word %d",
+                        ASM_COMMENT_START, i);
+             fputc ('\n', asm_out_file);
+           }
          break;
        case dw_val_class_flag:
          ASM_OUTPUT_DWARF_DATA1 (asm_out_file, a->dw_attr_val.v.val_flag);
@@ -3571,7 +3641,9 @@ output_die (die)
        default:
          abort ();
        }
-      if (a->dw_attr_val.val_class != dw_val_class_loc)
+      if (a->dw_attr_val.val_class != dw_val_class_loc
+         && a->dw_attr_val.val_class != dw_val_class_long_long
+         && a->dw_attr_val.val_class != dw_val_class_float)
        {
          if (flag_verbose_asm)
            {
@@ -3631,35 +3703,23 @@ output_compilation_unit_header ()
   fputc ('\n', asm_out_file);
 }
 
-/* Extract the register and offset values from RTL.  If no register number
-   is specified, return -1 to indicate frame-relative addressing.  */
-static void
-decode_cfi_rtl (rtl, regp, offsetp)
-     register rtx rtl;
-     register unsigned long *regp;
-     register long *offsetp;
+/* Generate a new label for the CFI info to refer to.  */
+
+char *
+dwarf2out_cfi_label ()
 {
-  switch (GET_CODE (rtl))
-    {
-    case REG:
-      *regp = reg_number (rtl);
-      *offsetp = 0;
-      break;
-    case PLUS:
-      *regp = reg_number (XEXP (rtl, 0));
-      *offsetp = INTVAL (XEXP (rtl, 1));
-      break;
-    case CONST_INT:
-      *regp = (unsigned long) -1;
-      *offsetp = INTVAL (rtl);
-      break;
-    default:
-      abort ();
-    }
+  static char label[20];
+  static unsigned long label_num = 0;
+  
+  ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++);
+  ASM_OUTPUT_LABEL (asm_out_file, label);
+
+  return label;
 }
 
 /* Add CFI to the current fde at the PC value indicated by LABEL if specified,
    or to the CIE if LABEL is NULL.  */
+
 static void
 add_fde_cfi (label, cfi)
      register char * label;
@@ -3668,6 +3728,8 @@ add_fde_cfi (label, cfi)
   if (label)
     {
       register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
+      if (*label == 0)
+       label = dwarf2out_cfi_label ();
       if (fde->dw_fde_current_label == NULL
          || strcmp (label, fde->dw_fde_current_label) != 0)
        {
@@ -3730,20 +3792,20 @@ lookup_cfa (regp, offsetp)
 }
 
 /* Entry point to update the canonical frame address (CFA).
-   LABEL is passed to add_fde_cfi.  RTL is either:
+   LABEL is passed to add_fde_cfi.  The value of CFA is now to be
+   calculated from REG+OFFSET.  */
 
-   a REG:  The frame is at 0(REG).
-   a PLUS of a REG and a CONST_INT:  The frame is at CONST(REG).  */
 void
-dwarf2out_def_cfa (label, rtl)
+dwarf2out_def_cfa (label, reg, offset)
      register char * label;
-     register rtx rtl;
+     register unsigned reg;
+     register long offset;
 {
   register dw_cfi_ref cfi;
-  unsigned long reg, old_reg;
-  long offset, old_offset;
+  unsigned old_reg;
+  long old_offset;
 
-  decode_cfi_rtl (rtl, &reg, &offset);
+  reg = DWARF_FRAME_REGNUM (reg);
   lookup_cfa (&old_reg, &old_offset);
 
   if (reg == old_reg && offset == old_offset)
@@ -3775,29 +3837,21 @@ dwarf2out_def_cfa (label, rtl)
 
 /* Add the CFI for saving a register.  REG is the CFA column number.
    LABEL is passed to add_fde_cfi.
-   RTL is either:
+   If SREG is -1, the register is saved at OFFSET from the CFA;
+   otherwise it is saved in SREG.  */
 
-   a REG:  The register is saved in REG.
-   a CONST_INT:  The register is saved at an offset of CONST
-     from the CFA.  */
 static void
-reg_save (label, reg, rtl)
+reg_save (label, reg, sreg, offset)
      register char * label;
-     register unsigned long reg;
-     register rtx rtl;
+     register unsigned reg;
+     register unsigned sreg;
+     register long offset;
 {
-  register dw_cfi_ref cfi;
-  unsigned long sreg;
-  long offset;
-
-  cfi = new_cfi ();
+  register dw_cfi_ref cfi = new_cfi ();
 
   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
 
-  decode_cfi_rtl (rtl, &sreg, &offset);
-  offset /= DWARF_CIE_DATA_ALIGNMENT;
-
-  if (sreg == (unsigned long) -1)
+  if (sreg == -1)
     {
       if (reg & ~0x3f)
        /* The register number won't fit in 6 bits, so we have to use
@@ -3805,6 +3859,9 @@ reg_save (label, reg, rtl)
        cfi->dw_cfi_opc = DW_CFA_offset_extended;
       else
        cfi->dw_cfi_opc = DW_CFA_offset;
+
+      offset /= DWARF_CIE_DATA_ALIGNMENT;
+      assert (offset >= 0);
       cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
     }
   else
@@ -3817,24 +3874,166 @@ reg_save (label, reg, rtl)
 }
 
 /* Entry point for saving a register.  REG is the GCC register number.
-   LABEL and RTL are passed to reg_save.  */
+   LABEL and OFFSET are passed to reg_save.  */
+
 void
-dwarf2out_reg_save (label, reg, rtl)
+dwarf2out_reg_save (label, reg, offset)
      register char * label;
-     register unsigned long reg;
+     register unsigned reg;
+     register long offset;
+{
+  reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset);
+}
+
+/* Record the initial position of the return address.  RTL is
+   INCOMING_RETURN_ADDR_RTX.  */
+
+static void
+initial_return_save (rtl)
      register rtx rtl;
 {
-  reg_save (label, DWARF_FRAME_REGNUM (reg), rtl);
+  unsigned reg = -1;
+  long offset = 0;
+
+  switch (GET_CODE (rtl))
+    {
+    case REG:
+      /* RA is in a register.  */
+      reg = reg_number (rtl);
+      break;
+    case MEM:
+      /* RA is on the stack.  */
+      rtl = XEXP (rtl, 0);
+      switch (GET_CODE (rtl))
+       {
+       case REG:
+         assert (REGNO (rtl) == STACK_POINTER_REGNUM);
+         offset = 0;
+         break;
+       case PLUS:
+         assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
+         offset = INTVAL (XEXP (rtl, 1));
+         break;
+       case MINUS:
+         assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
+         offset = -INTVAL (XEXP (rtl, 1));
+         break;
+       default:
+         abort ();
+       }
+      break;
+    default:
+      abort ();
+    }
+
+  reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset);
 }
 
-/* Entry point for saving the return address.
-   LABEL and RTL are passed to reg_save.  */
+/* Record call frame debugging information for INSN, which either
+   sets SP or FP (adjusting how we calculate the frame address) or saves a
+   register to the stack.  If INSN is NULL_RTX, initialize our state.  */
+
 void
-dwarf2out_return_save (label, rtl)
-     register char * label;
-     register rtx rtl;
+dwarf2out_frame_debug (insn)
+     rtx insn;
 {
-  reg_save (label, DWARF_FRAME_RETURN_COLUMN, rtl);
+  char *label;
+  rtx src, dest;
+  long offset;
+  static unsigned cfa_reg;
+  static long cfa_offset;
+  static long cfa_sp_offset;
+
+  if (insn == NULL_RTX)
+    {
+      /* Set up state for generating call frame debug info.  */
+      cfa_reg = STACK_POINTER_REGNUM;
+      cfa_offset = 0;
+      cfa_sp_offset = 0;
+      return;
+    }
+
+  label = dwarf2out_cfi_label ();
+    
+  insn = PATTERN (insn);
+  assert (GET_CODE (insn) == SET);
+
+  src = SET_SRC (insn);
+  dest = SET_DEST (insn);
+
+  switch (GET_CODE (dest))
+    {
+    case REG:
+      /* Update the CFA rule wrt SP or FP.  Make sure src is
+        relative to the current CFA register.  */
+      assert (REGNO (dest) == STACK_POINTER_REGNUM
+             || frame_pointer_needed && REGNO (dest) == FRAME_POINTER_REGNUM);
+      switch (GET_CODE (src))
+       {
+         /* Setting FP from SP.  */
+       case REG:
+         assert (cfa_reg == REGNO (src));
+         cfa_reg = REGNO (dest);
+         break;
+
+         /* Adjusting SP.  */
+       case PLUS:
+         cfa_sp_offset -= INTVAL (XEXP (src, 1));
+         goto add;
+       case MINUS:
+         cfa_sp_offset += INTVAL (XEXP (src, 1));
+       add:
+         assert (REGNO (XEXP (src, 0)) == STACK_POINTER_REGNUM);
+         if (cfa_reg == STACK_POINTER_REGNUM)
+           cfa_offset = cfa_sp_offset;
+         break;
+
+       default:
+         abort ();
+       }
+      dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+      break;
+
+    case MEM:
+      /* Saving a register to the stack.  Make sure dest is relative to the
+         CFA register.  */
+      assert (GET_CODE (src) == REG);
+      switch (GET_CODE (XEXP (dest, 0)))
+       {
+         /* With a push.  */
+       case PRE_DEC:
+         cfa_sp_offset += GET_MODE_SIZE (GET_MODE (dest));
+         goto pre;
+       case PRE_INC:
+         cfa_sp_offset -= GET_MODE_SIZE (GET_MODE (dest));
+       pre:
+         assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM);
+         if (cfa_reg == STACK_POINTER_REGNUM)
+           cfa_offset = cfa_sp_offset;
+         offset = -cfa_sp_offset;
+         break;
+
+         /* With an offset.  */
+       case PLUS:
+         offset = INTVAL (XEXP (XEXP (dest, 0), 1));
+         goto off;
+       case MINUS:
+         offset = -INTVAL (XEXP (XEXP (dest, 0), 1));
+       off:
+         assert (cfa_reg == REGNO (XEXP (XEXP (dest, 0), 0)));
+         offset -= cfa_offset;
+         break;
+
+       default:
+         abort ();
+       }
+      dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+      dwarf2out_reg_save (label, REGNO (src), offset);
+      break;
+
+    default:
+      abort ();
+    }
 }
 
 /* Return the size of a Call Frame Instruction.  */
@@ -3952,9 +4151,8 @@ output_cfi (cfi, fde)
                              cfi->dw_cfi_opc
                              | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f));
       if (flag_verbose_asm)
-       {
-         fprintf (asm_out_file, "\t%s DW_CFA_advance_loc", ASM_COMMENT_START);
-       }
+       fprintf (asm_out_file, "\t%s DW_CFA_advance_loc 0x%x",
+                ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
       fputc ('\n', asm_out_file);
     }
   else if (cfi->dw_cfi_opc == DW_CFA_offset)
@@ -3963,9 +4161,8 @@ output_cfi (cfi, fde)
                              cfi->dw_cfi_opc
                              | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
       if (flag_verbose_asm)
-       {
-         fprintf (asm_out_file, "\t%s DW_CFA_offset", ASM_COMMENT_START);
-       }
+       fprintf (asm_out_file, "\t%s DW_CFA_offset, column 0x%x",
+                ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
       fputc ('\n', asm_out_file);
       output_uleb128(cfi->dw_cfi_oprnd2.dw_cfi_offset);
       fputc ('\n', asm_out_file);
@@ -3976,9 +4173,8 @@ output_cfi (cfi, fde)
                              cfi->dw_cfi_opc
                              | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
       if (flag_verbose_asm)
-       {
-         fprintf (asm_out_file, "\t%s DW_CFA_restore", ASM_COMMENT_START);
-       }
+       fprintf (asm_out_file, "\t%s DW_CFA_restore, column 0x%x",
+                ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
       fputc ('\n', asm_out_file);
     }
   else
@@ -5534,12 +5730,54 @@ add_const_value_attribute (die, rtl)
       /* Note that a CONST_DOUBLE rtx could represent either an integer or a
          floating-point constant.  A CONST_DOUBLE is used whenever the
          constant requires more than one word in order to be adequately
-         represented.  In all such cases, the original mode of the constant
-         value is preserved as the mode of the CONST_DOUBLE rtx, but for
-         simplicity we always just output CONST_DOUBLEs using 8 bytes.  */
-      add_AT_double (die, DW_AT_const_value,
-                    (unsigned) CONST_DOUBLE_HIGH (rtl),
-                    (unsigned) CONST_DOUBLE_LOW (rtl));
+         represented.  We output CONST_DOUBLEs as blocks.  */
+      {
+       register enum machine_mode mode = GET_MODE (rtl);
+
+       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+         {
+           union real_extract u;
+           jmp_buf handler;
+           register unsigned length = GET_MODE_SIZE (mode) / 4;
+           register long *array = (long *) xmalloc (length * sizeof (long));
+           
+           bcopy ((char *) &CONST_DOUBLE_LOW (rtl), (char *) &u, sizeof u);
+
+           if (setjmp (handler))
+             {
+               error ("floating point trap outputting debug info");
+               u.d = dconst0;
+             }
+
+           set_float_handler (handler);
+
+           switch (mode)
+             {
+             case SFmode:
+               REAL_VALUE_TO_TARGET_SINGLE (u.d, array[0]);
+               break;
+
+             case DFmode:
+               REAL_VALUE_TO_TARGET_DOUBLE (u.d, array);
+               break;
+
+             case XFmode:
+             case TFmode:
+               REAL_VALUE_TO_TARGET_LONG_DOUBLE (u.d, array);
+               break;
+
+             default:
+               abort ();
+             }
+
+           set_float_handler (NULL_PTR);
+
+           add_AT_float (die, DW_AT_const_value, length, array);
+         }
+       else
+         add_AT_long_long (die, DW_AT_const_value,
+                           CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
+      }
       break;
 
     case CONST_STRING:
@@ -8043,59 +8281,6 @@ dwarf2out_begin_prologue ()
   fde->dw_fde_cfi = NULL;
 }
 
-/* Output a marker (i.e. a label) for the point in the generated code where
-   the real body of the function begins (after parameters have been moved to
-   their home locations).  */
-void
-dwarf2out_begin_function ()
-{
-#ifdef MIPS_DEBUGGING_INFO
-  char label[MAX_ARTIFICIAL_LABEL_BYTES];
-  register long int offset;
-  register dw_fde_ref fde;
-  register dw_cfi_ref cfi;
-  register int regno, fp_inc;
-
-  function_section (current_function_decl);
-  ASM_GENERATE_INTERNAL_LABEL (label, BODY_BEGIN_LABEL,
-                              current_funcdef_number);
-  ASM_OUTPUT_LABEL (asm_out_file, label);
-
-  /* Define the CFA as an offset from either the frame pointer
-     or the stack pointer.  */
-  dwarf2out_def_cfa
-    (label, gen_rtx (PLUS, VOIDmode,
-                    gen_rtx (REG, VOIDmode,
-                             (frame_pointer_needed ? FRAME_POINTER_REGNUM
-                              : STACK_POINTER_REGNUM)),
-                    GEN_INT (current_frame_info.total_size)));
-
-  /* Record the locations of the return address and any callee-saved regs.  */
-  offset = current_frame_info.gp_save_offset / DWARF_CIE_DATA_ALIGNMENT;
-  for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; --regno)
-    if (current_frame_info.mask & (1<<regno))
-      {
-       assert (offset >= 0);
-
-       if (regno == 31)
-         dwarf2out_return_save (label, GEN_INT (offset));
-       else
-         dwarf2out_reg_save (label, regno, GEN_INT (offset));
-       offset -= UNITS_PER_WORD / DWARF_CIE_DATA_ALIGNMENT;
-      }
-
-  fp_inc = (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) ? 1 : 2;
-  offset = current_frame_info.fp_save_offset / DWARF_CIE_DATA_ALIGNMENT;
-  for (regno = FP_REG_LAST - 1; regno >= FP_REG_FIRST; regno -= fp_inc)
-    if (current_frame_info.fmask & (1 << (regno - FP_REG_FIRST)))
-      {
-       assert (offset >= 0);
-       dwarf2out_reg_save (label, regno, GEN_INT (offset));
-       offset -= (fp_inc * UNITS_PER_FPREG) / DWARF_CIE_DATA_ALIGNMENT;
-      }
-#endif
-}
-
 /* Output a marker (i.e. a label) for the absolute end of the generated code
    for a function definition.  This gets called *after* the epilogue code has
    been generated.  */
@@ -8336,12 +8521,11 @@ dwarf2out_init (asm_out_file, main_input_filename)
 
   /* Generate the CFA instructions common to all FDE's.  Do it now for the
      sake of lookup_cfa.  */
-#ifdef MIPS_DEBUGGING_INFO
-  /* On entry, the Call Frame Address is in the stack pointer register.  */
-  dwarf2out_def_cfa (NULL, gen_rtx (REG, VOIDmode, STACK_POINTER_REGNUM));
 
-  /* Set the RA on entry to be the contents of r31.  */
-  dwarf2out_return_save (NULL, gen_rtx (REG, VOIDmode, GP_REG_FIRST + 31));
+#ifdef INCOMING_RETURN_ADDR_RTX
+  /* On entry, the Canonical Frame Address is at SP+0.  */
+  dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, 0);
+  initial_return_save (INCOMING_RETURN_ADDR_RTX);
 #endif
 }
 
index 40a0911..cc5bedf 100644 (file)
@@ -1208,6 +1208,10 @@ final (first, file, optimize, prescan)
   last_ignored_compare = 0;
   new_block = 1;
 
+#if defined (DWARF2_DEBUGGING_INFO) && defined (HAVE_prologue)
+  dwarf2out_frame_debug (NULL_RTX);
+#endif
+
   check_exception_handler_labels ();
 
   /* Make a map indicating which line numbers appear in this function.
@@ -1370,12 +1374,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
          if (write_symbols == DWARF_DEBUG)
            dwarfout_begin_function ();
 #endif
-#ifdef DWARF2_DEBUGGING_INFO
-         /* This outputs a marker where the function body starts, so it
-            must be after the prologue.  */
-         if (write_symbols == DWARF2_DEBUG)
-           dwarf2out_begin_function ();
-#endif
          break;
        }
       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
@@ -2104,6 +2102,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
        output_asm_insn (template, recog_operand);
 
+#if defined (DWARF2_DEBUGGING_INFO) && defined (HAVE_prologue)
+       /* If this insn is part of the prologue, emit DWARF v2
+          call frame info.  */
+       if (write_symbols == DWARF2_DEBUG && RTX_FRAME_RELATED_P (insn))
+         dwarf2out_frame_debug (insn);
+#endif
+
 #if 0
        /* It's not at all clear why we did this and doing so interferes
           with tests we'd like to do to use REG_WAS_0 notes, so let's try
index 733f881..83e3cc0 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -140,6 +140,10 @@ typedef struct rtx_def
      In a REG, nonzero means this reg refers to the return value
      of the current function.  */
   unsigned integrated : 1;
+  /* Nonzero if this rtx is related to the call frame, either changing how
+     we compute the frame address or saving and restoring registers in
+     the prologue and epilogue.  */
+  unsigned frame_related : 1;
   /* The first element of the operands of this rtx.
      The number of operands and their types are controlled
      by the `code' field, according to rtl.def.  */
@@ -165,6 +169,7 @@ typedef struct rtx_def
 
 #define RTX_INTEGRATED_P(RTX) ((RTX)->integrated)
 #define RTX_UNCHANGING_P(RTX) ((RTX)->unchanging)
+#define RTX_FRAME_RELATED_P(RTX) ((RTX)->frame_related)
 
 /* RTL vector.  These appear inside RTX's when there is a need
    for a variable number of things.  The principle use is inside