OSDN Git Service

* sparc/sparc.md (eligible_for_return_delay): New attribute.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index d7ddf76..a79339c 100644 (file)
@@ -1,5 +1,5 @@
 /* Output Dwarf2 format symbol table information from the GNU C compiler.
-   Copyright (C) 1992, 1993, 1995, 1996, 1997 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
@@ -27,8 +28,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    information.  */
 
 #include "config.h"
+#include "system.h"
 #include "defaults.h"
-#include <stdio.h>
 #include "tree.h"
 #include "flags.h"
 #include "rtl.h"
@@ -40,6 +41,18 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "expr.h"
 #include "except.h"
 #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.  */
+#undef assert
+#ifdef NDEBUG
+# define assert(e)
+#else
+# define assert(e) do { if (! (e)) abort (); } while (0)
+#endif
 
 /* Decide whether we want to emit frame unwind information for the current
    translation unit.  */
@@ -48,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
@@ -56,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 ";#"
@@ -174,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));
@@ -192,6 +204,8 @@ static void initial_return_save             PROTO((rtx));
 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.
@@ -263,7 +277,7 @@ static unsigned reg_number          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
@@ -330,6 +344,16 @@ static unsigned reg_number         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))
@@ -351,24 +375,24 @@ static unsigned reg_number                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
@@ -376,13 +400,13 @@ static unsigned reg_number                PROTO((rtx));
   do {                                                                 \
     if (WORDS_BIG_ENDIAN)                                              \
       {                                                                        \
-       fprintf ((FILE), "\t%s\t0x%x\n", UNALIGNED_INT_ASM_OP, HIGH_VALUE); \
-       fprintf ((FILE), "\t%s\t0x%x", 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%x\n", UNALIGNED_INT_ASM_OP, LOW_VALUE);\
-       fprintf ((FILE), "\t%s\t0x%x", 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
@@ -393,30 +417,30 @@ static unsigned reg_number                PROTO((rtx));
    .debug_frame.  */
 
 #define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \
-  assemble_integer (gen_rtx (SYMBOL_REF, Pmode, LABEL), PTR_SIZE, 1)
+  assemble_integer (gen_rtx_SYMBOL_REF (Pmode, LABEL), PTR_SIZE, 1)
 
 #define ASM_OUTPUT_DWARF_OFFSET4(FILE,LABEL) \
-  assemble_integer (gen_rtx (SYMBOL_REF, SImode, LABEL), 4, 1)
+  assemble_integer (gen_rtx_SYMBOL_REF (SImode, LABEL), 4, 1)
 
 #define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \
-  assemble_integer (gen_rtx (SYMBOL_REF, SImode, LABEL), 4, 1)
+  assemble_integer (gen_rtx_SYMBOL_REF (SImode, LABEL), 4, 1)
 
 #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)),      \
+  assemble_integer (gen_rtx_MINUS (HImode,                             \
+                                  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)),      \
+  assemble_integer (gen_rtx_MINUS (SImode,                             \
+                                  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)),      \
+  assemble_integer (gen_rtx_MINUS (Pmode,                              \
+                                  gen_rtx_SYMBOL_REF (Pmode, LABEL1),  \
+                                  gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
                    PTR_SIZE, 1)
 
 #define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \
@@ -448,7 +472,7 @@ static unsigned reg_number          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++)                                               \
@@ -456,7 +480,7 @@ static unsigned reg_number          PROTO((rtx));
          register int c = p[i];                                              \
          if (c == '\"' || c == '\\')                                         \
            putc ('\\', FILE);                                                \
-         if (c >= ' ' && c < 0177)                                           \
+         if (ISPRINT(c))                                                     \
            putc (c, FILE);                                                   \
          else                                                                \
            {                                                                 \
@@ -500,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;
@@ -569,18 +595,26 @@ expand_builtin_dwarf_reg_size (reg_tree, target)
        continue;
 
       mode = reg_raw_mode[i];
+
       /* CCmode is arbitrarily given a size of 4 bytes.  It is more useful
         to use the same size as word_mode, since that reduces the number
         of ranges we need.  It should not matter, since the result should
         never be used for a condition code register anyways.  */
-      if (mode == CCmode)
+      if (GET_MODE_CLASS (mode) == MODE_CC)
        mode = word_mode;
+
       size = GET_MODE_SIZE (mode);
 
+      /* If this register is not valid in the specified mode and
+        we have a previous size, use that for the size of this
+        register to avoid making junk tiny ranges.  */
+      if (! HARD_REGNO_MODE_OK (i, mode) && last_size != -1)
+       size = last_size;
+
       if (size != last_size)
        {
          ranges[n_ranges].beg = i;
-         ranges[n_ranges].size = last_size = GET_MODE_SIZE (reg_raw_mode[i]);
+         ranges[n_ranges].size = last_size = size;
          ++n_ranges;
          if (n_ranges >= 5)
            abort ();
@@ -606,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;
 {
@@ -828,6 +866,9 @@ static long cfa_store_offset;
 /* The running total of the size of arguments pushed onto the stack.  */
 static long args_size;
 
+/* The last args_size we actually output.  */
+static long old_args_size;
+
 /* Entry point to update the canonical frame address (CFA).
    LABEL is passed to add_fde_cfi.  The value of CFA is now to be
    calculated from REG+OFFSET.  */
@@ -895,7 +936,9 @@ reg_save (label, reg, sreg, offset)
 
   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
 
-  if (sreg == -1)
+  /* The following comparison is correct. -1 is used to indicate that
+     the value isn't a register number.  */
+  if (sreg == (unsigned int) -1)
     {
       if (reg & ~0x3f)
        /* The register number won't fit in 6 bits, so we have to use
@@ -942,7 +985,13 @@ dwarf2out_args_size (label, size)
      char *label;
      long size;
 {
-  register dw_cfi_ref cfi = new_cfi ();
+  register dw_cfi_ref cfi;
+
+  if (size == old_args_size)
+    return;
+  old_args_size = size;
+
+  cfi = new_cfi ();
   cfi->dw_cfi_opc = DW_CFA_GNU_args_size;
   cfi->dw_cfi_oprnd1.dw_cfi_offset = size;
   add_fde_cfi (label, cfi);
@@ -989,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))
@@ -1048,6 +1097,26 @@ dwarf2out_stack_adjust (insn)
   long offset;
   char *label;
 
+  if (! asynchronous_exceptions && GET_CODE (insn) == CALL_INSN)
+    {
+      /* Extract the size of the args from the CALL rtx itself.  */
+
+      insn = PATTERN (insn);
+      if (GET_CODE (insn) == PARALLEL)
+       insn = XVECEXP (insn, 0, 0);
+      if (GET_CODE (insn) == SET)
+       insn = SET_SRC (insn);
+      assert (GET_CODE (insn) == CALL);
+      dwarf2out_args_size ("", INTVAL (XEXP (insn, 1)));
+      return;
+    }
+
+  /* If only calls can throw, and we have a frame pointer,
+     save up adjustments until we see the CALL_INSN.  */
+  else if (! asynchronous_exceptions
+          && cfa_reg != STACK_POINTER_REGNUM)
+    return;
+
   if (GET_CODE (insn) == BARRIER)
     {
       /* When we see a BARRIER, we know to reset args_size to 0.  Usually
@@ -1118,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;
-
-       case PLUS:
-       case MINUS:
-         if (dest == stack_pointer_rtx)
-           {
+            abort ();
+          cfa_reg = REGNO (dest);
+          break;
+
+        case PLUS:
+        case MINUS:
+          if (dest == stack_pointer_rtx)
+            {
              /* Adjusting SP.  */
              switch (GET_CODE (XEXP (src, 1)))
                {
@@ -1196,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;
@@ -1207,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;
                }
@@ -1220,45 +1286,78 @@ dwarf2out_frame_debug (insn)
                cfa_offset += offset;
              if (cfa_store_reg == STACK_POINTER_REGNUM)
                cfa_store_offset += offset;
-           }
-         else
-           {
+            }
+          else if (dest == hard_frame_pointer_rtx)
+            {
+             /* 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 (cfa_reg != STACK_POINTER_REGNUM)
+                   abort ();
+                 offset = INTVAL (XEXP (src, 1));
+                 if (GET_CODE (src) == PLUS)
+                   offset = -offset;
+                 cfa_offset += offset;
+                 cfa_reg = HARD_FRAME_POINTER_REGNUM;
+               }
+             else if (XEXP (src, 0) == hard_frame_pointer_rtx
+                      && GET_CODE (XEXP (src, 1)) == CONST_INT)
+               {
+                 if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
+                   abort ();
+                 offset = INTVAL (XEXP (src, 1));
+                 if (GET_CODE (src) == PLUS)
+                   offset = -offset;
+                 cfa_offset += offset;
+               }
+
+             else 
+               abort();
+            }
+          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;
-
-       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
+            }
+          break;
+
+        case CONST_INT:
+          cfa_temp_reg = REGNO (dest);
+          cfa_temp_value = INTVAL (src);
+          break;
+
+        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)))
@@ -1284,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 ();
        }
@@ -1304,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
@@ -1369,7 +1518,7 @@ output_uleb128 (value)
   while (value != 0);
 
   if (flag_debug_asm)
-    fprintf (asm_out_file, "\t%s ULEB128 0x%x", ASM_COMMENT_START, save_value);
+    fprintf (asm_out_file, "\t%s ULEB128 0x%lx", ASM_COMMENT_START, save_value);
 }
 
 /* Output an signed LEB128 quantity.  */
@@ -1400,7 +1549,7 @@ output_sleb128 (value)
 
   while (more);
   if (flag_debug_asm)
-    fprintf (asm_out_file, "\t%s SLEB128 %d", ASM_COMMENT_START, save_value);
+    fprintf (asm_out_file, "\t%s SLEB128 %ld", ASM_COMMENT_START, save_value);
 }
 
 /* Output a Call Frame Information opcode and its operand(s).  */
@@ -1416,7 +1565,7 @@ output_cfi (cfi, fde)
                              cfi->dw_cfi_opc
                              | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f));
       if (flag_debug_asm)
-       fprintf (asm_out_file, "\t%s DW_CFA_advance_loc 0x%x",
+       fprintf (asm_out_file, "\t%s DW_CFA_advance_loc 0x%lx",
                 ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
       fputc ('\n', asm_out_file);
     }
@@ -1427,7 +1576,7 @@ output_cfi (cfi, fde)
                              cfi->dw_cfi_opc
                              | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
       if (flag_debug_asm)
-       fprintf (asm_out_file, "\t%s DW_CFA_offset, column 0x%x",
+       fprintf (asm_out_file, "\t%s DW_CFA_offset, column 0x%lx",
                 ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
 
       fputc ('\n', asm_out_file);
@@ -1440,7 +1589,7 @@ output_cfi (cfi, fde)
                              cfi->dw_cfi_opc
                              | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
       if (flag_debug_asm)
-       fprintf (asm_out_file, "\t%s DW_CFA_restore, column 0x%x",
+       fprintf (asm_out_file, "\t%s DW_CFA_restore, column 0x%lx",
                 ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
 
       fputc ('\n', asm_out_file);
@@ -1525,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.  */
@@ -1546,11 +1682,9 @@ static void
 output_call_frame_info (for_eh)
      int for_eh;
 {
-  register unsigned long i, j;
+  register unsigned long i;
   register dw_fde_ref fde;
-  register unsigned long fde_size;
   register dw_cfi_ref cfi;
-  unsigned long fde_pad;
   char l1[20], l2[20];
 #ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
   char ld[20];
@@ -1572,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));
@@ -1710,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)
@@ -1800,7 +1942,7 @@ dwarf2out_begin_prologue ()
   fde->dw_fde_end = NULL;
   fde->dw_fde_cfi = NULL;
 
-  args_size = 0;
+  args_size = old_args_size = 0;
 }
 
 /* Output a marker (i.e. a label) for the absolute end of the generated code
@@ -1825,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;
 
@@ -1862,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.  */
@@ -1889,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;
@@ -1968,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;
@@ -2063,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)
@@ -2078,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
@@ -2156,18 +2297,29 @@ static unsigned decl_die_table_in_use;
    decl_die_table.  */
 #define DECL_DIE_TABLE_INCREMENT 256
 
+/* Structure used for the decl_scope table.  scope is the current declaration
+   scope, and previous is the entry that is the parent of this scope.  This
+   is usually but not always the immediately preceeding entry.  */
+
+typedef struct decl_scope_struct
+{
+  tree scope;
+  int previous;
+}
+decl_scope_node;
+
 /* A pointer to the base of a table of references to declaration
    scopes.  This table is a display which tracks the nesting
    of declaration scopes at the current scope and containing
    scopes.  This table is used to find the proper place to
    define type declaration DIE's.  */
-static tree *decl_scope_table;
+static decl_scope_node *decl_scope_table;
 
 /* Number of elements currently allocated for the decl_scope_table.  */
-static unsigned decl_scope_table_allocated;
+static int decl_scope_table_allocated;
 
 /* Current level of nesting of declaration scopes.  */
-static unsigned decl_scope_depth;
+static int decl_scope_depth;
 
 /* Size (in elements) of increments by which we may expand the
    decl_scope_table.  */
@@ -2257,9 +2409,27 @@ 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)
 static int comp_unit_has_inlines;
+#endif
 
 /* A pointer to the ..._DECL node which we have most recently been working
    on.  We keep this around just in case something about it looks screwy and
@@ -2269,16 +2439,18 @@ 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 char *dwarf_type_encoding_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 const char *dwarf_type_encoding_name PROTO((unsigned));
+#endif
 static tree decl_ultimate_origin       PROTO((tree));
 static tree block_ultimate_origin      PROTO((tree));
 static tree decl_class_context         PROTO((tree));
@@ -2298,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));
@@ -2312,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,
@@ -2351,7 +2524,7 @@ static unsigned long size_of_locs PROTO((dw_loc_descr_ref));
 static int constant_size               PROTO((long unsigned));
 static unsigned long size_of_die       PROTO((dw_die_ref));
 static void calc_die_sizes             PROTO((dw_die_ref));
-static unsigned long size_of_prolog    PROTO((void));
+static unsigned long size_of_line_prolog       PROTO((void));
 static unsigned long size_of_line_info PROTO((void));
 static unsigned long size_of_pubnames  PROTO((void));
 static unsigned long size_of_aranges   PROTO((void));
@@ -2362,11 +2535,11 @@ 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_arrange                        PROTO((tree, dw_die_ref));
-static void output_arranges            PROTO((void));
+static void add_arange                 PROTO((tree, dw_die_ref));
+static void output_aranges             PROTO((void));
 static void output_line_info           PROTO((void));
 static int is_body_block               PROTO((tree));
 static dw_die_ref base_type_die                PROTO((tree));
@@ -2377,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));
@@ -2390,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));
@@ -2401,7 +2574,7 @@ static void add_prototyped_attribute      PROTO((dw_die_ref, tree));
 static void add_abstract_origin_attribute PROTO((dw_die_ref, tree));
 static void add_pure_or_virtual_attribute PROTO((dw_die_ref, tree));
 static void add_src_coords_attributes  PROTO((dw_die_ref, tree));
-static void ad_name_and_src_coords_attributes PROTO((dw_die_ref, tree));
+static void add_name_and_src_coords_attributes PROTO((dw_die_ref, tree));
 static void push_decl_scope            PROTO((tree));
 static dw_die_ref scope_die_for                PROTO((tree, dw_die_ref));
 static void pop_decl_scope             PROTO((void));
@@ -2409,10 +2582,14 @@ static void add_type_attribute          PROTO((dw_die_ref, tree, int, int,
                                               dw_die_ref));
 static char *type_tag                  PROTO((tree));
 static tree member_declared_type       PROTO((tree));
+#if 0
 static char *decl_start_label          PROTO((tree));
-static void gen_arrqay_type_die                PROTO((tree, dw_die_ref));
+#endif
+static void gen_array_type_die         PROTO((tree, dw_die_ref));
 static void gen_set_type_die           PROTO((tree, dw_die_ref));
+#if 0
 static void gen_entry_point_die                PROTO((tree, dw_die_ref));
+#endif
 static void pend_type                  PROTO((tree));
 static void output_pending_types_for_scope PROTO((dw_die_ref));
 static void gen_inlined_enumeration_type_die PROTO((tree, dw_die_ref));
@@ -2426,7 +2603,7 @@ static void gen_subprogram_die            PROTO((tree, dw_die_ref));
 static void gen_variable_die           PROTO((tree, dw_die_ref));
 static void gen_label_die              PROTO((tree, dw_die_ref));
 static void gen_lexical_block_die      PROTO((tree, dw_die_ref, int));
-static void gen_inlined_subprogram_die PROTO((tree, dw_die_ref, int));
+static void gen_inlined_subroutine_die PROTO((tree, dw_die_ref, int));
 static void gen_field_die              PROTO((tree, dw_die_ref));
 static void gen_ptr_to_mbr_type_die    PROTO((tree, dw_die_ref));
 static void gen_compile_unit_die       PROTO((char *));
@@ -2442,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
@@ -2481,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
@@ -2489,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"
@@ -2525,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
@@ -2543,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:
@@ -2601,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
@@ -2613,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;
 
@@ -2640,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:
@@ -2676,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.  */
@@ -2727,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;
 {
@@ -2844,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;
 {
@@ -3017,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;
 {
@@ -3072,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;
 {
@@ -3375,7 +3570,8 @@ dwarf_stack_op_name (op)
 
 /* Convert a DWARF type code into its string name.  */
 
-static char *
+#if 0
+static const char *
 dwarf_type_encoding_name (enc)
      register unsigned enc;
 {
@@ -3401,6 +3597,7 @@ dwarf_type_encoding_name (enc)
       return "DW_ATE_<unknown>";
     }
 }
+#endif
 \f
 /* Determine the "ultimate origin" of a decl.  The decl may be an inlined
    instance of an inlined instance of a decl which is local to an inline
@@ -3412,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
@@ -3603,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));
 
@@ -3702,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);
   
 }
@@ -3881,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)
     {
@@ -4042,7 +4229,6 @@ equate_decl_number_to_die (decl, decl_die)
      register dw_die_ref decl_die;
 {
   register unsigned decl_id = DECL_UID (decl);
-  register unsigned i;
   register unsigned num_allocated;
 
   if (decl_id >= decl_die_table_allocated)
@@ -4132,11 +4318,11 @@ print_die (die, outfile)
   register dw_die_ref c;
 
   print_spaces (outfile);
-  fprintf (outfile, "DIE %4u: %s\n",
+  fprintf (outfile, "DIE %4lu: %s\n",
           die->die_offset, dwarf_tag_name (die->die_tag));
   print_spaces (outfile);
-  fprintf (outfile, "  abbrev id: %u", die->die_abbrev);
-  fprintf (outfile, " offset: %u\n", die->die_offset);
+  fprintf (outfile, "  abbrev id: %lu", die->die_abbrev);
+  fprintf (outfile, " offset: %lu\n", die->die_offset);
 
   for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
     {
@@ -4152,13 +4338,13 @@ print_die (die, outfile)
          fprintf (outfile, "location descriptor");
          break;
        case dw_val_class_const:
-         fprintf (outfile, "%d", a->dw_attr_val.v.val_int);
+         fprintf (outfile, "%ld", a->dw_attr_val.v.val_int);
          break;
        case dw_val_class_unsigned_const:
-         fprintf (outfile, "%u", a->dw_attr_val.v.val_unsigned);
+         fprintf (outfile, "%lu", a->dw_attr_val.v.val_unsigned);
          break;
        case dw_val_class_long_long:
-         fprintf (outfile, "constant (%u,%u)",
+         fprintf (outfile, "constant (%lu,%lu)",
                  a->dw_attr_val.v.val_long_long.hi,
                  a->dw_attr_val.v.val_long_long.low);
          break;
@@ -4170,17 +4356,15 @@ print_die (die, outfile)
          break;
        case dw_val_class_die_ref:
          if (a->dw_attr_val.v.val_die_ref != NULL)
-           fprintf (outfile, "die -> %u",
+           fprintf (outfile, "die -> %lu",
                     a->dw_attr_val.v.val_die_ref->die_offset);
          else
            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);
@@ -4220,7 +4404,7 @@ print_dwarf_line_table (outfile)
       line_info = &line_info_table[i];
       fprintf (outfile, "%5d: ", i);
       fprintf (outfile, "%-20s", file_table[line_info->dw_file_num]);
-      fprintf (outfile, "%6d", line_info->dw_line_num);
+      fprintf (outfile, "%6ld", line_info->dw_line_num);
       fprintf (outfile, "\n");
     }
 
@@ -4244,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
@@ -4342,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.  */
@@ -4555,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:
@@ -4607,7 +4781,7 @@ size_of_line_prolog ()
   size += DWARF_LINE_OPCODE_BASE - 1;
 
   /* Include directory table is empty (at present).  Count only the
-     the null byte used to terminate the table.  */
+     null byte used to terminate the table.  */
   size += 1;
 
   for (ft_index = 1; ft_index < file_table_in_use; ++ft_index)
@@ -4657,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.  */
@@ -4673,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.  */
@@ -4717,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;
@@ -4759,6 +4939,7 @@ size_of_line_info ()
            }
        }
 
+    cont:
       ++lt_index;
 
       /* If we're done with a function, end its sequence.  */
@@ -4868,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;
@@ -4941,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).  */
@@ -5090,11 +5274,10 @@ 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)
-    fprintf (asm_out_file, " (DIE (0x%x) %s)",
+    fprintf (asm_out_file, " (DIE (0x%lx) %s)",
             die->die_offset, dwarf_tag_name (die->die_tag));
 
   fputc ('\n', asm_out_file);
@@ -5193,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);
@@ -5241,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:
@@ -5253,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:
@@ -5280,7 +5464,7 @@ output_die (die)
       /* Add null byte to terminate sibling list. */
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
       if (flag_debug_asm)
-       fprintf (asm_out_file, "\t%s end of children of DIE 0x%x",
+       fprintf (asm_out_file, "\t%s end of children of DIE 0x%lx",
                 ASM_COMMENT_START, die->die_offset);
 
       fputc ('\n', asm_out_file);
@@ -5304,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);
@@ -5321,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;
@@ -5377,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);
@@ -5405,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);
@@ -5457,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);
@@ -5474,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)
@@ -5483,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);
 
@@ -5634,14 +5826,14 @@ output_line_info ()
       if (flag_debug_asm)
        {
          ASM_OUTPUT_DWARF_STRING (asm_out_file, file_table[ft_index]);
-         fprintf (asm_out_file, "%s File Entry: 0x%x",
+         fprintf (asm_out_file, "%s File Entry: 0x%lx",
                   ASM_COMMENT_START, ft_index);
        }
       else
        {
          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);
@@ -5663,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.  */
@@ -5727,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;
@@ -5745,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 %d", 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 %d",
-                    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);
        }
     }
@@ -5823,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.  */
@@ -5908,7 +6116,7 @@ output_line_info ()
                                      DWARF_LINE_OPCODE_BASE + line_delta);
              if (flag_debug_asm)
                fprintf (asm_out_file,
-                        "\t%s line %d", ASM_COMMENT_START, current_line);
+                        "\t%s line %ld", ASM_COMMENT_START, current_line);
 
              fputc ('\n', asm_out_file);
            }
@@ -5916,17 +6124,28 @@ output_line_info ()
            {
              ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
              if (flag_debug_asm)
-               fprintf (asm_out_file, "\t%s advance to line %d",
+               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
+       {
+         /* 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.  */
@@ -6081,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;
@@ -6287,7 +6506,7 @@ reg_loc_descriptor (rtl)
   register dw_loc_descr_ref loc_result = NULL;
   register unsigned reg = reg_number (rtl);
 
-  if (reg >= 0 && reg <= 31)
+  if (reg <= 31)
     loc_result = new_loc_descr (DW_OP_reg0 + reg, 0, 0);
   else
     loc_result = new_loc_descr (DW_OP_regx, reg, 0);
@@ -6312,7 +6531,7 @@ based_loc_descr (reg, offset)
 
   if (reg == fp_reg)
     loc_result = new_loc_descr (DW_OP_fbreg, offset, 0);
-  else if (reg >= 0 && reg <= 31)
+  else if (reg <= 31)
     loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0);
   else
     loc_result = new_loc_descr (DW_OP_bregx, reg, offset);
@@ -6339,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 
@@ -6353,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
@@ -6381,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);
@@ -6392,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;
@@ -6407,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;
 
@@ -6475,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:
@@ -6960,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)
@@ -6970,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
 
@@ -7010,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);
@@ -7082,10 +7362,22 @@ add_bound_info (subrange_die, bound_attr, bound)
        {
          register dw_die_ref ctx = lookup_decl_die (current_function_decl);
          register dw_die_ref decl_die = new_die (DW_TAG_variable, ctx);
+         register rtx loc = SAVE_EXPR_RTL (bound);
+
+         /* If the RTL for the SAVE_EXPR is memory, handle the case where
+            it references an outer function's frame.  */
+
+         if (GET_CODE (loc) == MEM)
+           {
+             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);
+           }
+
          add_AT_flag (decl_die, DW_AT_artificial, 1);
          add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
-         add_AT_location_description (decl_die, DW_AT_location,
-                                      SAVE_EXPR_RTL (bound));
+         add_AT_location_description (decl_die, DW_AT_location, loc);
          add_AT_die_ref (subrange_die, bound_attr, decl_die);
        }
 
@@ -7094,6 +7386,7 @@ add_bound_info (subrange_die, bound_attr, bound)
 
     case MAX_EXPR:
     case VAR_DECL:
+    case COMPONENT_REF:
       /* ??? These types of bounds can be created by the Ada front end,
         and it isn't clear how to emit debug info for them.  */
       break;
@@ -7111,7 +7404,9 @@ add_subscript_info (type_die, type)
      register dw_die_ref type_die;
      register tree type;
 {
+#ifndef MIPS_DEBUGGING_INFO
   register unsigned dimension_number;
+#endif
   register tree lower, upper;
   register dw_die_ref subrange_die;
 
@@ -7162,14 +7457,23 @@ add_subscript_info (type_die, type)
                                    type_die);
            }
 
+         /* ??? If upper is NULL, the array has unspecified length,
+            but it does have a lower bound.  This happens with Fortran
+              dimension arr(N:*)
+                    Since the debugger is definitely going to need to know N
+            to produce useful results, go ahead and output the lower
+            bound solo, and hope the debugger can cope.  */
+
          add_bound_info (subrange_die, DW_AT_lower_bound, lower);
-         add_bound_info (subrange_die, DW_AT_upper_bound, upper);
+         if (upper)
+           add_bound_info (subrange_die, DW_AT_upper_bound, upper);
        }
       else
        /* We have an array type with an unspecified length.  The DWARF-2
             spec does not say how to handle this; let's just leave out the
             bounds.  */
-       ;
+       {;}
+      
 
 #ifndef MIPS_DEBUGGING_INFO
     }
@@ -7391,19 +7695,55 @@ static void
 push_decl_scope (scope)
      tree scope;
 {
+  tree containing_scope;
+  int i;
+
   /* Make room in the decl_scope_table, if necessary.  */
   if (decl_scope_table_allocated == decl_scope_depth)
     {
       decl_scope_table_allocated += DECL_SCOPE_TABLE_INCREMENT;
       decl_scope_table
-       = (tree *) xrealloc (decl_scope_table,
-                            decl_scope_table_allocated * sizeof (tree));
+       = (decl_scope_node *) xrealloc (decl_scope_table,
+                                       (decl_scope_table_allocated
+                                        * sizeof (decl_scope_node)));
     }
 
-  decl_scope_table[decl_scope_depth++] = scope;
+  decl_scope_table[decl_scope_depth].scope = scope;
+
+  /* Sometimes, while recursively emitting subtypes within a class type,
+     we end up recuring on a subtype at a higher level then the current
+     subtype.  In such a case, we need to search the decl_scope_table to
+     find the parent of this subtype.  */
+
+  if (AGGREGATE_TYPE_P (scope))
+    containing_scope = TYPE_CONTEXT (scope);
+  else
+    containing_scope = NULL_TREE;
+
+  /* The normal case.  */
+  if (decl_scope_depth == 0
+      || containing_scope == NULL_TREE
+      /* Ignore namespaces for the moment.  */
+      || TREE_CODE (containing_scope) == NAMESPACE_DECL
+      || containing_scope == decl_scope_table[decl_scope_depth - 1].scope)
+    decl_scope_table[decl_scope_depth].previous = decl_scope_depth - 1;
+  else
+    {
+      /* We need to search for the containing_scope.  */
+      for (i = 0; i < decl_scope_depth; i++)
+       if (decl_scope_table[i].scope == containing_scope)
+         break;
+
+      if (i == decl_scope_depth)
+       abort ();
+      else
+       decl_scope_table[decl_scope_depth].previous = i;
+    }
+
+  decl_scope_depth++;
 }
 
-/* Return the DIE for the scope the immediately contains this declaration.  */
+/* Return the DIE for the scope that immediately contains this declaration.  */
 
 static dw_die_ref
 scope_die_for (t, context_die)
@@ -7412,7 +7752,7 @@ scope_die_for (t, context_die)
 {
   register dw_die_ref scope_die = NULL;
   register tree containing_scope;
-  register unsigned long i;
+  register int i;
 
   /* Walk back up the declaration tree looking for a place to define
      this type.  */
@@ -7423,6 +7763,16 @@ scope_die_for (t, context_die)
   else
     containing_scope = DECL_CONTEXT (t);
 
+  /* Ignore namespaces for the moment.  */
+  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
@@ -7433,19 +7783,40 @@ scope_die_for (t, context_die)
     scope_die = comp_unit_die;
   else
     {
-      for (i = decl_scope_depth, scope_die = context_die;
-          i > 0 && decl_scope_table[i - 1] != containing_scope;
-          scope_die = scope_die->die_parent, --i)
+      for (i = decl_scope_depth - 1, scope_die = context_die;
+          i >= 0 && decl_scope_table[i].scope != containing_scope;
+          (scope_die = scope_die->die_parent,
+           i = decl_scope_table[i].previous))
        ;
 
-      if (i == 0)
+      /* ??? Integrate_decl_tree does not handle BLOCK_TYPE_TAGS, nor
+        does it try to handle types defined by TYPE_DECLs.  Such types
+        thus have an incorrect TYPE_CONTEXT, which points to the block
+        they were originally defined in, instead of the current block
+        created by function inlining.  We try to detect that here and
+        work around it.  */
+
+      if (i < 0 && scope_die == comp_unit_die
+         && TREE_CODE (containing_scope) == BLOCK
+         && is_tagged_type (t)
+         && (block_ultimate_origin (decl_scope_table[decl_scope_depth - 1].scope)
+             == containing_scope))
+       {
+         scope_die = context_die;
+         /* Since the checks below are no longer applicable.  */
+         i = 0;
+       }
+
+      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;
        }
     }
 
@@ -7549,6 +7920,7 @@ member_declared_type (member)
 /* Get the decl's label, as described by its RTL. This may be different
    from the DECL_NAME name used in the source file.  */
 
+#if 0
 static char *
 decl_start_label (decl)
      register tree decl;
@@ -7566,6 +7938,7 @@ decl_start_label (decl)
   fnname = XSTR (x, 0);
   return fnname;
 }
+#endif
 \f
 /* These routines generate the internal representation of the DIE's for
    the compilation unit.  Debugging information is collected by walking
@@ -7640,6 +8013,7 @@ gen_set_type_die (type, context_die)
   add_type_attribute (type_die, TREE_TYPE (type), 0, 0, context_die);
 }
 
+#if 0
 static void
 gen_entry_point_die (decl, context_die)
      register tree decl;
@@ -7661,6 +8035,7 @@ gen_entry_point_die (decl, context_die)
   else
     add_AT_lbl_id (decl_die, DW_AT_low_pc, decl_start_label (decl));
 }
+#endif
 
 /* Remember a type in the pending_types_list.  */
 
@@ -7701,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
@@ -7865,11 +8273,10 @@ 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;
 {
-  register dw_die_ref parm_die = new_die (DW_TAG_unspecified_parameters,
-                                         context_die);
+  new_die (DW_TAG_unspecified_parameters, context_die);
 }
 
 /* Generate a list of nameless DW_TAG_formal_parameter DIEs (and perhaps a
@@ -7951,7 +8358,6 @@ gen_subprogram_die (decl, context_die)
   char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
   register tree origin = decl_ultimate_origin (decl);
   register dw_die_ref subr_die;
-  register dw_loc_descr_ref fp_loc = NULL;
   register rtx fp_reg;
   register tree fn_arg_types;
   register tree outer_scope;
@@ -7984,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
@@ -7997,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;
 
@@ -8012,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));
        }
@@ -8249,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));
@@ -8312,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 
@@ -8619,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);
@@ -8678,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_.  */
@@ -8745,7 +9172,7 @@ gen_type_die (type, context_die)
   if (type == NULL_TREE || type == error_mark_node)
     return;
 
-  /* We are going to output a DIE to represent the unqualified version of of
+  /* We are going to output a DIE to represent the unqualified version of
      this type (i.e. without any const or volatile qualifiers) so get the
      main variant (i.e. the unqualified version) of this type now.  */
   type = type_main_variant (type);
@@ -8832,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);
@@ -8851,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 ();
 
@@ -8890,7 +9317,7 @@ gen_tagged_type_instantiation_die (type, context_die)
   if (type == NULL_TREE || type == error_mark_node)
     return;
 
-  /* We are going to output a DIE to represent the unqualified version of of
+  /* We are going to output a DIE to represent the unqualified version of
      this type (i.e. without any const or volatile qualifiers) so make sure
      that we have the main variant (i.e. the unqualified version) of this
      type now.  */
@@ -9005,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)
@@ -9092,7 +9519,7 @@ gen_decl_die (decl, context_die)
 
   /* If this ..._DECL node is marked to be ignored, then ignore it. But don't 
      ignore a function definition, since that would screw up our count of
-     blocks, and that it turn will completely screw up the the labels we will 
+     blocks, and that in turn will completely screw up the labels we will 
      reference in subsequent DW_AT_low_pc and DW_AT_high_pc attributes (for
      subsequent blocks).  */
   if (DECL_IGNORED_P (decl) && TREE_CODE (decl) != FUNCTION_DECL)
@@ -9224,14 +9651,14 @@ dwarf2out_decl (decl)
   /* If this ..._DECL node is marked to be ignored, then ignore it.  We gotta 
      hope that the node in question doesn't represent a function definition.
      If it does, then totally ignoring it is bound to screw up our count of
-     blocks, and that it turn will completely screw up the the labels we will 
+     blocks, and that in turn will completely screw up the labels we will 
      reference in subsequent DW_AT_low_pc and DW_AT_high_pc attributes (for
      subsequent blocks).  (It's too bad that BLOCK nodes don't carry their
      own sequence numbers with them!) */
   if (DECL_IGNORED_P (decl))
     {
       if (TREE_CODE (decl) == FUNCTION_DECL
-         && DECL_INITIAL (decl) != NULL)
+          && DECL_INITIAL (decl) != NULL)
        abort ();
 
       return;
@@ -9387,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;
@@ -9429,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 */
@@ -9468,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.  */
@@ -9494,7 +9945,7 @@ dwarf2out_line (filename, line)
 
 void
 dwarf2out_start_source_file (filename)
-     register char *filename;
+     register const char *filename ATTRIBUTE_UNUSED;
 {
 }
 
@@ -9512,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)
@@ -9529,8 +9980,8 @@ dwarf2out_define (lineno, buffer)
 
 void
 dwarf2out_undef (lineno, buffer)
-     register unsigned lineno;
-     register char *buffer;
+     register unsigned lineno ATTRIBUTE_UNUSED;
+     register const char *buffer ATTRIBUTE_UNUSED;
 {
 }
 
@@ -9545,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.  */
@@ -9554,36 +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
-    = (tree *) xmalloc (DECL_SCOPE_TABLE_INCREMENT * sizeof (tree));
-  bzero ((char *) decl_scope_table,
-        DECL_SCOPE_TABLE_INCREMENT * sizeof (tree));
+    = (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;
@@ -9596,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,
@@ -9631,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);
@@ -9655,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.  */