OSDN Git Service

* sparc/sparc.md (eligible_for_return_delay): New attribute.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 11229e6..a79339c 100644 (file)
@@ -1,5 +1,5 @@
 /* Output Dwarf2 format symbol table information from the GNU C compiler.
-   Copyright (C) 1992, 93, 95, 96, 97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1992, 93, 95-98, 1999 Free Software Foundation, Inc.
    Contributed by Gary Funck (gary@intrepid.com).
    Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
    Extensively modified by Jason Merrill (jason@cygnus.com).
@@ -18,7 +18,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /* The first part of this file deals with the DWARF 2 frame unwind
    information, which is also used by the GCC efficient exception handling
@@ -42,6 +43,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "dwarf2.h"
 #include "dwarf2out.h"
 #include "toplev.h"
+#include "dyn-string.h"
 
 /* We cannot use <assert.h> in GCC source, since that would include
    GCC's assert.h, which may not be compatible with the host compiler.  */
@@ -59,6 +61,9 @@ int
 dwarf2out_do_frame ()
 {
   return (write_symbols == DWARF2_DEBUG
+#ifdef DWARF2_FRAME_INFO
+          || DWARF2_FRAME_INFO
+#endif
 #ifdef DWARF2_UNWIND_INFO
          || (flag_exceptions && ! exceptions_via_longjmp)
 #endif
@@ -67,10 +72,6 @@ dwarf2out_do_frame ()
 
 #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 
-#ifndef __GNUC__
-#define inline
-#endif
-
 /* How to start an assembler comment.  */
 #ifndef ASM_COMMENT_START
 #define ASM_COMMENT_START ";#"
@@ -185,8 +186,8 @@ static unsigned current_funcdef_fde;
 
 /* Forward declarations for functions defined in this file.  */
 
-static char *stripattributes           PROTO((char *));
-static char *dwarf_cfi_name            PROTO((unsigned));
+static char *stripattributes           PROTO((const char *));
+static const char *dwarf_cfi_name      PROTO((unsigned));
 static dw_cfi_ref new_cfi              PROTO((void));
 static void add_cfi                    PROTO((dw_cfi_ref *, dw_cfi_ref));
 static unsigned long size_of_uleb128   PROTO((unsigned long));
@@ -204,6 +205,7 @@ static void output_cfi                      PROTO((dw_cfi_ref, dw_fde_ref));
 static void output_call_frame_info     PROTO((int));
 static unsigned reg_number             PROTO((rtx));
 static void dwarf2out_stack_adjust     PROTO((rtx));
+static void dwarf2out_frame_debug_expr PROTO((rtx, char *));
 
 /* Definitions of defaults for assembler-dependent names of various
    pseudo-ops and section names.
@@ -275,7 +277,7 @@ static void dwarf2out_stack_adjust  PROTO((rtx));
 
 #ifndef ASM_OUTPUT_DWARF_DATA1
 #define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \
-  fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, VALUE)
+  fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) (VALUE))
 #endif
 
 #ifndef ASM_OUTPUT_DWARF_DELTA1
@@ -342,6 +344,16 @@ static void dwarf2out_stack_adjust PROTO((rtx));
   } while (0)
 #endif
 
+/* ??? This macro takes an RTX in dwarfout.c and a string in dwarf2out.c.
+   We resolve the conflict by creating a new macro ASM_OUTPUT_DWARF2_ADDR_CONST
+   for ports that want to support both DWARF1 and DWARF2.  This needs a better
+   solution.  See also the comments in sparc/sp64-elf.h.  */
+#ifdef ASM_OUTPUT_DWARF2_ADDR_CONST
+#undef ASM_OUTPUT_DWARF_ADDR_CONST
+#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR) \
+  ASM_OUTPUT_DWARF2_ADDR_CONST (FILE, ADDR)
+#endif
+
 #ifndef ASM_OUTPUT_DWARF_ADDR_CONST
 #define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR)                         \
   fprintf ((FILE), "\t%s\t%s", UNALIGNED_WORD_ASM_OP, (ADDR))
@@ -363,24 +375,24 @@ static void dwarf2out_stack_adjust        PROTO((rtx));
 
 #ifndef ASM_OUTPUT_DWARF_DATA2
 #define ASM_OUTPUT_DWARF_DATA2(FILE,VALUE) \
-  fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, (unsigned) VALUE)
+  fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, (unsigned) (VALUE))
 #endif
 
 #ifndef ASM_OUTPUT_DWARF_DATA4
 #define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \
-  fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_INT_ASM_OP, (unsigned) VALUE)
+  fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_INT_ASM_OP, (unsigned) (VALUE))
 #endif
 
 #ifndef ASM_OUTPUT_DWARF_DATA
 #define ASM_OUTPUT_DWARF_DATA(FILE,VALUE) \
   fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP, \
-          (unsigned long) VALUE)
+          (unsigned long) (VALUE))
 #endif
 
 #ifndef ASM_OUTPUT_DWARF_ADDR_DATA
 #define ASM_OUTPUT_DWARF_ADDR_DATA(FILE,VALUE) \
   fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_WORD_ASM_OP, \
-          (unsigned long) VALUE)
+          (unsigned long) (VALUE))
 #endif
 
 #ifndef ASM_OUTPUT_DWARF_DATA8
@@ -388,13 +400,13 @@ static void dwarf2out_stack_adjust        PROTO((rtx));
   do {                                                                 \
     if (WORDS_BIG_ENDIAN)                                              \
       {                                                                        \
-       fprintf ((FILE), "\t%s\t0x%lx\n", UNALIGNED_INT_ASM_OP, HIGH_VALUE); \
-       fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, LOW_VALUE);\
+       fprintf ((FILE), "\t%s\t0x%lx\n", UNALIGNED_INT_ASM_OP, (HIGH_VALUE));\
+       fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (LOW_VALUE));\
       }                                                                        \
     else                                                               \
       {                                                                        \
-       fprintf ((FILE), "\t%s\t0x%lx\n", UNALIGNED_INT_ASM_OP, LOW_VALUE);\
-       fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, HIGH_VALUE); \
+       fprintf ((FILE), "\t%s\t0x%lx\n", UNALIGNED_INT_ASM_OP, (LOW_VALUE)); \
+       fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (HIGH_VALUE)); \
       }                                                                        \
   } while (0)
 #endif
@@ -415,20 +427,20 @@ static void dwarf2out_stack_adjust        PROTO((rtx));
 
 #define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2)                    \
   assemble_integer (gen_rtx_MINUS (HImode,                             \
-                            gen_rtx_SYMBOL_REF (Pmode, LABEL1),        \
-                            gen_rtx_SYMBOL_REF (Pmode, LABEL2)),       \
+                                  gen_rtx_SYMBOL_REF (Pmode, LABEL1),  \
+                                  gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
                    2, 1)
   
 #define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2)                    \
   assemble_integer (gen_rtx_MINUS (SImode,                             \
-                            gen_rtx_SYMBOL_REF (Pmode, LABEL1),        \
-                            gen_rtx_SYMBOL_REF (Pmode, LABEL2)),       \
+                                  gen_rtx_SYMBOL_REF (Pmode, LABEL1),  \
+                                  gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
                    4, 1)
 
 #define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE,LABEL1,LABEL2)                        \
   assemble_integer (gen_rtx_MINUS (Pmode,                              \
-                            gen_rtx_SYMBOL_REF (Pmode, LABEL1),        \
-                            gen_rtx_SYMBOL_REF (Pmode, LABEL2)),       \
+                                  gen_rtx_SYMBOL_REF (Pmode, LABEL1),  \
+                                  gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
                    PTR_SIZE, 1)
 
 #define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \
@@ -460,7 +472,7 @@ static void dwarf2out_stack_adjust  PROTO((rtx));
 #define ASM_OUTPUT_DWARF_STRING(FILE,P) \
   do {                                                                       \
     register int slen = strlen(P);                                            \
-    register char *p = (P);                                                  \
+    register const char *p = (P);                                            \
     register int i;                                                          \
     fprintf (FILE, "\t.ascii \"");                                           \
     for (i = 0; i < slen; i++)                                               \
@@ -468,7 +480,7 @@ static void dwarf2out_stack_adjust  PROTO((rtx));
          register int c = p[i];                                              \
          if (c == '\"' || c == '\\')                                         \
            putc ('\\', FILE);                                                \
-         if (c >= ' ' && c < 0177)                                           \
+         if (ISPRINT(c))                                                     \
            putc (c, FILE);                                                   \
          else                                                                \
            {                                                                 \
@@ -512,17 +524,19 @@ expand_builtin_dwarf_fp_regnum ()
 #endif
 
 /* Return a pointer to a copy of the section string name S with all
-   attributes stripped off.  */
+   attributes stripped off, and an asterisk prepended (for assemble_name).  */
 
 static inline char *
 stripattributes (s)
-     char *s;
+     const char *s;
 {
-  char *stripped = xstrdup (s);
+  char *stripped = xmalloc (strlen (s) + 2);
   char *p = stripped;
 
-  while (*p && *p != ',')
-    p++;
+  *p++ = '*';
+
+  while (*s && *s != ',')
+    *p++ = *s++;
 
   *p = '\0';
   return stripped;
@@ -626,31 +640,35 @@ expand_builtin_dwarf_reg_size (reg_tree, target)
     }
   else
     {
+      /* Initialize last_end to be larger than any possible
+        DWARF_FRAME_REGNUM.  */
+      int last_end = 0x7fffffff;
       --n_ranges;
       t = build_int_2 (ranges[n_ranges].size, 0);
-      size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
-      for (; n_ranges--; )
+      do
        {
-         if ((DWARF_FRAME_REGNUM (ranges[n_ranges].end)
-              - DWARF_FRAME_REGNUM (ranges[n_ranges].beg))
-             != ranges[n_ranges].end - ranges[n_ranges].beg)
+         int beg = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
+         int end = DWARF_FRAME_REGNUM (ranges[n_ranges].end);
+         if (beg < 0)
+           continue;
+         if (end >= last_end)
            abort ();
-         if (DWARF_FRAME_REGNUM (ranges[n_ranges].beg) >= size)
+         last_end = end;
+         if (end - beg != ranges[n_ranges].end - ranges[n_ranges].beg)
            abort ();
-         size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
          t2 = fold (build (LE_EXPR, integer_type_node, reg_tree,
-                           build_int_2 (DWARF_FRAME_REGNUM
-                                        (ranges[n_ranges].end), 0)));
+                           build_int_2 (end, 0)));
          t = fold (build (COND_EXPR, integer_type_node, t2,
                           build_int_2 (ranges[n_ranges].size, 0), t));
        }
+      while (--n_ranges >= 0);
     }
   return expand_expr (t, target, Pmode, 0);
 }
 
 /* Convert a DWARF call frame info. operation to its string name */
 
-static char *
+static const char *
 dwarf_cfi_name (cfi_opc)
      register unsigned cfi_opc;
 {
@@ -1020,7 +1038,7 @@ static void
 initial_return_save (rtl)
      register rtx rtl;
 {
-  unsigned reg = -1;
+  unsigned int reg = (unsigned int) -1;
   long offset = 0;
 
   switch (GET_CODE (rtl))
@@ -1169,77 +1187,74 @@ dwarf2out_stack_adjust (insn)
   dwarf2out_args_size (label, args_size);
 }
 
-/* Record call frame debugging information for INSN, which either
+/* A temporary register used in adjusting SP or setting up the store_reg.  */
+static unsigned cfa_temp_reg;
+
+/* A temporary value used in adjusting SP or setting up the store_reg.  */
+static long cfa_temp_value;
+
+/* Record call frame debugging information for an expression, 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.  */
+   register to the stack. */
 
-void
-dwarf2out_frame_debug (insn)
-     rtx insn;
+static void
+dwarf2out_frame_debug_expr (expr, label)
+     rtx expr;
+     char *label;
 {
-  char *label;
   rtx src, dest;
   long offset;
+    
+  /* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of 
+     the PARALLEL independantly. The first element is always processed if 
+     it is a SET. This is for backward compatability.   Other elements 
+     are processed only if they are SETs and the RTX_FRAME_RELATED_P 
+     flag is set in them. */
 
-  /* A temporary register used in adjusting SP or setting up the store_reg.  */
-  static unsigned cfa_temp_reg;
-  static long cfa_temp_value;
-
-  if (insn == NULL_RTX)
-    {
-      /* Set up state for generating call frame debug info.  */
-      lookup_cfa (&cfa_reg, &cfa_offset);
-      if (cfa_reg != DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
-       abort ();
-      cfa_reg = STACK_POINTER_REGNUM;
-      cfa_store_reg = cfa_reg;
-      cfa_store_offset = cfa_offset;
-      cfa_temp_reg = -1;
-      cfa_temp_value = 0;
-      return;
-    }
-
-  if (! RTX_FRAME_RELATED_P (insn))
-    {
-      dwarf2out_stack_adjust (insn);
+  if (GET_CODE (expr) == PARALLEL)
+    { 
+      int par_index;
+      int limit = XVECLEN (expr, 0);
+
+      for (par_index = 0; par_index < limit; par_index++)
+        {
+          rtx x = XVECEXP (expr, 0, par_index);
+          
+          if (GET_CODE (x) == SET &&
+             (RTX_FRAME_RELATED_P (x) || par_index == 0))
+           dwarf2out_frame_debug_expr (x, label);
+        }
       return;
     }
-
-  label = dwarf2out_cfi_label ();
-    
-  insn = PATTERN (insn);
-  /* Assume that in a PARALLEL prologue insn, only the first elt is
-     significant.  Currently this is true.  */
-  if (GET_CODE (insn) == PARALLEL)
-    insn = XVECEXP (insn, 0, 0);
-  if (GET_CODE (insn) != SET)
+  
+  if (GET_CODE (expr) != SET)
     abort ();
 
-  src = SET_SRC (insn);
-  dest = SET_DEST (insn);
+  src = SET_SRC (expr);
+  dest = SET_DEST (expr);
 
   switch (GET_CODE (dest))
     {
     case REG:
       /* Update the CFA rule wrt SP or FP.  Make sure src is
-        relative to the current CFA register.  */
+         relative to the current CFA register.  */
       switch (GET_CODE (src))
-       {
-         /* Setting FP from SP.  */
-       case REG:
-         if (cfa_reg != REGNO (src))
-           abort ();
-         if (REGNO (dest) != STACK_POINTER_REGNUM
+        {
+          /* Setting FP from SP.  */
+        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 ();
-         cfa_reg = REGNO (dest);
-         break;
+            abort ();
+          cfa_reg = REGNO (dest);
+          break;
 
-       case PLUS:
-       case MINUS:
-         if (dest == stack_pointer_rtx)
-           {
+        case PLUS:
+        case MINUS:
+          if (dest == stack_pointer_rtx)
+            {
              /* Adjusting SP.  */
              switch (GET_CODE (XEXP (src, 1)))
                {
@@ -1247,7 +1262,7 @@ dwarf2out_frame_debug (insn)
                  offset = INTVAL (XEXP (src, 1));
                  break;
                case REG:
-                 if (REGNO (XEXP (src, 1)) != cfa_temp_reg)
+                 if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp_reg)
                    abort ();
                  offset = cfa_temp_value;
                  break;
@@ -1258,7 +1273,7 @@ dwarf2out_frame_debug (insn)
              if (XEXP (src, 0) == hard_frame_pointer_rtx)
                {
                  /* Restoring SP from FP in the epilogue.  */
-                 if (cfa_reg != HARD_FRAME_POINTER_REGNUM)
+                 if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
                    abort ();
                  cfa_reg = STACK_POINTER_REGNUM;
                }
@@ -1271,78 +1286,78 @@ dwarf2out_frame_debug (insn)
                cfa_offset += offset;
              if (cfa_store_reg == STACK_POINTER_REGNUM)
                cfa_store_offset += offset;
-           }
+            }
           else if (dest == hard_frame_pointer_rtx)
             {
-              /* Either setting the FP from an offset of the SP,
-                 or adjusting the FP */
+             /* Either setting the FP from an offset of the SP,
+                or adjusting the FP */
              if (! frame_pointer_needed
                  || REGNO (dest) != HARD_FRAME_POINTER_REGNUM)
                abort ();
 
-              if (XEXP (src, 0) == stack_pointer_rtx
-                  && GET_CODE (XEXP (src, 1)) == CONST_INT)
-                {
+             if (XEXP (src, 0) == stack_pointer_rtx
+                 && 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 != HARD_FRAME_POINTER_REGNUM)
+                 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();
+                 offset = INTVAL (XEXP (src, 1));
+                 if (GET_CODE (src) == PLUS)
+                   offset = -offset;
+                 cfa_offset += offset;
+               }
+
+             else 
+               abort();
             }
-         else
-           {
+          else
+            {
              if (GET_CODE (src) != PLUS
                  || XEXP (src, 1) != stack_pointer_rtx)
                abort ();
              if (GET_CODE (XEXP (src, 0)) != REG
-                 || REGNO (XEXP (src, 0)) != cfa_temp_reg)
+                 || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg)
                abort ();
              if (cfa_reg != STACK_POINTER_REGNUM)
                abort ();
              cfa_store_reg = REGNO (dest);
              cfa_store_offset = cfa_offset - cfa_temp_value;
-           }
-         break;
+            }
+          break;
 
-       case CONST_INT:
-         cfa_temp_reg = REGNO (dest);
-         cfa_temp_value = INTVAL (src);
-         break;
+        case CONST_INT:
+          cfa_temp_reg = REGNO (dest);
+          cfa_temp_value = INTVAL (src);
+          break;
 
-       case IOR:
-         if (GET_CODE (XEXP (src, 0)) != REG
-             || REGNO (XEXP (src, 0)) != cfa_temp_reg
-             || REGNO (dest) != cfa_temp_reg
+        case IOR:
+          if (GET_CODE (XEXP (src, 0)) != REG
+             || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg
+             || (unsigned) REGNO (dest) != cfa_temp_reg
              || GET_CODE (XEXP (src, 1)) != CONST_INT)
-           abort ();
-         cfa_temp_value |= INTVAL (XEXP (src, 1));
-         break;
+            abort ();
+          cfa_temp_value |= INTVAL (XEXP (src, 1));
+          break;
 
-       default:
-         abort ();
-       }
+        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.  */
+        CFA register.  */
       if (GET_CODE (src) != REG)
        abort ();
       switch (GET_CODE (XEXP (dest, 0)))
@@ -1368,14 +1383,21 @@ dwarf2out_frame_debug (insn)
        case PLUS:
        case MINUS:
          offset = INTVAL (XEXP (XEXP (dest, 0), 1));
-         if (GET_CODE (src) == MINUS)
+         if (GET_CODE (XEXP (dest, 0)) == MINUS)
            offset = -offset;
 
-         if (cfa_store_reg != REGNO (XEXP (XEXP (dest, 0), 0)))
+         if (cfa_store_reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
            abort ();
          offset -= cfa_store_offset;
          break;
 
+         /* Without an offset.  */
+       case REG:
+         if (cfa_store_reg != (unsigned) REGNO (XEXP (dest, 0)))
+           abort();
+         offset = -cfa_store_offset;
+         break;
+
        default:
          abort ();
        }
@@ -1388,6 +1410,49 @@ dwarf2out_frame_debug (insn)
     }
 }
 
+
+/* 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_frame_debug (insn)
+     rtx insn;
+{
+  char *label;
+  rtx src;
+
+  if (insn == NULL_RTX)
+    {
+      /* Set up state for generating call frame debug info.  */
+      lookup_cfa (&cfa_reg, &cfa_offset);
+      if (cfa_reg != DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
+       abort ();
+      cfa_reg = STACK_POINTER_REGNUM;
+      cfa_store_reg = cfa_reg;
+      cfa_store_offset = cfa_offset;
+      cfa_temp_reg = -1;
+      cfa_temp_value = 0;
+      return;
+    }
+
+  if (! RTX_FRAME_RELATED_P (insn))
+    {
+      dwarf2out_stack_adjust (insn);
+      return;
+    }
+
+  label = dwarf2out_cfi_label ();
+    
+  src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
+  if (src)
+    insn = XEXP (src, 0);
+  else 
+    insn = PATTERN (insn);
+
+  dwarf2out_frame_debug_expr (insn, label);
+}
+
 /* Return the size of an unsigned LEB128 quantity.  */
 
 static inline unsigned long
@@ -1609,19 +1674,6 @@ output_cfi (cfi, fde)
      }
 }
 
-#if !defined (EH_FRAME_SECTION)
-#if defined (EH_FRAME_SECTION_ASM_OP)
-#define EH_FRAME_SECTION() eh_frame_section();
-#else
-#if defined (ASM_OUTPUT_SECTION_NAME)
-#define EH_FRAME_SECTION()                             \
-  do {                                                 \
-      named_section (NULL_TREE, ".eh_frame", 0);       \
-  } while (0)
-#endif
-#endif
-#endif
-
 /* Output the call frame information used to used to record information
    that relates to calculating the frame pointer, and records the
    location of saved registers.  */
@@ -1654,7 +1706,7 @@ output_call_frame_info (for_eh)
 #else
       tree label = get_file_function_name ('F');
 
-      data_section ();
+      force_data_section ();
       ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
       ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
       ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
@@ -1792,8 +1844,16 @@ output_call_frame_info (for_eh)
       fputc ('\n', asm_out_file);
       ASM_OUTPUT_LABEL (asm_out_file, l1);
 
+      /* ??? This always emits a 4 byte offset when for_eh is true, but it
+        emits a target dependent sized offset when for_eh is not true.
+        This inconsistency may confuse gdb.  The only case where we need a
+        non-4 byte offset is for the Irix6 N64 ABI, so we may lose SGI
+        compatibility if we emit a 4 byte offset.  We need a 4 byte offset
+        though in order to be compatible with the dwarf_fde struct in frame.c.
+        If the for_eh case is changed, then the struct in frame.c has
+        to be adjusted appropriately.  */
       if (for_eh)
-       ASM_OUTPUT_DWARF_DELTA (asm_out_file, l1, "__FRAME_BEGIN__");
+       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, l1, "__FRAME_BEGIN__");
       else
        ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (FRAME_SECTION));
       if (flag_debug_asm)
@@ -1907,9 +1967,7 @@ void
 dwarf2out_frame_init ()
 {
   /* Allocate the initial hunk of the fde_table.  */
-  fde_table
-    = (dw_fde_ref) xmalloc (FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
-  bzero ((char *) fde_table, FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
+  fde_table = (dw_fde_ref) xcalloc (FDE_TABLE_INCREMENT, sizeof (dw_fde_node));
   fde_table_allocated = FDE_TABLE_INCREMENT;
   fde_table_in_use = 0;
 
@@ -1944,8 +2002,6 @@ dwarf2out_frame_finish ()
 /* And now, the support for symbolic debugging information.  */
 #ifdef DWARF2_DEBUGGING_INFO
 
-extern char *getpwd ();
-
 /* NOTE: In the comments in this file, many references are made to
    "Debugging Information Entries".  This term is abbreviated as `DIE'
    throughout the remainder of this file.  */
@@ -1971,7 +2027,7 @@ typedef enum
   dw_val_class_die_ref,
   dw_val_class_fde_ref,
   dw_val_class_lbl_id,
-  dw_val_class_section_offset,
+  dw_val_class_lbl_offset,
   dw_val_class_str
 }
 dw_val_class;
@@ -2050,7 +2106,6 @@ typedef struct dw_val_struct
       unsigned val_fde_index;
       char *val_str;
       char *val_lbl_id;
-      char *val_section;
       unsigned char val_flag;
     }
   v;
@@ -2145,7 +2200,6 @@ limbo_die_node;
 
 extern int flag_traditional;
 extern char *version_string;
-extern char *language_string;
 
 /* Fixed size portion of the DWARF compilation unit header.  */
 #define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
@@ -2160,6 +2214,11 @@ extern char *language_string;
 #define DWARF_ARANGES_HEADER_SIZE \
   (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, PTR_SIZE * 2) - DWARF_OFFSET_SIZE)
 
+/* The default is to have gcc emit the line number tables.  */
+#ifndef DWARF2_ASM_LINE_DEBUG_INFO
+#define DWARF2_ASM_LINE_DEBUG_INFO 0
+#endif
+
 /* Define the architecture-dependent minimum instruction length (in bytes).
    In this implementation of DWARF, this field is used for information
    purposes only.  Since GCC generates assembly language, we have
@@ -2350,6 +2409,22 @@ static unsigned pending_types;
    be enough for most typical programs.         */
 #define PENDING_TYPES_INCREMENT 64
 
+/* A pointer to the base of a list of incomplete types which might be
+   completed at some later time.  */
+
+static tree *incomplete_types_list;
+
+/* Number of elements currently allocated for the incomplete_types_list.  */
+static unsigned incomplete_types_allocated;
+
+/* Number of elements of incomplete_types_list currently in use.  */
+static unsigned incomplete_types;
+
+/* Size (in elements) of increments by which we may expand the incomplete
+   types list.  Actually, a single hunk of space of this size should
+   be enough for most typical programs.         */
+#define INCOMPLETE_TYPES_INCREMENT 64
+
 /* Record whether the function being analyzed contains inlined functions.  */
 static int current_function_has_inlines;
 #if 0 && defined (MIPS_DEBUGGING_INFO)
@@ -2364,17 +2439,17 @@ static tree dwarf_last_decl;
 
 /* Forward declarations for functions defined in this file.  */
 
-static void addr_const_to_string       PROTO((char *, rtx));
+static void addr_const_to_string       PROTO((dyn_string_t, rtx));
 static char *addr_to_string            PROTO((rtx));
 static int is_pseudo_reg               PROTO((rtx));
 static tree type_main_variant          PROTO((tree));
 static int is_tagged_type              PROTO((tree));
-static char *dwarf_tag_name            PROTO((unsigned));
-static char *dwarf_attr_name           PROTO((unsigned));
-static char *dwarf_form_name           PROTO((unsigned));
-static char *dwarf_stack_op_name       PROTO((unsigned));
+static const char *dwarf_tag_name      PROTO((unsigned));
+static const char *dwarf_attr_name     PROTO((unsigned));
+static const char *dwarf_form_name     PROTO((unsigned));
+static const char *dwarf_stack_op_name PROTO((unsigned));
 #if 0
-static char *dwarf_type_encoding_name  PROTO((unsigned));
+static const char *dwarf_type_encoding_name PROTO((unsigned));
 #endif
 static tree decl_ultimate_origin       PROTO((tree));
 static tree block_ultimate_origin      PROTO((tree));
@@ -2395,7 +2470,8 @@ static void add_AT_float          PROTO((dw_die_ref,
                                               enum dwarf_attribute,
                                               unsigned, long *));
 static void add_AT_string              PROTO((dw_die_ref,
-                                              enum dwarf_attribute, char *));
+                                              enum dwarf_attribute,
+                                              const char *));
 static void add_AT_die_ref             PROTO((dw_die_ref,
                                               enum dwarf_attribute,
                                               dw_die_ref));
@@ -2409,7 +2485,7 @@ static void add_AT_addr                   PROTO((dw_die_ref,
                                               enum dwarf_attribute, char *));
 static void add_AT_lbl_id              PROTO((dw_die_ref,
                                               enum dwarf_attribute, char *));
-static void add_AT_section_offset      PROTO((dw_die_ref,
+static void add_AT_lbl_offset          PROTO((dw_die_ref,
                                               enum dwarf_attribute, char *));
 static int is_extern_subr_die          PROTO((dw_die_ref));
 static dw_attr_ref get_AT              PROTO((dw_die_ref,
@@ -2459,7 +2535,7 @@ static void output_loc_operands           PROTO((dw_loc_descr_ref));
 static unsigned long sibling_offset    PROTO((dw_die_ref));
 static void output_die                 PROTO((dw_die_ref));
 static void output_compilation_unit_header PROTO((void));
-static char *dwarf2_name               PROTO((tree, int));
+static const char *dwarf2_name         PROTO((tree, int));
 static void add_pubname                        PROTO((tree, dw_die_ref));
 static void output_pubnames            PROTO((void));
 static void add_arange                 PROTO((tree, dw_die_ref));
@@ -2474,7 +2550,7 @@ static int type_is_enum                   PROTO((tree));
 static dw_loc_descr_ref reg_loc_descriptor PROTO((rtx));
 static dw_loc_descr_ref based_loc_descr        PROTO((unsigned, long));
 static int is_based_loc                        PROTO((rtx));
-static dw_loc_descr_ref mem_loc_descriptor PROTO((rtx));
+static dw_loc_descr_ref mem_loc_descriptor PROTO((rtx, enum machine_mode mode));
 static dw_loc_descr_ref concat_loc_descriptor PROTO((rtx, rtx));
 static dw_loc_descr_ref loc_descriptor PROTO((rtx));
 static unsigned ceiling                        PROTO((unsigned, unsigned));
@@ -2487,7 +2563,7 @@ static void add_AT_location_description   PROTO((dw_die_ref,
 static void add_data_member_location_attribute PROTO((dw_die_ref, tree));
 static void add_const_value_attribute  PROTO((dw_die_ref, rtx));
 static void add_location_or_const_value_attribute PROTO((dw_die_ref, tree));
-static void add_name_attribute         PROTO((dw_die_ref, char *));
+static void add_name_attribute         PROTO((dw_die_ref, const char *));
 static void add_bound_info             PROTO((dw_die_ref,
                                               enum dwarf_attribute, tree));
 static void add_subscript_info         PROTO((dw_die_ref, tree));
@@ -2543,7 +2619,9 @@ static void gen_block_die         PROTO((tree, dw_die_ref, int));
 static void decls_for_scope            PROTO((tree, dw_die_ref, int));
 static int is_redundant_typedef                PROTO((tree));
 static void gen_decl_die               PROTO((tree, dw_die_ref));
-static unsigned lookup_filename                PROTO((char *));
+static unsigned lookup_filename                PROTO((const char *));
+static void add_incomplete_type                PROTO((tree));
+static void retry_incomplete_types     PROTO((void));
 
 /* Section names used to hold DWARF debugging information.  */
 #ifndef DEBUG_INFO_SECTION
@@ -2582,6 +2660,22 @@ static unsigned lookup_filename          PROTO((char *));
 #define BSS_SECTION            ".bss"
 #endif
 
+/* Labels we insert at beginning sections we can reference instead of
+   the section names themselves. */
+
+#ifndef TEXT_SECTION_LABEL
+#define TEXT_SECTION_LABEL      "Ltext"
+#endif
+#ifndef DEBUG_LINE_SECTION_LABEL
+#define DEBUG_LINE_SECTION_LABEL "Ldebug_line"
+#endif
+#ifndef DEBUG_INFO_SECTION_LABEL
+#define DEBUG_INFO_SECTION_LABEL "Ldebug_info"
+#endif
+#ifndef ABBREV_SECTION_LABEL
+#define ABBREV_SECTION_LABEL     "Ldebug_abbrev"
+#endif
+
 
 /* Definitions of defaults for formats and names of various special
    (artificial) labels which may be generated within this file (when the -g
@@ -2590,6 +2684,10 @@ static unsigned lookup_filename          PROTO((char *));
    typically, overriding these defaults is unnecessary.  */
 
 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 
 #ifndef TEXT_END_LABEL
 #define TEXT_END_LABEL         "Letext"
@@ -2626,13 +2724,18 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
    macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
    a string rather than writing to a file.  */
 #ifndef ASM_NAME_TO_STRING
-#define ASM_NAME_TO_STRING(STR, NAME) \
-  do {                                                                       \
-      if ((NAME)[0] == '*')                                                  \
-       strcpy (STR, NAME+1);                                                 \
-      else                                                                   \
-       strcpy (STR, NAME);                                                   \
-  }                                                                           \
+#define ASM_NAME_TO_STRING(STR, NAME)                  \
+  do {                                                 \
+      if ((NAME)[0] == '*')                            \
+       dyn_string_append (STR, NAME + 1);              \
+      else                                             \
+       {                                               \
+         const char *newstr;                           \
+         STRIP_NAME_ENCODING (newstr, NAME);           \
+         dyn_string_append (STR, user_label_prefix);   \
+         dyn_string_append (STR, newstr);              \
+       }                                               \
+  }                                                    \
   while (0)
 #endif
 \f
@@ -2644,50 +2747,44 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 
 static void
 addr_const_to_string (str, x)
-     char *str;
+     dyn_string_t str;
      rtx x;
 {
   char buf1[256];
-  char buf2[256];
 
 restart:
-  str[0] = '\0';
   switch (GET_CODE (x))
     {
     case PC:
       if (flag_pic)
-       strcat (str, ",");
+       dyn_string_append (str, ",");
       else
        abort ();
       break;
 
     case SYMBOL_REF:
-      ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
-      strcat (str, buf1);
+      ASM_NAME_TO_STRING (str, XSTR (x, 0));
       break;
 
     case LABEL_REF:
       ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
-      ASM_NAME_TO_STRING (buf2, buf1);
-      strcat (str, buf2);
+      ASM_NAME_TO_STRING (str, buf1);
       break;
 
     case CODE_LABEL:
       ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
-      ASM_NAME_TO_STRING (buf2, buf1);
-      strcat (str, buf2);
+      ASM_NAME_TO_STRING (str, buf1);
       break;
 
     case CONST_INT:
       sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
-      strcat (str, buf1);
+      dyn_string_append (str, buf1);
       break;
 
     case CONST:
       /* This used to output parentheses around the expression, but that does 
          not work on the 386 (either ATT or BSD assembler).  */
-      addr_const_to_string (buf1, XEXP (x, 0));
-      strcat (str, buf1);
+      addr_const_to_string (str, XEXP (x, 0));
       break;
 
     case CONST_DOUBLE:
@@ -2702,7 +2799,7 @@ restart:
          else
            sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
                     CONST_DOUBLE_LOW (x));
-         strcat (str, buf1);
+         dyn_string_append (str, buf1);
        }
       else
        /* We can't handle floating point constants; PRINT_OPERAND must
@@ -2714,23 +2811,19 @@ restart:
       /* Some assemblers need integer constants to appear last (eg masm).  */
       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
        {
-         addr_const_to_string (buf1, XEXP (x, 1));
-         strcat (str, buf1);
+         addr_const_to_string (str, XEXP (x, 1));
          if (INTVAL (XEXP (x, 0)) >= 0)
-           strcat (str, "+");
+           dyn_string_append (str, "+");
 
-         addr_const_to_string (buf1, XEXP (x, 0));
-         strcat (str, buf1);
+         addr_const_to_string (str, XEXP (x, 0));
        }
       else
        {
-         addr_const_to_string (buf1, XEXP (x, 0));
-         strcat (str, buf1);
+         addr_const_to_string (str, XEXP (x, 0));
          if (INTVAL (XEXP (x, 1)) >= 0)
-           strcat (str, "+");
+           dyn_string_append (str, "+");
 
-         addr_const_to_string (buf1, XEXP (x, 1));
-         strcat (str, buf1);
+         addr_const_to_string (str, XEXP (x, 1));
        }
       break;
 
@@ -2741,28 +2834,22 @@ restart:
       if (GET_CODE (x) != MINUS)
        goto restart;
 
-      addr_const_to_string (buf1, XEXP (x, 0));
-      strcat (str, buf1);
-      strcat (str, "-");
+      addr_const_to_string (str, XEXP (x, 0));
+      dyn_string_append (str, "-");
       if (GET_CODE (XEXP (x, 1)) == CONST_INT
          && INTVAL (XEXP (x, 1)) < 0)
        {
-         strcat (str, ASM_OPEN_PAREN);
-         addr_const_to_string (buf1, XEXP (x, 1));
-         strcat (str, buf1);
-         strcat (str, ASM_CLOSE_PAREN);
+         dyn_string_append (str, ASM_OPEN_PAREN);
+         addr_const_to_string (str, XEXP (x, 1));
+         dyn_string_append (str, ASM_CLOSE_PAREN);
        }
       else
-       {
-         addr_const_to_string (buf1, XEXP (x, 1));
-         strcat (str, buf1);
-       }
+       addr_const_to_string (str, XEXP (x, 1));
       break;
 
     case ZERO_EXTEND:
     case SIGN_EXTEND:
-      addr_const_to_string (buf1, XEXP (x, 0));
-      strcat (str, buf1);
+      addr_const_to_string (str, XEXP (x, 0));
       break;
 
     default:
@@ -2777,9 +2864,16 @@ static char *
 addr_to_string (x)
      rtx x;
 {
-  char buf[1024];
-  addr_const_to_string (buf, x);
-  return xstrdup (buf);
+  dyn_string_t ds = dyn_string_new (256);
+  char *s;
+
+  addr_const_to_string (ds, x);
+  
+  /* Return the dynamically allocated string, but free the
+     dyn_string_t itself.  */
+  s = ds->s;
+  free (ds);
+  return s;
 }
 
 /* Test if rtl node points to a pseudo register.  */
@@ -2828,7 +2922,7 @@ is_tagged_type (type)
 
 /* Convert a DIE tag into its string name.  */
 
-static char *
+static const char *
 dwarf_tag_name (tag)
      register unsigned tag;
 {
@@ -2945,7 +3039,7 @@ dwarf_tag_name (tag)
 
 /* Convert a DWARF attribute code into its string name.  */
 
-static char *
+static const char *
 dwarf_attr_name (attr)
      register unsigned attr;
 {
@@ -3118,7 +3212,7 @@ dwarf_attr_name (attr)
 
 /* Convert a DWARF value form code into its string name.  */
 
-static char *
+static const char *
 dwarf_form_name (form)
      register unsigned form;
 {
@@ -3173,7 +3267,7 @@ dwarf_form_name (form)
 
 /* Convert a DWARF stack opcode into its string name.  */
 
-static char *
+static const char *
 dwarf_stack_op_name (op)
      register unsigned op;
 {
@@ -3477,7 +3571,7 @@ dwarf_stack_op_name (op)
 /* Convert a DWARF type code into its string name.  */
 
 #if 0
-static char *
+static const char *
 dwarf_type_encoding_name (enc)
      register unsigned enc;
 {
@@ -3515,24 +3609,14 @@ static tree
 decl_ultimate_origin (decl)
      register tree decl;
 {
-  register tree immediate_origin = DECL_ABSTRACT_ORIGIN (decl);
-
-  if (immediate_origin == NULL_TREE)
-    return NULL_TREE;
-  else
-    {
-      register tree ret_val;
-      register tree lookahead = immediate_origin;
-
-      do
-       {
-         ret_val = lookahead;
-         lookahead = DECL_ABSTRACT_ORIGIN (ret_val);
-       }
-      while (lookahead != NULL && lookahead != ret_val);
+#ifdef ENABLE_CHECKING 
+  if (DECL_FROM_INLINE (DECL_ORIGIN (decl)))
+    /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
+       most distant ancestor, this should never happen.  */
+    abort ();
+#endif
 
-      return ret_val;
-    }
+  return DECL_ABSTRACT_ORIGIN (decl);
 }
 
 /* Determine the "ultimate origin" of a block.  The block may be an inlined
@@ -3706,7 +3790,7 @@ static inline void
 add_AT_string (die, attr_kind, str)
      register dw_die_ref die;
      register enum dwarf_attribute attr_kind;
-     register char *str;
+     register const char *str;
 {
   register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
@@ -3805,17 +3889,17 @@ add_AT_lbl_id (die, attr_kind, lbl_id)
 /* Add a section offset attribute value to a DIE.  */
 
 static inline void
-add_AT_section_offset (die, attr_kind, section)
+add_AT_lbl_offset (die, attr_kind, label)
      register dw_die_ref die;
      register enum dwarf_attribute attr_kind;
-     register char *section;
+     register char *label;
 {
   register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
-  attr->dw_attr_val.val_class = dw_val_class_section_offset;
-  attr->dw_attr_val.v.val_section = section;
+  attr->dw_attr_val.val_class = dw_val_class_lbl_offset;
+  attr->dw_attr_val.v.val_lbl_id = label;
   add_dwarf_attr (die, attr);
   
 }
@@ -3984,7 +4068,7 @@ remove_AT (die, attr_kind)
      register enum dwarf_attribute attr_kind;
 {
   register dw_attr_ref a;
-  register dw_attr_ref removed = NULL;;
+  register dw_attr_ref removed = NULL;
 
   if (die != NULL)
     {
@@ -4278,11 +4362,9 @@ print_die (die, outfile)
            fprintf (outfile, "die -> <null>");
          break;
        case dw_val_class_lbl_id:
+       case dw_val_class_lbl_offset:
          fprintf (outfile, "label: %s", a->dw_attr_val.v.val_lbl_id);
          break;
-       case dw_val_class_section_offset:
-         fprintf (outfile, "section: %s", a->dw_attr_val.v.val_section);
-         break;
        case dw_val_class_str:
          if (a->dw_attr_val.v.val_str != NULL)
            fprintf (outfile, "\"%s\"", a->dw_attr_val.v.val_str);
@@ -4346,7 +4428,8 @@ debug_dwarf ()
 {
   print_indent = 0;
   print_die (comp_unit_die, stderr);
-  print_dwarf_line_table (stderr);
+  if (! DWARF2_ASM_LINE_DEBUG_INFO)
+    print_dwarf_line_table (stderr);
 }
 \f
 /* Traverse the DIE, and add a sibling attribute if it may have the
@@ -4444,29 +4527,18 @@ build_abbrev_table (die)
     build_abbrev_table (c);
 }
 \f
-/* Return the size of a string, including the null byte.  */
+/* Return the size of a string, including the null byte.
+
+   This used to treat backslashes as escapes, and hence they were not included
+   in the count.  However, that conflicts with what ASM_OUTPUT_ASCII does,
+   which treats a backslash as a backslash, escaping it if necessary, and hence
+   we must include them in the count.  */
 
 static unsigned long
 size_of_string (str)
      register char *str;
 {
-  register unsigned long size = 0;
-  register unsigned long slen = strlen (str);
-  register unsigned long i;
-  register unsigned c;
-
-  for (i = 0; i < slen; ++i)
-    {
-      c = str[i];
-      if (c == '\\')
-       ++i;
-
-      size += 1;
-    }
-
-  /* Null terminator.  */
-  size += 1;
-  return size;
+  return strlen (str) + 1;
 }
 
 /* Return the size of a location descriptor.  */
@@ -4657,7 +4729,7 @@ size_of_die (die)
        case dw_val_class_lbl_id:
          size += PTR_SIZE;
          break;
-       case dw_val_class_section_offset:
+       case dw_val_class_lbl_offset:
          size += DWARF_OFFSET_SIZE;
          break;
        case dw_val_class_str:
@@ -4759,14 +4831,15 @@ size_of_line_info ()
   /* Prolog.  */
   size += size_of_line_prolog ();
 
-  /* Set address register instruction.  */
-  size += size_of_set_address;
-
   current_file = 1;
   current_line = 1;
   for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
     {
-      register dw_line_info_ref line_info;
+      register dw_line_info_ref line_info = &line_info_table[lt_index];
+
+      if (line_info->dw_line_num == current_line
+         && line_info->dw_file_num == current_file)
+       continue;
 
       /* Advance pc instruction.  */
       /* ??? See the DW_LNS_advance_pc comment in output_line_info.  */
@@ -4775,7 +4848,6 @@ size_of_line_info ()
       else
        size += size_of_set_address;
 
-      line_info = &line_info_table[lt_index];
       if (line_info->dw_file_num != current_file)
        {
          /* Set file number instruction.  */
@@ -4819,6 +4891,12 @@ size_of_line_info ()
     {
       register dw_separate_line_info_ref line_info
        = &separate_line_info_table[lt_index];
+
+      if (line_info->dw_line_num == current_line
+         && line_info->dw_file_num == current_file
+         && line_info->function == function)
+       goto cont;
+
       if (function != line_info->function)
        {
          function = line_info->function;
@@ -4861,6 +4939,7 @@ size_of_line_info ()
            }
        }
 
+    cont:
       ++lt_index;
 
       /* If we're done with a function, end its sequence.  */
@@ -4970,7 +5049,7 @@ value_format (v)
       return DW_FORM_data;
     case dw_val_class_lbl_id:
       return DW_FORM_addr;
-    case dw_val_class_section_offset:
+    case dw_val_class_lbl_offset:
       return DW_FORM_data;
     case dw_val_class_str:
       return DW_FORM_string;
@@ -5043,6 +5122,9 @@ output_abbrev_section ()
 
       fprintf (asm_out_file, "\t%s\t0,0\n", ASM_BYTE_OP);
     }
+
+  /* Terminate the table.  */
+  fprintf (asm_out_file, "\t%s\t0\n", ASM_BYTE_OP);
 }
 
 /* Output location description stack opcode's operands (if any).  */
@@ -5192,7 +5274,6 @@ 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_debug_asm)
@@ -5295,24 +5376,27 @@ output_die (die)
          break;
 
        case dw_val_class_float:
-         ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
-                                 a->dw_attr_val.v.val_float.length * 4);
-         if (flag_debug_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_debug_asm)
-               fprintf (asm_out_file, "\t%s fp constant word %d",
-                        ASM_COMMENT_START, i);
+         {
+           register unsigned int i;
+           ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+                                   a->dw_attr_val.v.val_float.length * 4);
+           if (flag_debug_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_debug_asm)
+                 fprintf (asm_out_file, "\t%s fp constant word %u",
+                          ASM_COMMENT_START, i);
 
-             fputc ('\n', asm_out_file);
-           }
+               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);
@@ -5343,10 +5427,8 @@ output_die (die)
          ASM_OUTPUT_DWARF_ADDR (asm_out_file, a->dw_attr_val.v.val_lbl_id);
          break;
 
-       case dw_val_class_section_offset:
-         ASM_OUTPUT_DWARF_OFFSET (asm_out_file,
-                                  stripattributes
-                                  (a->dw_attr_val.v.val_section));
+       case dw_val_class_lbl_offset:
+         ASM_OUTPUT_DWARF_OFFSET (asm_out_file, a->dw_attr_val.v.val_lbl_id);
          break;
 
        case dw_val_class_str:
@@ -5355,7 +5437,7 @@ output_die (die)
          else
            ASM_OUTPUT_ASCII (asm_out_file,
                              a->dw_attr_val.v.val_str,
-                             strlen (a->dw_attr_val.v.val_str) + 1);
+                             (int) strlen (a->dw_attr_val.v.val_str) + 1);
          break;
 
        default:
@@ -5406,7 +5488,7 @@ output_compilation_unit_header ()
     fprintf (asm_out_file, "\t%s DWARF version number", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
-  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (ABBREV_SECTION));
+  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, abbrev_section_label);
   if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Offset Into Abbrev. Section",
             ASM_COMMENT_START);
@@ -5423,7 +5505,7 @@ output_compilation_unit_header ()
    of decl_printable_name for C++ looks like "A::f(int)".  Let's drop the
    argument list, and maybe the scope.  */
 
-static char *
+static const char *
 dwarf2_name (decl, scope)
      tree decl;
      int scope;
@@ -5479,7 +5561,7 @@ output_pubnames ()
     fprintf (asm_out_file, "\t%s DWARF Version", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
-  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (DEBUG_INFO_SECTION));
+  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, debug_info_section_label);
   if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.",
             ASM_COMMENT_START);
@@ -5507,7 +5589,8 @@ output_pubnames ()
        }
       else
        {
-         ASM_OUTPUT_ASCII (asm_out_file, pub->name, strlen (pub->name) + 1);
+         ASM_OUTPUT_ASCII (asm_out_file, pub->name,
+                           (int) strlen (pub->name) + 1);
        }
 
       fputc ('\n', asm_out_file);
@@ -5559,7 +5642,7 @@ output_aranges ()
     fprintf (asm_out_file, "\t%s DWARF Version", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
-  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (DEBUG_INFO_SECTION));
+  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, debug_info_section_label);
   if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.",
             ASM_COMMENT_START);
@@ -5576,8 +5659,14 @@ output_aranges ()
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
-  ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 4);
-  if (PTR_SIZE == 8)
+  /* We need to align to twice the pointer size here.
+     If DWARF_OFFSET_SIZE == 4, then we have emitted 12 bytes, and need 4
+     bytes of padding to align for either 4 or 8 byte pointers.  */
+  ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
+  /* If DWARF_OFFSET_SIZE == 8, then we have emitted 20 bytes, and need 12
+     bytes of padding to align for 8 byte pointers.  We have already emitted
+     4 bytes of padding, so emit 8 more here.  */
+  if (DWARF_OFFSET_SIZE == 8)
     fprintf (asm_out_file, ",0,0");
 
   if (flag_debug_asm)
@@ -5585,12 +5674,13 @@ output_aranges ()
             ASM_COMMENT_START, 2 * PTR_SIZE);
 
   fputc ('\n', asm_out_file);
-  ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_SECTION);
+  ASM_OUTPUT_DWARF_ADDR (asm_out_file, text_section_label);
   if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Address", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
-  ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, text_end_label, TEXT_SECTION);
+  ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, text_end_label,
+                              text_section_label);
   if (flag_debug_asm)
     fprintf (asm_out_file, "%s Length", ASM_COMMENT_START);
 
@@ -5743,7 +5833,7 @@ output_line_info ()
        {
          ASM_OUTPUT_ASCII (asm_out_file,
                            file_table[ft_index],
-                           strlen (file_table[ft_index]) + 1);
+                           (int) strlen (file_table[ft_index]) + 1);
        }
 
       fputc ('\n', asm_out_file);
@@ -5765,27 +5855,25 @@ output_line_info ()
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
   fputc ('\n', asm_out_file);
 
-  /* Set the address register to the first location in the text section */
-  ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-  if (flag_debug_asm)
-    fprintf (asm_out_file, "\t%s DW_LNE_set_address", ASM_COMMENT_START);
-
-  fputc ('\n', asm_out_file);
-  output_uleb128 (1 + PTR_SIZE);
-  fputc ('\n', asm_out_file);
-  ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address);
-  fputc ('\n', asm_out_file);
-  ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_SECTION);
-  fputc ('\n', asm_out_file);
+  /* We used to set the address register to the first location in the text
+     section here, but that didn't accomplish anything since we already
+     have a line note for the opening brace of the first function.  */
 
   /* Generate the line number to PC correspondence table, encoded as
      a series of state machine operations.  */
   current_file = 1;
   current_line = 1;
-  strcpy (prev_line_label, TEXT_SECTION);
+  strcpy (prev_line_label, text_section_label);
   for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
     {
-      register dw_line_info_ref line_info;
+      register dw_line_info_ref line_info = &line_info_table[lt_index];
+
+      /* Don't emit anything for redundant notes.  Just updating the
+         address doesn't accomplish anything, because we already assume
+         that anything after the last address is this line.  */
+      if (line_info->dw_line_num == current_line
+         && line_info->dw_file_num == current_file)
+       continue;
 
       /* Emit debug info for the address of the current line, choosing
         the encoding that uses the least amount of space.  */
@@ -5829,7 +5917,6 @@ output_line_info ()
 
       /* Emit debug info for the source file of the current line, if
         different from the previous line.  */
-      line_info = &line_info_table[lt_index];
       if (line_info->dw_file_num != current_file)
        {
          current_file = line_info->dw_file_num;
@@ -5847,35 +5934,48 @@ output_line_info ()
 
       /* Emit debug info for the current line number, choosing the encoding
         that uses the least amount of space.  */
-      line_offset = line_info->dw_line_num - current_line;
-      line_delta = line_offset - DWARF_LINE_BASE;
-      current_line = line_info->dw_line_num;
-      if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
+      if (line_info->dw_line_num != current_line)
        {
-         /* This can handle deltas from -10 to 234, using the current
-            definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE.  This
-            takes 1 byte.  */
-         ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
-                                 DWARF_LINE_OPCODE_BASE + line_delta);
-         if (flag_debug_asm)
-             fprintf (asm_out_file,
-                      "\t%s line %ld", ASM_COMMENT_START, current_line);
+         line_offset = line_info->dw_line_num - current_line;
+         line_delta = line_offset - DWARF_LINE_BASE;
+         current_line = line_info->dw_line_num;
+         if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
+           {
+             /* This can handle deltas from -10 to 234, using the current
+                definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE.  This
+                takes 1 byte.  */
+             ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+                                     DWARF_LINE_OPCODE_BASE + line_delta);
+             if (flag_debug_asm)
+               fprintf (asm_out_file,
+                        "\t%s line %ld", ASM_COMMENT_START, current_line);
 
-         fputc ('\n', asm_out_file);
+             fputc ('\n', asm_out_file);
+           }
+         else
+           {
+             /* This can handle any delta.  This takes at least 4 bytes,
+                depending on the value being encoded.  */
+             ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
+             if (flag_debug_asm)
+               fprintf (asm_out_file, "\t%s advance to line %ld",
+                        ASM_COMMENT_START, current_line);
+
+             fputc ('\n', asm_out_file);
+             output_sleb128 (line_offset);
+             fputc ('\n', asm_out_file);
+             ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+             if (flag_debug_asm)
+               fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
+             fputc ('\n', asm_out_file);
+           }
        }
       else
        {
-         /* This can handle any delta.  This takes at least 4 bytes, depending
-            on the value being encoded.  */
-         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
-         if (flag_debug_asm)
-           fprintf (asm_out_file, "\t%s advance to line %ld",
-                    ASM_COMMENT_START, current_line);
-
-         fputc ('\n', asm_out_file);
-         output_sleb128 (line_offset);
-         fputc ('\n', asm_out_file);
+         /* We still need to start a new row, so output a copy insn.  */
          ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+         if (flag_debug_asm)
+           fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
          fputc ('\n', asm_out_file);
        }
     }
@@ -5925,6 +6025,12 @@ output_line_info ()
       register dw_separate_line_info_ref line_info
        = &separate_line_info_table[lt_index];
 
+      /* Don't emit anything for redundant notes.  */
+      if (line_info->dw_line_num == current_line
+         && line_info->dw_file_num == current_file
+         && line_info->function == function)
+       goto cont;
+
       /* Emit debug info for the address of the current line.  If this is
         a new function, or the first line of a function, then we need
         to handle it differently.  */
@@ -6025,10 +6131,21 @@ output_line_info ()
              output_sleb128 (line_offset);
              fputc ('\n', asm_out_file);
              ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+             if (flag_debug_asm)
+               fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
              fputc ('\n', asm_out_file);
            }
        }
+      else
+       {
+         /* We still need to start a new row, so output a copy insn.  */
+         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+         if (flag_debug_asm)
+           fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
+         fputc ('\n', asm_out_file);
+       }
 
+    cont:
       ++lt_index;
 
       /* If we're done with a function, end its sequence.  */
@@ -6183,7 +6300,7 @@ base_type_die (type)
   base_type_result = new_die (DW_TAG_base_type, comp_unit_die);
   add_AT_string (base_type_result, DW_AT_name, type_name);
   add_AT_unsigned (base_type_result, DW_AT_byte_size,
-                  TYPE_PRECISION (type) / BITS_PER_UNIT);
+                  int_size_in_bytes (type));
   add_AT_unsigned (base_type_result, DW_AT_encoding, encoding);
 
   return base_type_result;
@@ -6441,11 +6558,15 @@ is_based_loc (rtl)
    When creating memory location descriptors, we are effectively transforming
    the RTL for a memory-resident object into its Dwarf postfix expression
    equivalent.  This routine recursively descends an RTL tree, turning
-   it into Dwarf postfix code as it goes.  */
+   it into Dwarf postfix code as it goes.
+
+   MODE is the mode of the memory reference, needed to handle some
+   autoincrement addressing modes.  */
 
 static dw_loc_descr_ref
-mem_loc_descriptor (rtl)
+mem_loc_descriptor (rtl, mode)
      register rtx rtl;
+     enum machine_mode mode;
 {
   dw_loc_descr_ref mem_loc_result = NULL;
   /* Note that for a dynamically sized array, the location we will generate a 
@@ -6455,6 +6576,13 @@ mem_loc_descriptor (rtl)
 
   switch (GET_CODE (rtl))
     {
+    case POST_INC:
+    case POST_DEC:
+      /* POST_INC and POST_DEC can be handled just like a SUBREG.  So we
+        just fall into the SUBREG code.  */
+
+      /* ... fall through ... */
+
     case SUBREG:
       /* The case of a subreg may arise when we have a local (register)
          variable or a formal (register) parameter which doesn't quite fill
@@ -6483,10 +6611,14 @@ mem_loc_descriptor (rtl)
       break;
 
     case MEM:
-      mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0));
+      mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
       add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
       break;
 
+     case LABEL_REF:
+       /* Some ports can transform a symbol ref into a label ref, because
+        the symbol ref is too far away and has to be dumped into a constant
+        pool.  */
     case CONST:
     case SYMBOL_REF:
       mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
@@ -6494,14 +6626,27 @@ mem_loc_descriptor (rtl)
       mem_loc_result->dw_loc_oprnd1.v.val_addr = addr_to_string (rtl);
       break;
 
+    case PRE_INC:
+    case PRE_DEC:
+      /* Turn these into a PLUS expression and fall into the PLUS code
+        below.  */
+      rtl = gen_rtx_PLUS (word_mode, XEXP (rtl, 0),
+                         GEN_INT (GET_CODE (rtl) == PRE_INC
+                                  ? GET_MODE_UNIT_SIZE (mode) 
+                                  : - GET_MODE_UNIT_SIZE (mode)));
+                         
+      /* ... fall through ... */
+
     case PLUS:
       if (is_based_loc (rtl))
        mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)),
                                          INTVAL (XEXP (rtl, 1)));
       else
        {
-         add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0)));
-         add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1)));
+         add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0),
+                                                             mode));
+         add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1),
+                                                             mode));
          add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_plus, 0, 0));
        }
       break;
@@ -6509,8 +6654,8 @@ mem_loc_descriptor (rtl)
     case MULT:
       /* If a pseudo-reg is optimized away, it is possible for it to
         be replaced with a MEM containing a multiply.  */
-      add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0)));
-      add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1)));
+      add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0), mode));
+      add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1), mode));
       add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
       break;
 
@@ -6577,7 +6722,7 @@ loc_descriptor (rtl)
       break;
 
     case MEM:
-      loc_result = mem_loc_descriptor (XEXP (rtl, 0));
+      loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
       break;
 
     case CONCAT:
@@ -7062,9 +7207,42 @@ add_location_or_const_value_attribute (die, decl)
            rtl = DECL_INCOMING_RTL (decl);
          else if (! BYTES_BIG_ENDIAN
                   && TREE_CODE (declared_type) == INTEGER_TYPE
-                  && TYPE_SIZE (declared_type) <= TYPE_SIZE (passed_type))
+                  && (GET_MODE_SIZE (TYPE_MODE (declared_type))
+                      <= GET_MODE_SIZE (TYPE_MODE (passed_type))))
                rtl = DECL_INCOMING_RTL (decl);
        }
+
+      /* If the parm was passed in registers, but lives on the stack, then
+        make a big endian correction if the mode of the type of the
+        parameter is not the same as the mode of the rtl.  */
+      /* ??? This is the same series of checks that are made in dbxout.c before
+        we reach the big endian correction code there.  It isn't clear if all
+        of these checks are necessary here, but keeping them all is the safe
+        thing to do.  */
+      else if (GET_CODE (rtl) == MEM
+              && XEXP (rtl, 0) != const0_rtx
+              && ! CONSTANT_P (XEXP (rtl, 0))
+              /* Not passed in memory.  */
+              && GET_CODE (DECL_INCOMING_RTL (decl)) != MEM
+              /* Not passed by invisible reference.  */
+              && (GET_CODE (XEXP (rtl, 0)) != REG
+                  || REGNO (XEXP (rtl, 0)) == HARD_FRAME_POINTER_REGNUM
+                  || REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+                  || REGNO (XEXP (rtl, 0)) == ARG_POINTER_REGNUM
+#endif
+                    )
+              /* Big endian correction check.  */
+              && BYTES_BIG_ENDIAN
+              && TYPE_MODE (TREE_TYPE (decl)) != GET_MODE (rtl)
+              && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))
+                  < UNITS_PER_WORD))
+       {
+         int offset = (UNITS_PER_WORD
+                       - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))));
+         rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
+                            plus_constant (XEXP (rtl, 0), offset));
+       }
     }
 
   if (rtl == NULL_RTX)
@@ -7072,7 +7250,7 @@ add_location_or_const_value_attribute (die, decl)
 
   rtl = eliminate_regs (rtl, 0, NULL_RTX);
 #ifdef LEAF_REG_REMAP
-  if (leaf_function)
+  if (current_function_uses_only_leaf_regs)
     leaf_renumber_regs_insn (rtl);
 #endif
 
@@ -7112,7 +7290,7 @@ add_location_or_const_value_attribute (die, decl)
 static inline void
 add_name_attribute (die, name_string)
      register dw_die_ref die;
-     register char *name_string;
+     register const char *name_string;
 {
   if (name_string != NULL && *name_string != 0)
     add_AT_string (die, DW_AT_name, name_string);
@@ -7194,7 +7372,7 @@ add_bound_info (subrange_die, bound_attr, bound)
              rtx new_addr = fix_lexical_addr (XEXP (loc, 0), bound);
 
              if (XEXP (loc, 0) != new_addr)
-               loc = gen_rtx (MEM, GET_MODE (loc), new_addr);
+               loc = gen_rtx_MEM (GET_MODE (loc), new_addr);
            }
 
          add_AT_flag (decl_die, DW_AT_artificial, 1);
@@ -7537,7 +7715,7 @@ push_decl_scope (scope)
      subtype.  In such a case, we need to search the decl_scope_table to
      find the parent of this subtype.  */
 
-  if (TREE_CODE_CLASS (TREE_CODE (scope)) == 't')
+  if (AGGREGATE_TYPE_P (scope))
     containing_scope = TYPE_CONTEXT (scope);
   else
     containing_scope = NULL_TREE;
@@ -7589,6 +7767,12 @@ scope_die_for (t, context_die)
   if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL)
     containing_scope = NULL_TREE;
 
+  /* Ignore function type "scopes" from the C frontend.  They mean that
+     a tagged type is local to a parmlist of a function declarator, but
+     that isn't useful to DWARF.  */
+  if (containing_scope && TREE_CODE (containing_scope) == FUNCTION_TYPE)
+    containing_scope = NULL_TREE;
+
   /* Function-local tags and functions get stuck in limbo until they are
      fixed up by decls_for_scope.  */
   if (context_die == NULL && containing_scope != NULL_TREE
@@ -7625,12 +7809,14 @@ scope_die_for (t, context_die)
 
       if (i < 0)
        {
-         if (scope_die != comp_unit_die
-             || TREE_CODE_CLASS (TREE_CODE (containing_scope)) != 't')
+         if (TREE_CODE_CLASS (TREE_CODE (containing_scope)) != 't')
            abort ();
          if (debug_info_level > DINFO_LEVEL_TERSE
              && !TREE_ASM_WRITTEN (containing_scope))
            abort ();
+
+         /* If none of the current dies are suitable, we get file scope.  */
+         scope_die = comp_unit_die;
        }
     }
 
@@ -7890,6 +8076,39 @@ output_pending_types_for_scope (context_die)
     }
 }
 
+/* Remember a type in the incomplete_types_list.  */
+
+static void
+add_incomplete_type (type)
+     tree type;
+{
+  if (incomplete_types == incomplete_types_allocated)
+    {
+      incomplete_types_allocated += INCOMPLETE_TYPES_INCREMENT;
+      incomplete_types_list
+       = (tree *) xrealloc (incomplete_types_list,
+                            sizeof (tree) * incomplete_types_allocated);
+    }
+
+  incomplete_types_list[incomplete_types++] = type;
+}
+
+/* Walk through the list of incomplete types again, trying once more to
+   emit full debugging info for them.  */
+
+static void
+retry_incomplete_types ()
+{
+  register tree type;
+
+  while (incomplete_types)
+    {
+      --incomplete_types;
+      type = incomplete_types_list[incomplete_types];
+      gen_type_die (type, comp_unit_die);
+    }
+}
+
 /* Generate a DIE to represent an inlined instance of an enumeration type.  */
 
 static void
@@ -8054,7 +8273,7 @@ gen_formal_parameter_die (node, context_die)
 
 static void
 gen_unspecified_parameters_die (decl_or_type, context_die)
-     register tree decl_or_type;
+     register tree decl_or_type ATTRIBUTE_UNUSED;
      register dw_die_ref context_die;
 {
   new_die (DW_TAG_unspecified_parameters, context_die);
@@ -8171,7 +8390,16 @@ gen_subprogram_die (decl, context_die)
        = lookup_filename (DECL_SOURCE_FILE (decl));
 
       if (get_AT_flag (old_die, DW_AT_declaration) != 1)
-       abort ();
+       {
+         /* ??? This can happen if there is a bug in the program, for
+            instance, if it has duplicate function definitions.  Ideally,
+            we should detect this case and ignore it.  For now, if we have
+            already reported an error, any error at all, then assume that
+            we got here because of a input error, not a dwarf2 bug.  */
+         if (errorcount)
+           return;
+         abort ();
+       }
 
       /* If the definition comes from the same place as the declaration,
         maybe use the old DIE.  We always want the DIE for this function
@@ -8184,7 +8412,7 @@ gen_subprogram_die (decl, context_die)
           || context_die == NULL)
          && get_AT_unsigned (old_die, DW_AT_decl_file) == file_index
          && (get_AT_unsigned (old_die, DW_AT_decl_line)
-             == DECL_SOURCE_LINE (decl)))
+             == (unsigned)DECL_SOURCE_LINE (decl)))
        {
          subr_die = old_die;
 
@@ -8199,7 +8427,7 @@ gen_subprogram_die (decl, context_die)
          if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index)
            add_AT_unsigned (subr_die, DW_AT_decl_file, file_index);
          if (get_AT_unsigned (old_die, DW_AT_decl_line)
-             != DECL_SOURCE_LINE (decl))
+             != (unsigned)DECL_SOURCE_LINE (decl))
            add_AT_unsigned
              (subr_die, DW_AT_decl_line, DECL_SOURCE_LINE (decl));
        }
@@ -8436,7 +8664,7 @@ gen_variable_die (decl, context_die)
            add_AT_unsigned (var_die, DW_AT_decl_file, file_index);
 
          if (get_AT_unsigned (old_die, DW_AT_decl_line)
-             != DECL_SOURCE_LINE (decl))
+             != (unsigned)DECL_SOURCE_LINE (decl))
 
            add_AT_unsigned (var_die, DW_AT_decl_line,
                             DECL_SOURCE_LINE (decl));
@@ -8499,7 +8727,13 @@ gen_label_die (decl, context_die)
   else
     {
       insn = DECL_RTL (decl);
-      if (GET_CODE (insn) == CODE_LABEL)
+
+      /* Deleted labels are programmer specified labels which have been
+        eliminated because of various optimisations.  We still emit them
+        here so that it is possible to put breakpoints on them.  */
+      if (GET_CODE (insn) == CODE_LABEL
+         || ((GET_CODE (insn) == NOTE
+              && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
        {
          /* When optimization is enabled (via -O) some parts of the compiler 
             (e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which 
@@ -8806,7 +9040,7 @@ gen_struct_or_union_type_die (type, context_die)
     return;
 
   if (TYPE_CONTEXT (type) != NULL_TREE
-      && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't')
+      && AGGREGATE_TYPE_P (TYPE_CONTEXT (type)))
     nested = 1;
 
   scope_die = scope_die_for (type, context_die);
@@ -8865,7 +9099,13 @@ gen_struct_or_union_type_die (type, context_die)
        }
     }
   else
-    add_AT_flag (type_die, DW_AT_declaration, 1);
+    {
+      add_AT_flag (type_die, DW_AT_declaration, 1);
+
+      /* We can't do this for function-local types, and we don't need to.  */
+      if (TREE_PERMANENT (type))
+       add_incomplete_type (type);
+    }
 }
 
 /* Generate a DIE for a subroutine _type_.  */
@@ -9019,7 +9259,7 @@ gen_type_die (type, context_die)
       /* If this is a nested type whose containing class hasn't been
         written out yet, writing it out will cover this one, too.  */
       if (TYPE_CONTEXT (type)
-         && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+         && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
          && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
        {
          gen_type_die (TYPE_CONTEXT (type), context_die);
@@ -9038,7 +9278,7 @@ gen_type_die (type, context_die)
        gen_struct_or_union_type_die (type, context_die);
 
       if (TYPE_CONTEXT (type)
-         && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+         && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
          && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
        pop_decl_scope ();
 
@@ -9192,7 +9432,7 @@ gen_block_die (stmt, context_die, depth)
 }
 
 /* Generate all of the decls declared within a given scope and (recursively)
-   all of it's sub-blocks.  */
+   all of its sub-blocks.  */
 
 static void
 decls_for_scope (stmt, context_die, depth)
@@ -9418,7 +9658,7 @@ dwarf2out_decl (decl)
   if (DECL_IGNORED_P (decl))
     {
       if (TREE_CODE (decl) == FUNCTION_DECL
-         && DECL_INITIAL (decl) != NULL)
+          && DECL_INITIAL (decl) != NULL)
        abort ();
 
       return;
@@ -9574,7 +9814,7 @@ dwarf2out_label (insn)
 
 static unsigned
 lookup_filename (file_name)
-     char *file_name;
+     const char *file_name;
 {
   static unsigned last_file_lookup_index = 0;
   register unsigned i;
@@ -9616,18 +9856,40 @@ lookup_filename (file_name)
 
 void
 dwarf2out_line (filename, line)
-     register char *filename;
+     register const char *filename;
      register unsigned line;
 {
   if (debug_info_level >= DINFO_LEVEL_NORMAL)
     {
       function_section (current_function_decl);
 
-      if (DECL_SECTION_NAME (current_function_decl))
+      if (DWARF2_ASM_LINE_DEBUG_INFO)
+       {
+         static const char *lastfile;
+
+         /* Emit the .file and .loc directives understood by GNU as.  */
+         if (lastfile == 0 || strcmp (filename, lastfile))
+           {
+             fprintf (asm_out_file, "\t.file 0 \"%s\"\n", filename);
+             lastfile = filename;
+           }
+
+         fprintf (asm_out_file, "\t.loc 0 %d 0\n", line);
+
+         /* Indicate that line number info exists.  */
+         ++line_info_table_in_use;
+
+         /* Indicate that multiple line number tables exist.  */
+         if (DECL_SECTION_NAME (current_function_decl))
+           ++separate_line_info_table_in_use;
+       }
+      else if (DECL_SECTION_NAME (current_function_decl))
        {
          register dw_separate_line_info_ref line_info;
          ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL,
                                     separate_line_info_table_in_use);
+         if (flag_debug_asm)
+           fprintf (asm_out_file, "\t%s line %d", ASM_COMMENT_START, line);
          fputc ('\n', asm_out_file);
 
          /* expand the line info table if necessary */
@@ -9655,6 +9917,8 @@ dwarf2out_line (filename, line)
 
          ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL,
                                     line_info_table_in_use);
+         if (flag_debug_asm)
+           fprintf (asm_out_file, "\t%s line %d", ASM_COMMENT_START, line);
          fputc ('\n', asm_out_file);
 
          /* Expand the line info table if necessary.  */
@@ -9681,7 +9945,7 @@ dwarf2out_line (filename, line)
 
 void
 dwarf2out_start_source_file (filename)
-     register char *filename ATTRIBUTE_UNUSED;
+     register const char *filename ATTRIBUTE_UNUSED;
 {
 }
 
@@ -9699,8 +9963,8 @@ dwarf2out_end_source_file ()
 
 void
 dwarf2out_define (lineno, buffer)
-     register unsigned lineno;
-     register char *buffer;
+     register unsigned lineno ATTRIBUTE_UNUSED;
+     register const char *buffer ATTRIBUTE_UNUSED;
 {
   static int initialized = 0;
   if (!initialized)
@@ -9717,7 +9981,7 @@ dwarf2out_define (lineno, buffer)
 void
 dwarf2out_undef (lineno, buffer)
      register unsigned lineno ATTRIBUTE_UNUSED;
-     register char *buffer ATTRIBUTE_UNUSED;
+     register const char *buffer ATTRIBUTE_UNUSED;
 {
 }
 
@@ -9732,8 +9996,7 @@ dwarf2out_init (asm_out_file, main_input_filename)
   primary_filename = main_input_filename;
 
   /* Allocate the initial hunk of the file_table.  */
-  file_table = (char **) xmalloc (FILE_TABLE_INCREMENT * sizeof (char *));
-  bzero ((char *) file_table, FILE_TABLE_INCREMENT * sizeof (char *));
+  file_table = (char **) xcalloc (FILE_TABLE_INCREMENT, sizeof (char *));
   file_table_allocated = FILE_TABLE_INCREMENT;
 
   /* Skip the first entry - file numbers begin at 1.  */
@@ -9741,37 +10004,29 @@ dwarf2out_init (asm_out_file, main_input_filename)
 
   /* Allocate the initial hunk of the decl_die_table.  */
   decl_die_table
-    = (dw_die_ref *) xmalloc (DECL_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
-  bzero ((char *) decl_die_table,
-        DECL_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
+    = (dw_die_ref *) xcalloc (DECL_DIE_TABLE_INCREMENT, sizeof (dw_die_ref));
   decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT;
   decl_die_table_in_use = 0;
 
   /* Allocate the initial hunk of the decl_scope_table.  */
   decl_scope_table
-    = (decl_scope_node *) xmalloc (DECL_SCOPE_TABLE_INCREMENT
-                                  * sizeof (decl_scope_node));
-  bzero ((char *) decl_scope_table,
-        DECL_SCOPE_TABLE_INCREMENT * sizeof (decl_scope_node));
+    = (decl_scope_node *) xcalloc (DECL_SCOPE_TABLE_INCREMENT,
+                                  sizeof (decl_scope_node));
   decl_scope_table_allocated = DECL_SCOPE_TABLE_INCREMENT;
   decl_scope_depth = 0;
 
   /* Allocate the initial hunk of the abbrev_die_table.  */
   abbrev_die_table
-    = (dw_die_ref *) xmalloc (ABBREV_DIE_TABLE_INCREMENT
-                             * sizeof (dw_die_ref));
-  bzero ((char *) abbrev_die_table,
-        ABBREV_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
+    = (dw_die_ref *) xcalloc (ABBREV_DIE_TABLE_INCREMENT,
+                             sizeof (dw_die_ref));
   abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
   /* Zero-th entry is allocated, but unused */
   abbrev_die_table_in_use = 1;
 
   /* Allocate the initial hunk of the line_info_table.  */
   line_info_table
-    = (dw_line_info_ref) xmalloc (LINE_INFO_TABLE_INCREMENT
-                                 * sizeof (dw_line_info_entry));
-  bzero ((char *) line_info_table,
-        LINE_INFO_TABLE_INCREMENT * sizeof (dw_line_info_entry));
+    = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
+                                 sizeof (dw_line_info_entry));
   line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
   /* Zero-th entry is allocated, but unused */
   line_info_table_in_use = 1;
@@ -9784,6 +10039,25 @@ dwarf2out_init (asm_out_file, main_input_filename)
   gen_compile_unit_die (main_input_filename);
 
   ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
+  ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, ABBREV_SECTION_LABEL, 0);
+  if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
+    ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
+  else
+    strcpy (text_section_label, stripattributes (TEXT_SECTION));
+  ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label, 
+                              DEBUG_INFO_SECTION_LABEL, 0);
+  ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label, 
+                              DEBUG_LINE_SECTION_LABEL, 0);
+
+  ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
+  ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
+  ASM_OUTPUT_SECTION (asm_out_file, TEXT_SECTION);
+  if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
+    ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
+  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION);
+  ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label);
+  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
+  ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label);
 }
 
 /* Output stuff that dwarf requires at the end of every file,
@@ -9819,6 +10093,10 @@ dwarf2out_finish ()
       free (node);
     }
 
+  /* Walk through the list of incomplete types again, trying once more to
+     emit full debugging info for them.  */
+  retry_incomplete_types ();
+
   /* Traverse the DIE tree and add sibling attributes to those DIE's
      that have children.  */
   add_sibling_attributes (comp_unit_die);
@@ -9843,19 +10121,23 @@ dwarf2out_finish ()
   /* Output the source line correspondence table.  */
   if (line_info_table_in_use > 1 || separate_line_info_table_in_use)
     {
-      fputc ('\n', asm_out_file);
-      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
-      output_line_info ();
+      if (! DWARF2_ASM_LINE_DEBUG_INFO)
+       {
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
+         output_line_info ();
+       }
 
       /* We can only use the low/high_pc attributes if all of the code
         was in .text.  */
       if (separate_line_info_table_in_use == 0)
        {
-         add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, TEXT_SECTION);
+         add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label);
          add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
        }
 
-      add_AT_section_offset (comp_unit_die, DW_AT_stmt_list, DEBUG_LINE_SECTION);
+      add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list,
+                        debug_line_section_label);
     }
 
   /* Output the abbreviation table.  */