OSDN Git Service

[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index b20683d..8661080 100644 (file)
@@ -1,7 +1,7 @@
 /* Output Dwarf2 format symbol table information from the GNU C compiler.
-   Copyright (C) 1992, 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
-   Contributed by Gary Funck (gary@intrepid.com).  Derived from the
-   DWARF 1 implementation written by Ron Guilmette (rfg@monkeys.com).
+   Copyright (C) 1992, 93, 95, 96, 97, 1998 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).
 
 This file is part of GNU CC.
@@ -20,20 +20,15 @@ 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.  */
 
-#include "config.h"
-#include "defaults.h"
-
 /* The first part of this file deals with the DWARF 2 frame unwind
    information, which is also used by the GCC efficient exception handling
    mechanism.  The second part, controlled only by an #ifdef
    DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging
    information.  */
 
-#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
-
-#include <stdio.h>
-#include <setjmp.h>
-#include "dwarf2.h"
+#include "config.h"
+#include "system.h"
+#include "defaults.h"
 #include "tree.h"
 #include "flags.h"
 #include "rtl.h"
@@ -44,9 +39,37 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "output.h"
 #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.  */
 
-/* #define NDEBUG 1 */
-#include "assert.h"
+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
+         );
+}
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 
 #ifndef __GNUC__
 #define inline
@@ -174,7 +197,6 @@ static unsigned long size_of_uleb128        PROTO((unsigned long));
 static unsigned long size_of_sleb128   PROTO((long));
 static void output_uleb128             PROTO((unsigned long));
 static void output_sleb128             PROTO((long));
-char *dwarf2out_cfi_label              PROTO((void));
 static void add_fde_cfi                        PROTO((char *, dw_cfi_ref));
 static void lookup_cfa_1               PROTO((dw_cfi_ref, unsigned long *,
                                               long *));
@@ -185,12 +207,14 @@ 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));
 
 /* Definitions of defaults for assembler-dependent names of various
    pseudo-ops and section names.
    Theses may be overridden in the tm.h file (if necessary) for a particular
    assembler.  */
 
+#ifdef OBJECT_FORMAT_ELF
 #ifndef UNALIGNED_SHORT_ASM_OP
 #define UNALIGNED_SHORT_ASM_OP ".2byte"
 #endif
@@ -200,20 +224,12 @@ static unsigned reg_number                PROTO((rtx));
 #ifndef UNALIGNED_DOUBLE_INT_ASM_OP
 #define UNALIGNED_DOUBLE_INT_ASM_OP    ".8byte"
 #endif
+#endif /* OBJECT_FORMAT_ELF */
+
 #ifndef ASM_BYTE_OP
 #define ASM_BYTE_OP            ".byte"
 #endif
 
-#ifndef UNALIGNED_OFFSET_ASM_OP
-#define UNALIGNED_OFFSET_ASM_OP \
-  (DWARF_OFFSET_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
-#endif
-
-#ifndef UNALIGNED_WORD_ASM_OP
-#define UNALIGNED_WORD_ASM_OP \
-  (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
-#endif
-
 /* Data and reference forms for relocatable data.  */
 #define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
 #define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
@@ -238,9 +254,6 @@ static unsigned reg_number          PROTO((rtx));
 #ifndef FRAME_SECTION
 #define FRAME_SECTION          ".debug_frame"
 #endif
-#if !defined (EH_FRAME_SECTION) && defined (ASM_OUTPUT_SECTION_NAME)
-#define EH_FRAME_SECTION       ".eh_frame"
-#endif
 
 #ifndef FUNC_BEGIN_LABEL
 #define FUNC_BEGIN_LABEL       "LFB"
@@ -250,18 +263,46 @@ static unsigned reg_number                PROTO((rtx));
 #endif
 #define CIE_AFTER_SIZE_LABEL   "LSCIE"
 #define CIE_END_LABEL          "LECIE"
+#define CIE_LENGTH_LABEL       "LLCIE"
 #define FDE_AFTER_SIZE_LABEL   "LSFDE"
 #define FDE_END_LABEL          "LEFDE"
+#define FDE_LENGTH_LABEL       "LLFDE"
 
 /* Definitions of defaults for various types of primitive assembly language
    output operations.  These may be overridden from within the tm.h file,
-   but typically, that is unecessary.  */
+   but typically, that is unnecessary.  */
 
 #ifndef ASM_OUTPUT_SECTION
 #define ASM_OUTPUT_SECTION(FILE, SECTION) \
   fprintf ((FILE), SECTION_FORMAT, SECTION_ASM_OP, SECTION)
 #endif
 
+#ifndef ASM_OUTPUT_DWARF_DATA1
+#define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \
+  fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) (VALUE))
+#endif
+
+#ifndef ASM_OUTPUT_DWARF_DELTA1
+#define ASM_OUTPUT_DWARF_DELTA1(FILE,LABEL1,LABEL2)                    \
+ do {  fprintf ((FILE), "\t%s\t", ASM_BYTE_OP);                        \
+       assemble_name (FILE, LABEL1);                                   \
+       fprintf (FILE, "-");                                            \
+       assemble_name (FILE, LABEL2);                                   \
+  } while (0)
+#endif
+
+#ifdef UNALIGNED_INT_ASM_OP
+
+#ifndef UNALIGNED_OFFSET_ASM_OP
+#define UNALIGNED_OFFSET_ASM_OP \
+  (DWARF_OFFSET_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
+#endif
+
+#ifndef UNALIGNED_WORD_ASM_OP
+#define UNALIGNED_WORD_ASM_OP \
+  (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
+#endif
+
 #ifndef ASM_OUTPUT_DWARF_DELTA2
 #define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2)                    \
  do {  fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP);             \
@@ -305,11 +346,28 @@ 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))
 #endif
 
+#ifndef ASM_OUTPUT_DWARF_OFFSET4
+#define ASM_OUTPUT_DWARF_OFFSET4(FILE,LABEL) \
+ do {  fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP);               \
+       assemble_name (FILE, LABEL);                                    \
+  } while (0)
+#endif
+
 #ifndef ASM_OUTPUT_DWARF_OFFSET
 #define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL)                            \
  do {  fprintf ((FILE), "\t%s\t", UNALIGNED_OFFSET_ASM_OP);            \
@@ -317,31 +375,26 @@ static unsigned reg_number                PROTO((rtx));
   } while (0)
 #endif
 
-#ifndef ASM_OUTPUT_DWARF_DATA1
-#define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \
-  fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, VALUE)
-#endif
-
 #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
@@ -349,19 +402,73 @@ 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
 
+#else /* UNALIGNED_INT_ASM_OP */
+
+/* We don't have unaligned support, let's hope the normal output works for
+   .debug_frame.  */
+
+#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \
+  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)
+
+#define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \
+  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)),       \
+                   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)),       \
+                   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)),       \
+                   PTR_SIZE, 1)
+
+#define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \
+  ASM_OUTPUT_DWARF_DELTA4 (FILE,LABEL1,LABEL2)
+
+#define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \
+  assemble_integer (GEN_INT (VALUE), 4, 1)
+
+#endif /* UNALIGNED_INT_ASM_OP */
+
+#ifdef SET_ASM_OP
+#ifndef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
+#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO)            \
+ do {                                                                  \
+  fprintf (FILE, "\t%s\t", SET_ASM_OP);                                        \
+  assemble_name (FILE, SY);                                            \
+  fputc (',', FILE);                                                   \
+  assemble_name (FILE, HI);                                            \
+  fputc ('-', FILE);                                                   \
+  assemble_name (FILE, LO);                                            \
+ } while (0)
+#endif
+#endif /* SET_ASM_OP */
+
 /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
-   newline is produced.  When flag_verbose_asm is asserted, we add commnetary
+   newline is produced.  When flag_debug_asm is asserted, we add commentary
    at the end of the line, so we must avoid output of a newline here.  */
 #ifndef ASM_OUTPUT_DWARF_STRING
 #define ASM_OUTPUT_DWARF_STRING(FILE,P) \
@@ -404,6 +511,14 @@ static unsigned reg_number         PROTO((rtx));
 #define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
 #endif
 
+/* Hook used by __throw.  */
+
+rtx
+expand_builtin_dwarf_fp_regnum ()
+{
+  return GEN_INT (DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM));
+}
+
 /* The offset from the incoming value of %sp to the top of the stack frame
    for the current function.  */
 #ifndef INCOMING_FRAME_SP_OFFSET
@@ -411,17 +526,19 @@ static unsigned reg_number                PROTO((rtx));
 #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;
 {
-  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;
@@ -445,6 +562,112 @@ reg_number (rtl)
   return regno;
 }
 
+struct reg_size_range
+{
+  int beg;
+  int end;
+  int size;
+};
+
+/* Given a register number in REG_TREE, return an rtx for its size in bytes.
+   We do this in kind of a roundabout way, by building up a list of
+   register size ranges and seeing where our register falls in one of those
+   ranges.  We need to do it this way because REG_TREE is not a constant,
+   and the target macros were not designed to make this task easy.  */
+
+rtx
+expand_builtin_dwarf_reg_size (reg_tree, target)
+     tree reg_tree;
+     rtx target;
+{
+  enum machine_mode mode;
+  int size;
+  struct reg_size_range ranges[5];
+  tree t, t2;
+
+  int i = 0;
+  int n_ranges = 0;
+  int last_size = -1;
+
+  for (; i < FIRST_PSEUDO_REGISTER; ++i)
+    {
+      /* The return address is out of order on the MIPS, and we don't use
+        copy_reg for it anyway, so we don't care here how large it is.  */
+      if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN)
+       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 (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 = size;
+         ++n_ranges;
+         if (n_ranges >= 5)
+           abort ();
+       }
+      ranges[n_ranges-1].end = i;
+    }
+
+  /* The usual case: fp regs surrounded by general regs.  */
+  if (n_ranges == 3 && ranges[0].size == ranges[2].size)
+    {
+      if ((DWARF_FRAME_REGNUM (ranges[1].end)
+          - DWARF_FRAME_REGNUM (ranges[1].beg))
+         != ranges[1].end - ranges[1].beg)
+       abort ();
+      t  = fold (build (GE_EXPR, integer_type_node, reg_tree,
+                       build_int_2 (DWARF_FRAME_REGNUM (ranges[1].beg), 0)));
+      t2 = fold (build (LE_EXPR, integer_type_node, reg_tree,
+                       build_int_2 (DWARF_FRAME_REGNUM (ranges[1].end), 0)));
+      t = fold (build (TRUTH_ANDIF_EXPR, integer_type_node, t, t2));
+      t = fold (build (COND_EXPR, integer_type_node, t,
+                      build_int_2 (ranges[1].size, 0),
+                      build_int_2 (ranges[0].size, 0)));
+    }
+  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);
+      do
+       {
+         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 ();
+         last_end = end;
+         if (end - beg != ranges[n_ranges].end - ranges[n_ranges].beg)
+           abort ();
+         t2 = fold (build (LE_EXPR, integer_type_node, reg_tree,
+                           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 *
@@ -497,6 +720,8 @@ dwarf_cfi_name (cfi_opc)
     /* GNU extensions */
     case DW_CFA_GNU_window_save:
       return "DW_CFA_GNU_window_save";
+    case DW_CFA_GNU_args_size:
+      return "DW_CFA_GNU_args_size";
 
     default:
       return "DW_CFA_<unknown>";
@@ -603,6 +828,8 @@ lookup_cfa_1 (cfi, regp, offsetp)
       *regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
       *offsetp = cfi->dw_cfi_oprnd2.dw_cfi_offset;
       break;
+    default:
+      break;
     }
 }
 
@@ -638,6 +865,12 @@ static long cfa_offset;
 static unsigned cfa_store_reg;
 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.  */
@@ -705,7 +938,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
@@ -715,7 +950,8 @@ reg_save (label, reg, sreg, offset)
        cfi->dw_cfi_opc = DW_CFA_offset;
 
       offset /= DWARF_CIE_DATA_ALIGNMENT;
-      assert (offset >= 0);
+      if (offset < 0)
+       abort ();
       cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
     }
   else
@@ -743,6 +979,26 @@ dwarf2out_window_save (label)
   add_fde_cfi (label, cfi);
 }
 
+/* Add a CFI to update the running total of the size of arguments
+   pushed onto the stack.  */
+
+void
+dwarf2out_args_size (label, size)
+     char *label;
+     long size;
+{
+  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);
+}
+
 /* Entry point for saving a register to the stack.  REG is the GCC register
    number.  LABEL and OFFSET are passed to reg_save.  */
 
@@ -799,15 +1055,18 @@ initial_return_save (rtl)
       switch (GET_CODE (rtl))
        {
        case REG:
-         assert (REGNO (rtl) == STACK_POINTER_REGNUM);
+         if (REGNO (rtl) != STACK_POINTER_REGNUM)
+           abort ();
          offset = 0;
          break;
        case PLUS:
-         assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
+         if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM)
+           abort ();
          offset = INTVAL (XEXP (rtl, 1));
          break;
        case MINUS:
-         assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
+         if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM)
+           abort ();
          offset = -INTVAL (XEXP (rtl, 1));
          break;
        default:
@@ -818,7 +1077,8 @@ initial_return_save (rtl)
       /* The return address is at some offset from any value we can
         actually load.  For instance, on the SPARC it is in %i7+8. Just
         ignore the offset for now; it doesn't matter for unwinding frames.  */
-      assert (GET_CODE (XEXP (rtl, 1)) == CONST_INT);
+      if (GET_CODE (XEXP (rtl, 1)) != CONST_INT)
+       abort ();
       initial_return_save (XEXP (rtl, 0));
       return;
     default:
@@ -828,6 +1088,107 @@ initial_return_save (rtl)
   reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa_offset);
 }
 
+/* Check INSN to see if it looks like a push or a stack adjustment, and
+   make a note of it if it does.  EH uses this information to find out how
+   much extra space it needs to pop off the stack.  */
+
+static void
+dwarf2out_stack_adjust (insn)
+     rtx 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
+        the compiler will have already emitted a stack adjustment, but
+        doesn't bother for calls to noreturn functions.  */
+#ifdef STACK_GROWS_DOWNWARD
+      offset = -args_size;
+#else
+      offset = args_size;
+#endif
+    }
+  else if (GET_CODE (PATTERN (insn)) == SET)
+    {
+      rtx src, dest;
+      enum rtx_code code;
+
+      insn = PATTERN (insn);
+      src = SET_SRC (insn);
+      dest = SET_DEST (insn);
+
+      if (dest == stack_pointer_rtx)
+       {
+         /* (set (reg sp) (plus (reg sp) (const_int))) */
+         code = GET_CODE (src);
+         if (! (code == PLUS || code == MINUS)
+             || XEXP (src, 0) != stack_pointer_rtx
+             || GET_CODE (XEXP (src, 1)) != CONST_INT)
+           return;
+
+         offset = INTVAL (XEXP (src, 1));
+       }
+      else if (GET_CODE (dest) == MEM)
+       {
+         /* (set (mem (pre_dec (reg sp))) (foo)) */
+         src = XEXP (dest, 0);
+         code = GET_CODE (src);
+
+         if (! (code == PRE_DEC || code == PRE_INC)
+             || XEXP (src, 0) != stack_pointer_rtx)
+           return;
+
+         offset = GET_MODE_SIZE (GET_MODE (dest));
+       }
+      else
+       return;
+
+      if (code == PLUS || code == PRE_INC)
+       offset = -offset;
+    }
+  else
+    return;
+
+  if (offset == 0)
+    return;
+
+  if (cfa_reg == STACK_POINTER_REGNUM)
+    cfa_offset += offset;
+
+#ifndef STACK_GROWS_DOWNWARD
+  offset = -offset;
+#endif
+  args_size += offset;
+  if (args_size < 0)
+    args_size = 0;
+
+  label = dwarf2out_cfi_label ();
+  dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+  dwarf2out_args_size (label, args_size);
+}
+
 /* 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.  */
@@ -848,7 +1209,8 @@ dwarf2out_frame_debug (insn)
     {
       /* Set up state for generating call frame debug info.  */
       lookup_cfa (&cfa_reg, &cfa_offset);
-      assert (cfa_reg == DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM));
+      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;
@@ -857,10 +1219,26 @@ dwarf2out_frame_debug (insn)
       return;
     }
 
+  if (! RTX_FRAME_RELATED_P (insn))
+    {
+      dwarf2out_stack_adjust (insn);
+      return;
+    }
+
   label = dwarf2out_cfi_label ();
     
-  insn = PATTERN (insn);
-  assert (GET_CODE (insn) == SET);
+  src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
+  if (src)
+    insn = XEXP (src, 0);
+  else
+    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)
+    abort ();
 
   src = SET_SRC (insn);
   dest = SET_DEST (insn);
@@ -874,10 +1252,12 @@ dwarf2out_frame_debug (insn)
        {
          /* Setting FP from SP.  */
        case REG:
-         assert (cfa_reg == REGNO (src));
-         assert (REGNO (dest) == STACK_POINTER_REGNUM
-                 || (frame_pointer_needed
-                     && REGNO (dest) == HARD_FRAME_POINTER_REGNUM));
+         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;
 
@@ -892,31 +1272,76 @@ dwarf2out_frame_debug (insn)
                  offset = INTVAL (XEXP (src, 1));
                  break;
                case REG:
-                 assert (REGNO (XEXP (src, 1)) == cfa_temp_reg);
+                 if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp_reg)
+                   abort ();
                  offset = cfa_temp_value;
                  break;
                default:
                  abort ();
                }
 
+             if (XEXP (src, 0) == hard_frame_pointer_rtx)
+               {
+                 /* Restoring SP from FP in the epilogue.  */
+                 if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
+                   abort ();
+                 cfa_reg = STACK_POINTER_REGNUM;
+               }
+             else if (XEXP (src, 0) != stack_pointer_rtx)
+               abort ();
+
              if (GET_CODE (src) == PLUS)
                offset = -offset;
              if (cfa_reg == STACK_POINTER_REGNUM)
                cfa_offset += offset;
              if (cfa_store_reg == STACK_POINTER_REGNUM)
                cfa_store_offset += offset;
-             assert (XEXP (src, 0) == stack_pointer_rtx);
            }
+          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
            {
-             /* Initializing the store base register.  */
-             assert (GET_CODE (src) == PLUS);
-             assert (XEXP (src, 1) == stack_pointer_rtx);
-             assert (GET_CODE (XEXP (src, 0)) == REG
-                     && REGNO (XEXP (src, 0)) == cfa_temp_reg);
-             assert (cfa_store_reg == STACK_POINTER_REGNUM);
+             if (GET_CODE (src) != PLUS
+                 || XEXP (src, 1) != stack_pointer_rtx)
+               abort ();
+             if (GET_CODE (XEXP (src, 0)) != 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_temp_value;
+             cfa_store_offset = cfa_offset - cfa_temp_value;
            }
          break;
 
@@ -926,10 +1351,11 @@ dwarf2out_frame_debug (insn)
          break;
 
        case IOR:
-         assert (GET_CODE (XEXP (src, 0)) == REG
-                 && REGNO (XEXP (src, 0)) == cfa_temp_reg);
-         assert (REGNO (dest) == cfa_temp_reg);
-         assert (GET_CODE (XEXP (src, 1)) == CONST_INT);
+         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;
 
@@ -942,18 +1368,20 @@ dwarf2out_frame_debug (insn)
     case MEM:
       /* Saving a register to the stack.  Make sure dest is relative to the
          CFA register.  */
-      assert (GET_CODE (src) == REG);
+      if (GET_CODE (src) != REG)
+       abort ();
       switch (GET_CODE (XEXP (dest, 0)))
        {
          /* With a push.  */
        case PRE_INC:
        case PRE_DEC:
          offset = GET_MODE_SIZE (GET_MODE (dest));
-         if (GET_CODE (src) == PRE_INC)
+         if (GET_CODE (XEXP (dest, 0)) == PRE_INC)
            offset = -offset;
 
-         assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM);
-         assert (cfa_store_reg == STACK_POINTER_REGNUM);
+         if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
+             || cfa_store_reg != STACK_POINTER_REGNUM)
+           abort ();
          cfa_store_offset += offset;
          if (cfa_reg == STACK_POINTER_REGNUM)
            cfa_offset = cfa_store_offset;
@@ -968,10 +1396,18 @@ dwarf2out_frame_debug (insn)
          if (GET_CODE (src) == MINUS)
            offset = -offset;
 
-         assert (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 ();
        }
@@ -1048,8 +1484,8 @@ output_uleb128 (value)
     }
   while (value != 0);
 
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s ULEB128 0x%x", ASM_COMMENT_START, save_value);
+  if (flag_debug_asm)
+    fprintf (asm_out_file, "\t%s ULEB128 0x%lx", ASM_COMMENT_START, save_value);
 }
 
 /* Output an signed LEB128 quantity.  */
@@ -1079,8 +1515,8 @@ output_sleb128 (value)
     }
 
   while (more);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s SLEB128 %d", ASM_COMMENT_START, save_value);
+  if (flag_debug_asm)
+    fprintf (asm_out_file, "\t%s SLEB128 %ld", ASM_COMMENT_START, save_value);
 }
 
 /* Output a Call Frame Information opcode and its operand(s).  */
@@ -1095,8 +1531,8 @@ output_cfi (cfi, fde)
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
                              cfi->dw_cfi_opc
                              | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f));
-      if (flag_verbose_asm)
-       fprintf (asm_out_file, "\t%s DW_CFA_advance_loc 0x%x",
+      if (flag_debug_asm)
+       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);
     }
@@ -1106,8 +1542,8 @@ output_cfi (cfi, fde)
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
                              cfi->dw_cfi_opc
                              | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
-      if (flag_verbose_asm)
-       fprintf (asm_out_file, "\t%s DW_CFA_offset, column 0x%x",
+      if (flag_debug_asm)
+       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);
@@ -1119,8 +1555,8 @@ output_cfi (cfi, fde)
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
                              cfi->dw_cfi_opc
                              | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
-      if (flag_verbose_asm)
-       fprintf (asm_out_file, "\t%s DW_CFA_restore, column 0x%x",
+      if (flag_debug_asm)
+       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);
@@ -1128,7 +1564,7 @@ output_cfi (cfi, fde)
   else
     {
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file, cfi->dw_cfi_opc);
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START,
                 dwarf_cfi_name (cfi->dw_cfi_opc));
 
@@ -1140,8 +1576,11 @@ output_cfi (cfi, fde)
           fputc ('\n', asm_out_file);
          break;
        case DW_CFA_advance_loc1:
-         /* TODO: not currently implemented.  */
-         abort ();
+         ASM_OUTPUT_DWARF_DELTA1 (asm_out_file,
+                                  cfi->dw_cfi_oprnd1.dw_cfi_addr,
+                                  fde->dw_fde_current_label);
+         fputc ('\n', asm_out_file);
+         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
          break;
        case DW_CFA_advance_loc2:
           ASM_OUTPUT_DWARF_DELTA2 (asm_out_file,
@@ -1192,12 +1631,34 @@ output_cfi (cfi, fde)
          break;
        case DW_CFA_GNU_window_save:
          break;
+       case DW_CFA_GNU_args_size:
+         output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
+          fputc ('\n', asm_out_file);
+         break;
        default:
          break;
        }
      }
 }
 
+#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
+
+/* If we aren't using crtstuff to run ctors, don't use it for EH.  */
+#if !defined (HAS_INIT_SECTION) && !defined (INIT_SECTION_ASM_OP)
+#undef EH_FRAME_SECTION
+#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.  */
@@ -1206,30 +1667,34 @@ 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];
+#endif
 
   /* Do we want to include a pointer to the exception table?  */
   int eh_ptr = for_eh && exception_table_p ();
 
-  /* Only output the info if it will be interesting.  */
-  for (i = 0; i < fde_table_in_use; ++i)
-    if (fde_table[i].dw_fde_cfi != NULL)
-      break;
-  if (i == fde_table_in_use)
-    return;
-
   fputc ('\n', asm_out_file);
+
+  /* We're going to be generating comments, so turn on app.  */
+  if (flag_debug_asm)
+    app_enable ();
+
   if (for_eh)
     {
 #ifdef EH_FRAME_SECTION
-      ASM_OUTPUT_SECTION_NAME (asm_out_file, NULL_TREE, EH_FRAME_SECTION, 0);
+      EH_FRAME_SECTION ();
 #else
+      tree label = get_file_function_name ('F');
+
       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));
 #endif
       assemble_label ("__FRAME_BEGIN__");
     }
@@ -1239,70 +1704,93 @@ output_call_frame_info (for_eh)
   /* Output the CIE. */
   ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
   ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
-  ASM_OUTPUT_DWARF_DELTA (asm_out_file, l2, l1);
-  if (flag_verbose_asm)
+#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
+  ASM_GENERATE_INTERNAL_LABEL (ld, CIE_LENGTH_LABEL, for_eh);
+  if (for_eh)
+    ASM_OUTPUT_DWARF_OFFSET4 (asm_out_file, ld);
+  else
+    ASM_OUTPUT_DWARF_OFFSET (asm_out_file, ld);
+#else
+  if (for_eh)
+    ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, l2, l1);
+  else
+    ASM_OUTPUT_DWARF_DELTA (asm_out_file, l2, l1);
+#endif
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Length of Common Information Entry",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_LABEL (asm_out_file, l1);
 
-  ASM_OUTPUT_DWARF_DATA4 (asm_out_file, DW_CIE_ID);
-  if (flag_verbose_asm)
+  if (for_eh)
+    /* Now that the CIE pointer is PC-relative for EH,
+       use 0 to identify the CIE.  */
+    ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
+  else
+    ASM_OUTPUT_DWARF_DATA4 (asm_out_file, DW_CIE_ID);
+
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s CIE Identifier Tag", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
-  if (DWARF_OFFSET_SIZE == 8)
+  if (! for_eh && DWARF_OFFSET_SIZE == 8)
     {
       ASM_OUTPUT_DWARF_DATA4 (asm_out_file, DW_CIE_ID);
       fputc ('\n', asm_out_file);
     }
 
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CIE_VERSION);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s CIE Version", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   if (eh_ptr)
     {
-      /* The "z" augmentation was defined by SGI; the FDE contains a pointer
-        to the exception region info for the frame.  */
-      ASM_OUTPUT_DWARF_STRING (asm_out_file, "z");
-      if (flag_verbose_asm)
-       fprintf (asm_out_file, "\t%s CIE Augmentation", ASM_COMMENT_START);
+      /* The CIE contains a pointer to the exception region info for the
+         frame.  Make the augmentation string three bytes (including the
+         trailing null) so the pointer is 4-byte aligned.  The Solaris ld
+         can't handle unaligned relocs.  */
+      if (flag_debug_asm)
+       {
+         ASM_OUTPUT_DWARF_STRING (asm_out_file, "eh");
+         fprintf (asm_out_file, "\t%s CIE Augmentation", ASM_COMMENT_START);
+       }
+      else
+       {
+         ASM_OUTPUT_ASCII (asm_out_file, "eh", 3);
+       }
+      fputc ('\n', asm_out_file);
+
+      ASM_OUTPUT_DWARF_ADDR (asm_out_file, "__EXCEPTION_TABLE__");
+      if (flag_debug_asm)
+       fprintf (asm_out_file, "\t%s pointer to exception region info",
+                ASM_COMMENT_START);
     }
   else
     {
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s CIE Augmentation (none)",
                 ASM_COMMENT_START);
     }
 
   fputc ('\n', asm_out_file);
   output_uleb128 (1);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, " (CIE Code Alignment Factor)");
 
   fputc ('\n', asm_out_file);
   output_sleb128 (DWARF_CIE_DATA_ALIGNMENT);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, " (CIE Data Alignment Factor)");
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DWARF_FRAME_RETURN_COLUMN);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s CIE RA Column", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
-  if (eh_ptr)
-    {
-      output_uleb128 (0);
-      if (flag_verbose_asm)
-       fprintf (asm_out_file, "\t%s CIE augmentation fields length",
-                ASM_COMMENT_START);
-      fputc ('\n', asm_out_file);
-    }
 
   for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
     output_cfi (cfi, NULL);
@@ -1310,61 +1798,64 @@ output_call_frame_info (for_eh)
   /* Pad the CIE out to an address sized boundary.  */
   ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
   ASM_OUTPUT_LABEL (asm_out_file, l2);
+#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
+  ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (asm_out_file, ld, l2, l1);
+  if (flag_debug_asm)
+    fprintf (asm_out_file, "\t%s CIE Length Symbol", ASM_COMMENT_START);
+  fputc ('\n', asm_out_file);
+#endif
 
   /* Loop through all of the FDE's.  */
   for (i = 0; i < fde_table_in_use; ++i)
     {
       fde = &fde_table[i];
-      if (fde->dw_fde_cfi == NULL)
-       continue;
 
       ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i*2);
       ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i*2);
-      ASM_OUTPUT_DWARF_DELTA (asm_out_file, l2, l1);
-      if (flag_verbose_asm)
+#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
+      ASM_GENERATE_INTERNAL_LABEL (ld, FDE_LENGTH_LABEL, for_eh + i*2);
+      if (for_eh)
+       ASM_OUTPUT_DWARF_OFFSET4 (asm_out_file, ld);
+      else
+       ASM_OUTPUT_DWARF_OFFSET (asm_out_file, ld);
+#else
+      if (for_eh)
+       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, l2, l1);
+      else
+       ASM_OUTPUT_DWARF_DELTA (asm_out_file, l2, l1);
+#endif
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s FDE Length", ASM_COMMENT_START);
       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_ADDR (asm_out_file, "__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_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s FDE CIE offset", ASM_COMMENT_START);
 
       fputc ('\n', asm_out_file);
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, fde->dw_fde_begin);
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s FDE initial location", ASM_COMMENT_START);
 
       fputc ('\n', asm_out_file);
       ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file,
                                   fde->dw_fde_end, fde->dw_fde_begin);
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s FDE address range", ASM_COMMENT_START);
 
       fputc ('\n', asm_out_file);
-      if (eh_ptr)
-       {
-         output_uleb128 (PTR_SIZE);
-         if (flag_verbose_asm)
-           fprintf (asm_out_file, "\t%s FDE augmentation fields length",
-                    ASM_COMMENT_START);
-         fputc ('\n', asm_out_file);
-
-         /* For now, a pointer to the translation unit's info will do.
-            ??? Eventually this should point to the function's info.  */
-         if (exception_table_p ())
-           ASM_OUTPUT_DWARF_ADDR (asm_out_file, "__EXCEPTION_TABLE__");
-         else
-           ASM_OUTPUT_DWARF_ADDR_DATA (asm_out_file, 0);
-
-         if (flag_verbose_asm)
-           fprintf (asm_out_file, "\t%s pointer to exception region info",
-                    ASM_COMMENT_START);
-         fputc ('\n', asm_out_file);
-       }
 
       /* Loop through the Call Frame Instructions associated with
         this FDE.  */
@@ -1375,12 +1866,18 @@ output_call_frame_info (for_eh)
       /* Pad the FDE out to an address sized boundary.  */
       ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
       ASM_OUTPUT_LABEL (asm_out_file, l2);
+#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
+      ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (asm_out_file, ld, l2, l1);
+      if (flag_debug_asm)
+       fprintf (asm_out_file, "\t%s FDE Length Symbol", ASM_COMMENT_START);
+      fputc ('\n', asm_out_file);
+#endif
     }
 #ifndef EH_FRAME_SECTION
   if (for_eh)
     {
       /* Emit terminating zero for table.  */
-      ASM_OUTPUT_DWARF_DATA (asm_out_file, 0);
+      ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
       fputc ('\n', asm_out_file);
     }
 #endif
@@ -1389,16 +1886,10 @@ output_call_frame_info (for_eh)
      get a value of 0.  Putting .align 0 after the label fixes it.  */
   ASM_OUTPUT_ALIGN (asm_out_file, 0);
 #endif
-}
-
-/* Decide whether we want to emit frame unwind information for the current
-   translation unit.  */
 
-int
-dwarf2out_do_frame ()
-{
-  return (write_symbols == DWARF2_DEBUG
-         || (flag_exceptions && ! exceptions_via_longjmp));
+  /* Turn off app to make assembly quicker.  */
+  if (flag_debug_asm)
+    app_disable ();
 }
 
 /* Output a marker (i.e. a label) for the beginning of a function, before
@@ -1435,6 +1926,8 @@ dwarf2out_begin_prologue ()
   fde->dw_fde_current_label = NULL;
   fde->dw_fde_end = NULL;
   fde->dw_fde_cfi = NULL;
+
+  args_size = old_args_size = 0;
 }
 
 /* Output a marker (i.e. a label) for the absolute end of the generated code
@@ -1496,7 +1989,7 @@ dwarf2out_frame_finish ()
 /* And now, the support for symbolic debugging information.  */
 #ifdef DWARF2_DEBUGGING_INFO
 
-extern char *getpwd ();
+extern char *getpwd PROTO((void));
 
 /* NOTE: In the comments in this file, many references are made to
    "Debugging Information Entries".  This term is abbreviated as `DIE'
@@ -1563,7 +2056,7 @@ typedef struct dw_fp_struct
 dw_float_const;
 
 /* Each entry in the line_info_table maintains the file and
-   line nuber associated with the label generated for that
+   line number associated with the label generated for that
    entry.  The label gives the PC value associated with
    the line number entry.  */
 
@@ -1584,7 +2077,7 @@ typedef struct dw_separate_line_info_struct
 }
 dw_separate_line_info_entry;
 
-/* The dw_val_node describes an attibute's value, as it is
+/* The dw_val_node describes an attribute's value, as it is
    represented internally.  */
 
 typedef struct dw_val_struct
@@ -1777,7 +2270,7 @@ static unsigned next_block_number = 2;
 
 /* A pointer to the base of a table of references to DIE's that describe
    declarations.  The table is indexed by DECL_UID() which is a unique
-   number, indentifying each decl.  */
+   number identifying each decl.  */
 static dw_die_ref *decl_die_table;
 
 /* Number of elements currently allocated for the decl_die_table.  */
@@ -1790,18 +2283,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 declataion scopes.  */
-static unsigned decl_scope_depth;
+/* Current level of nesting of declaration scopes.  */
+static int decl_scope_depth;
 
 /* Size (in elements) of increments by which we may expand the
    decl_scope_table.  */
@@ -1893,7 +2397,9 @@ static unsigned pending_types;
 
 /* 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
@@ -1903,7 +2409,7 @@ 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));
@@ -1912,7 +2418,9 @@ 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));
+#if 0
 static 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));
@@ -1946,7 +2454,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_setion_offset       PROTO((dw_die_ref,
+static void add_AT_section_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,
@@ -1977,7 +2485,7 @@ static void add_loc_descr         PROTO((dw_loc_descr_ref *,
 static void print_spaces               PROTO((FILE *));
 static void print_die                  PROTO((dw_die_ref, FILE *));
 static void print_dwarf_line_table     PROTO((FILE *));
-static void add_sibling_atttributes    PROTO((dw_die_ref));
+static void add_sibling_attributes     PROTO((dw_die_ref));
 static void build_abbrev_table         PROTO((dw_die_ref));
 static unsigned long size_of_string    PROTO((char *));
 static unsigned long size_of_loc_descr PROTO((dw_loc_descr_ref));
@@ -1985,7 +2493,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));
@@ -1999,8 +2507,8 @@ static void output_compilation_unit_header PROTO((void));
 static 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));
@@ -2008,10 +2516,11 @@ static tree root_type                   PROTO((tree));
 static int is_base_type                        PROTO((tree));
 static dw_die_ref modified_type_die    PROTO((tree, int, int, dw_die_ref));
 static int type_is_enum                        PROTO((tree));
-static dw_loc_descr_ref reg_loc_descr_ref PROTO((rtx));
+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 concat_loc_descriptor PROTO((rtx, rtx));
 static dw_loc_descr_ref loc_descriptor PROTO((rtx));
 static unsigned ceiling                        PROTO((unsigned, unsigned));
 static tree field_type                 PROTO((tree));
@@ -2034,7 +2543,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));
@@ -2042,10 +2551,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));
@@ -2059,7 +2572,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 *));
@@ -2103,7 +2616,7 @@ static unsigned lookup_filename           PROTO((char *));
 #define STR_SECTION            ".debug_str"
 #endif
 
-/* Standerd ELF section names for compiled code and data.  */
+/* Standard ELF section names for compiled code and data.  */
 #ifndef TEXT_SECTION
 #define TEXT_SECTION           ".text"
 #endif
@@ -2158,13 +2671,16 @@ 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                                             \
+       {                                               \
+         dyn_string_append (STR, user_label_prefix);   \
+         dyn_string_append (STR, NAME);                \
+       }                                               \
+  }                                                    \
   while (0)
 #endif
 \f
@@ -2176,50 +2692,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:
@@ -2234,7 +2744,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
@@ -2246,23 +2756,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;
 
@@ -2273,28 +2779,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:
@@ -2309,12 +2809,19 @@ 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 psuedo register.  */
+/* Test if rtl node points to a pseudo register.  */
 
 static inline int
 is_pseudo_reg (rtl)
@@ -3008,6 +3515,7 @@ dwarf_stack_op_name (op)
 
 /* Convert a DWARF type code into its string name.  */
 
+#if 0
 static char *
 dwarf_type_encoding_name (enc)
      register unsigned enc;
@@ -3034,6 +3542,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
@@ -3045,24 +3554,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
@@ -3584,7 +4083,8 @@ add_child_die (die, child_die)
 {
   if (die != NULL && child_die != NULL)
     {
-      assert (die != child_die);
+      if (die == child_die)
+       abort ();
       child_die->die_parent = die;
       child_die->die_sib = NULL;
 
@@ -3674,7 +4174,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)
@@ -3752,7 +4251,7 @@ print_spaces (outfile)
   fprintf (outfile, "%*s", print_indent, "");
 }
 
-/* Print the information assoaciated with a given DIE, and its children.
+/* Print the information associated with a given DIE, and its children.
    This routine is a debugging aid only.  */
 
 static void
@@ -3764,11 +4263,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)
     {
@@ -3784,13 +4283,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;
@@ -3802,7 +4301,7 @@ 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>");
@@ -3819,6 +4318,8 @@ print_die (die, outfile)
          else
            fprintf (outfile, "<null>");
          break;
+       default:
+         break;
        }
 
       fprintf (outfile, "\n");
@@ -3850,7 +4351,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");
     }
 
@@ -3955,8 +4456,8 @@ build_abbrev_table (die)
        {
          n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
          abbrev_die_table 
-           = (dw_die_ref *) xmalloc (abbrev_die_table,
-                                     sizeof (dw_die_ref) * n_alloc);
+           = (dw_die_ref *) xrealloc (abbrev_die_table,
+                                      sizeof (dw_die_ref) * n_alloc);
 
          bzero ((char *) &abbrev_die_table[abbrev_die_table_allocated],
                 (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
@@ -3972,29 +4473,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.  */
@@ -4199,10 +4689,10 @@ size_of_die (die)
   return size;
 }
 
-/* Size the debgging information associted with a given DIE.
+/* Size the debugging information associated with a given DIE.
    Visits the DIE's children recursively.  Updates the global
    variable next_die_offset, on each time through.  Uses the
-   current value of next_die_offset to updete the die_offset
+   current value of next_die_offset to update the die_offset
    field in each DIE.  */
 
 static void
@@ -4237,7 +4727,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)
@@ -4432,7 +4922,7 @@ size_of_pubnames ()
   return size;
 }
 
-/* Return the size of the information in the .debug_aranges seciton.  */
+/* Return the size of the information in the .debug_aranges section.  */
 
 static unsigned long
 size_of_aranges ()
@@ -4516,7 +5006,7 @@ output_value_format (v)
   enum dwarf_form form = value_format (v);
 
   output_uleb128 (form);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, " (%s)", dwarf_form_name (form));
 
   fputc ('\n', asm_out_file);
@@ -4536,12 +5026,12 @@ output_abbrev_section ()
       register dw_die_ref abbrev = abbrev_die_table[abbrev_id];
 
       output_uleb128 (abbrev_id);
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, " (abbrev code)");
 
       fputc ('\n', asm_out_file);
       output_uleb128 (abbrev->die_tag);
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, " (TAG: %s)",
                 dwarf_tag_name (abbrev->die_tag));
 
@@ -4549,7 +5039,7 @@ output_abbrev_section ()
       fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP,
               abbrev->die_child != NULL ? DW_children_yes : DW_children_no);
 
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s %s",
                 ASM_COMMENT_START,
                 (abbrev->die_child != NULL
@@ -4561,7 +5051,7 @@ output_abbrev_section ()
           a_attr = a_attr->dw_attr_next)
        {
          output_uleb128 (a_attr->dw_attr);
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, " (%s)",
                     dwarf_attr_name (a_attr->dw_attr));
 
@@ -4720,11 +5210,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_verbose_asm)
-    fprintf (asm_out_file, " (DIE (0x%x) %s)",
+  if (flag_debug_asm)
+    fprintf (asm_out_file, " (DIE (0x%lx) %s)",
             die->die_offset, dwarf_tag_name (die->die_tag));
 
   fputc ('\n', asm_out_file);
@@ -4754,7 +5243,7 @@ output_die (die)
              abort ();
            }
 
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s %s",
                     ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
 
@@ -4764,7 +5253,7 @@ output_die (die)
            {
              /* Output the opcode.  */
              ASM_OUTPUT_DWARF_DATA1 (asm_out_file, loc->dw_loc_opc);
-             if (flag_verbose_asm)
+             if (flag_debug_asm)
                fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START,
                         dwarf_stack_op_name (loc->dw_loc_opc));
 
@@ -4806,7 +5295,7 @@ output_die (die)
 
        case dw_val_class_long_long:
          ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 8);
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s %s",
                   ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
 
@@ -4815,7 +5304,7 @@ output_die (die)
                                  a->dw_attr_val.v.val_long_long.hi,
                                  a->dw_attr_val.v.val_long_long.low);
 
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file,
                     "\t%s long long constant", ASM_COMMENT_START);
          
@@ -4823,24 +5312,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_verbose_asm)
-           fprintf (asm_out_file, "\t%s %s",
-                    ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
-
-         fputc ('\n', asm_out_file);
-         for (i = 0; i < a->dw_attr_val.v.val_float.length; ++i)
-           {
-             ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
-                                     a->dw_attr_val.v.val_float.array[i]);
-             if (flag_verbose_asm)
-               fprintf (asm_out_file, "\t%s fp constant word %d",
-                        ASM_COMMENT_START, i);
+         {
+           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);
@@ -4878,7 +5370,12 @@ output_die (die)
          break;
 
        case dw_val_class_str:
-         ASM_OUTPUT_DWARF_STRING (asm_out_file, a->dw_attr_val.v.val_str);
+         if (flag_debug_asm)
+           ASM_OUTPUT_DWARF_STRING (asm_out_file, a->dw_attr_val.v.val_str);
+         else
+           ASM_OUTPUT_ASCII (asm_out_file,
+                             a->dw_attr_val.v.val_str,
+                             (int) strlen (a->dw_attr_val.v.val_str) + 1);
          break;
 
        default:
@@ -4889,7 +5386,7 @@ output_die (die)
          && a->dw_attr_val.val_class != dw_val_class_long_long
          && a->dw_attr_val.val_class != dw_val_class_float)
        {
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s %s",
                     ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
 
@@ -4904,8 +5401,8 @@ output_die (die)
     {
       /* Add null byte to terminate sibling list. */
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-      if (flag_verbose_asm)
-       fprintf (asm_out_file, "\t%s end of children of DIE 0x%x",
+      if (flag_debug_asm)
+       fprintf (asm_out_file, "\t%s end of children of DIE 0x%lx",
                 ASM_COMMENT_START, die->die_offset);
 
       fputc ('\n', asm_out_file);
@@ -4919,24 +5416,24 @@ static void
 output_compilation_unit_header ()
 {
   ASM_OUTPUT_DWARF_DATA (asm_out_file, next_die_offset - DWARF_OFFSET_SIZE);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Length of Compilation Unit Info.",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA2 (asm_out_file, DWARF_VERSION);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     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));
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Offset Into Abbrev. Section",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, PTR_SIZE);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Pointer Size (in bytes)", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
@@ -4991,25 +5488,25 @@ output_pubnames ()
 
   ASM_OUTPUT_DWARF_DATA (asm_out_file, pubnames_length);
 
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Length of Public Names Info.",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA2 (asm_out_file, DWARF_VERSION);
 
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     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));
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA (asm_out_file, next_die_offset);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Compilation Unit Length", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
@@ -5018,14 +5515,21 @@ output_pubnames ()
       register pubname_ref pub = &pubname_table[i];
 
       ASM_OUTPUT_DWARF_DATA (asm_out_file, pub->die->die_offset);
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s DIE offset", ASM_COMMENT_START);
 
       fputc ('\n', asm_out_file);
 
-      ASM_OUTPUT_DWARF_STRING (asm_out_file, pub->name);
-      if (flag_verbose_asm)
-       fprintf (asm_out_file, "%s external name", ASM_COMMENT_START);
+      if (flag_debug_asm)
+       {
+         ASM_OUTPUT_DWARF_STRING (asm_out_file, pub->name);
+         fprintf (asm_out_file, "%s external name", ASM_COMMENT_START);
+       }
+      else
+       {
+         ASM_OUTPUT_ASCII (asm_out_file, pub->name,
+                           (int) strlen (pub->name) + 1);
+       }
 
       fputc ('\n', asm_out_file);
     }
@@ -5066,29 +5570,29 @@ output_aranges ()
   register unsigned long aranges_length = size_of_aranges ();
 
   ASM_OUTPUT_DWARF_DATA (asm_out_file, aranges_length);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Length of Address Ranges Info.",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA2 (asm_out_file, DWARF_VERSION);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     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));
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, PTR_SIZE);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Size of Address", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Size of Segment Descriptor",
             ASM_COMMENT_START);
 
@@ -5097,18 +5601,19 @@ output_aranges ()
   if (PTR_SIZE == 8)
     fprintf (asm_out_file, ",0,0");
 
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Pad to %d byte boundary",
             ASM_COMMENT_START, 2 * PTR_SIZE);
 
   fputc ('\n', asm_out_file);
-  ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_SECTION);
-  if (flag_verbose_asm)
+  ASM_OUTPUT_DWARF_ADDR (asm_out_file, stripattributes (TEXT_SECTION));
+  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);
-  if (flag_verbose_asm)
+  ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, text_end_label,
+                              stripattributes (TEXT_SECTION));
+  if (flag_debug_asm)
     fprintf (asm_out_file, "%s Length", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
@@ -5127,7 +5632,7 @@ output_aranges ()
          ASM_OUTPUT_DWARF_ADDR (asm_out_file, name);
        }
 
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s Address", ASM_COMMENT_START);
 
       fputc ('\n', asm_out_file);
@@ -5138,7 +5643,7 @@ output_aranges ()
        ASM_OUTPUT_DWARF_ADDR_DATA (asm_out_file,
                                    get_AT_unsigned (a, DW_AT_byte_size));
 
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "%s Length", ASM_COMMENT_START);
 
       fputc ('\n', asm_out_file);
@@ -5173,47 +5678,47 @@ output_line_info ()
   register unsigned long function;
 
   ASM_OUTPUT_DWARF_DATA (asm_out_file, size_of_line_info ());
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Length of Source Line Info.",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA2 (asm_out_file, DWARF_VERSION);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s DWARF Version", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA (asm_out_file, size_of_line_prolog ());
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Prolog Length", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DWARF_LINE_MIN_INSTR_LENGTH);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Minimum Instruction Length",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DWARF_LINE_DEFAULT_IS_STMT_START);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Default is_stmt_start flag",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   fprintf (asm_out_file, "\t%s\t%d", ASM_BYTE_OP, DWARF_LINE_BASE);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Line Base Value (Special Opcodes)",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   fprintf (asm_out_file, "\t%s\t%u", ASM_BYTE_OP, DWARF_LINE_RANGE);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Line Range Value (Special Opcodes)",
             ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
   fprintf (asm_out_file, "\t%s\t%u", ASM_BYTE_OP, DWARF_LINE_OPCODE_BASE);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s Special Opcode Base", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
@@ -5233,27 +5738,35 @@ output_line_info ()
          break;
        }
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file, n_op_args);
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s opcode: 0x%x has %d args",
                 ASM_COMMENT_START, opc, n_op_args);
       fputc ('\n', asm_out_file);
     }
 
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "%s Include Directory Table\n", ASM_COMMENT_START);
 
   /* Include directory table is empty, at present */
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
   fputc ('\n', asm_out_file);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "%s File Name Table\n", ASM_COMMENT_START);
 
   for (ft_index = 1; ft_index < file_table_in_use; ++ft_index)
     {
-      ASM_OUTPUT_DWARF_STRING (asm_out_file, file_table[ft_index]);
-      if (flag_verbose_asm)
-       fprintf (asm_out_file, "%s File Entry: 0x%x",
-                ASM_COMMENT_START, ft_index);
+      if (flag_debug_asm)
+       {
+         ASM_OUTPUT_DWARF_STRING (asm_out_file, file_table[ft_index]);
+         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],
+                           (int) strlen (file_table[ft_index]) + 1);
+       }
 
       fputc ('\n', asm_out_file);
 
@@ -5276,7 +5789,7 @@ output_line_info ()
 
   /* Set the address register to the first location in the text section */
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s DW_LNE_set_address", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
@@ -5284,14 +5797,14 @@ output_line_info ()
   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);
+  ASM_OUTPUT_DWARF_ADDR (asm_out_file, stripattributes (TEXT_SECTION));
   fputc ('\n', asm_out_file);
 
   /* 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, stripattributes (TEXT_SECTION));
   for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
     {
       register dw_line_info_ref line_info;
@@ -5311,7 +5824,7 @@ output_line_info ()
        {
          /* This can handle deltas up to 0xffff.  This takes 3 bytes.  */
          ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc);
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s DW_LNS_fixed_advance_pc",
                     ASM_COMMENT_START);
 
@@ -5323,7 +5836,7 @@ output_line_info ()
        {
          /* This can handle any delta.  This takes 4+PTR_SIZE bytes.  */
          ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s DW_LNE_set_address",
                     ASM_COMMENT_START);
          fputc ('\n', asm_out_file);
@@ -5343,12 +5856,12 @@ output_line_info ()
        {
          current_file = line_info->dw_file_num;
          ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_set_file);
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s DW_LNS_set_file", ASM_COMMENT_START);
 
          fputc ('\n', asm_out_file);
          output_uleb128 (current_file);
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, " (\"%s\")", file_table[current_file]);
 
          fputc ('\n', asm_out_file);
@@ -5366,9 +5879,9 @@ output_line_info ()
             takes 1 byte.  */
          ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
                                  DWARF_LINE_OPCODE_BASE + line_delta);
-         if (flag_verbose_asm)
+         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);
        }
@@ -5377,8 +5890,8 @@ output_line_info ()
          /* 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_verbose_asm)
-           fprintf (asm_out_file, "\t%s advance to line %d",
+         if (flag_debug_asm)
+           fprintf (asm_out_file, "\t%s advance to line %ld",
                     ASM_COMMENT_START, current_line);
 
          fputc ('\n', asm_out_file);
@@ -5393,7 +5906,7 @@ output_line_info ()
   if (0)
     {
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc);
-      if (flag_verbose_asm)
+      if (flag_debug_asm)
        fprintf (asm_out_file, "\t%s DW_LNS_fixed_advance_pc",
                 ASM_COMMENT_START);
 
@@ -5404,7 +5917,7 @@ output_line_info ()
   else
     {
       ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-      if (flag_verbose_asm)
+      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);
@@ -5417,7 +5930,7 @@ output_line_info ()
 
   /* Output the marker for the end of the line number info.  */
   ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "\t%s DW_LNE_end_sequence", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
@@ -5445,7 +5958,7 @@ output_line_info ()
 
          /* Set the address register to the first line in the function */
          ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s DW_LNE_set_address",
                     ASM_COMMENT_START);
 
@@ -5463,7 +5976,7 @@ output_line_info ()
          if (0)
            {
              ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc);
-             if (flag_verbose_asm)
+             if (flag_debug_asm)
                fprintf (asm_out_file, "\t%s DW_LNS_fixed_advance_pc",
                         ASM_COMMENT_START);
 
@@ -5475,7 +5988,7 @@ output_line_info ()
          else
            {
              ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-             if (flag_verbose_asm)
+             if (flag_debug_asm)
                fprintf (asm_out_file, "\t%s DW_LNE_set_address",
                         ASM_COMMENT_START);
              fputc ('\n', asm_out_file);
@@ -5495,12 +6008,12 @@ output_line_info ()
        {
          current_file = line_info->dw_file_num;
          ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_set_file);
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s DW_LNS_set_file", ASM_COMMENT_START);
 
          fputc ('\n', asm_out_file);
          output_uleb128 (current_file);
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, " (\"%s\")", file_table[current_file]);
 
          fputc ('\n', asm_out_file);
@@ -5517,17 +6030,17 @@ output_line_info ()
            {
              ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
                                      DWARF_LINE_OPCODE_BASE + line_delta);
-             if (flag_verbose_asm)
+             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);
            }
          else
            {
              ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
-             if (flag_verbose_asm)
-               fprintf (asm_out_file, "\t%s advance to line %d",
+             if (flag_debug_asm)
+               fprintf (asm_out_file, "\t%s advance to line %ld",
                         ASM_COMMENT_START, current_line);
 
              fputc ('\n', asm_out_file);
@@ -5552,7 +6065,7 @@ output_line_info ()
          if (0)
            {
              ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc);
-             if (flag_verbose_asm)
+             if (flag_debug_asm)
                fprintf (asm_out_file, "\t%s DW_LNS_fixed_advance_pc",
                         ASM_COMMENT_START);
 
@@ -5564,7 +6077,7 @@ output_line_info ()
          else
            {
              ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-             if (flag_verbose_asm)
+             if (flag_debug_asm)
                fprintf (asm_out_file, "\t%s DW_LNE_set_address",
                         ASM_COMMENT_START);
              fputc ('\n', asm_out_file);
@@ -5578,7 +6091,7 @@ output_line_info ()
 
          /* Output the marker for the end of this sequence.  */
          ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-         if (flag_verbose_asm)
+         if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s DW_LNE_end_sequence",
                     ASM_COMMENT_START);
 
@@ -5692,7 +6205,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;
@@ -5857,7 +6370,8 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
             that copy might have a different TYPE_UID from the original
             ..._TYPE node.  */
          mod_type_die = lookup_type_die (type_main_variant (type));
-         assert (mod_type_die != NULL);
+         if (mod_type_die == NULL)
+           abort ();
        }
     }
 
@@ -5897,7 +6411,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);
@@ -5922,7 +6436,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);
@@ -6033,6 +6547,30 @@ mem_loc_descriptor (rtl)
   return mem_loc_result;
 }
 
+/* Return a descriptor that describes the concatenation of two locations.
+   This is typically a complex variable.  */
+
+static dw_loc_descr_ref
+concat_loc_descriptor (x0, x1)
+     register rtx x0, x1;
+{
+  dw_loc_descr_ref cc_loc_result = NULL;
+
+  if (!is_pseudo_reg (x0)
+      && (GET_CODE (x0) != MEM || !is_pseudo_reg (XEXP (x0, 0))))
+    add_loc_descr (&cc_loc_result, loc_descriptor (x0));
+  add_loc_descr (&cc_loc_result,
+                new_loc_descr (DW_OP_piece, GET_MODE_SIZE (GET_MODE (x0)), 0));
+
+  if (!is_pseudo_reg (x1)
+      && (GET_CODE (x1) != MEM || !is_pseudo_reg (XEXP (x1, 0))))
+    add_loc_descr (&cc_loc_result, loc_descriptor (x1));
+  add_loc_descr (&cc_loc_result,
+                new_loc_descr (DW_OP_piece, GET_MODE_SIZE (GET_MODE (x1)), 0));
+
+  return cc_loc_result;
+}
+
 /* Output a proper Dwarf location descriptor for a variable or parameter
    which is either allocated in a register or in a memory location.  For a
    register, we just generate an OP_REG and the register number.  For a
@@ -6064,6 +6602,10 @@ loc_descriptor (rtl)
       loc_result = mem_loc_descriptor (XEXP (rtl, 0));
       break;
 
+    case CONCAT:
+      loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1));
+      break;
+
     default:
       abort ();
     }
@@ -6260,38 +6802,24 @@ add_AT_location_description (die, attr_kind, rtl)
      enum dwarf_attribute attr_kind;
      register rtx rtl;
 {
-  dw_loc_descr_ref loc_descr = NULL;
-
   /* Handle a special case.  If we are about to output a location descriptor
      for a variable or parameter which has been optimized out of existence,
-     don't do that.  Instead we output a null location descriptor value as
-     part of the location attribute. A variable which has been optimized out
+     don't do that.  A variable which has been optimized out
      of existence will have a DECL_RTL value which denotes a pseudo-reg.
      Currently, in some rare cases, variables can have DECL_RTL values which
      look like (MEM (REG pseudo-reg#)).  These cases are due to bugs
      elsewhere in the compiler.  We treat such cases as if the variable(s) in 
-     question had been optimized out of existence. Note that in all cases
-     where we wish to express the fact that a variable has been optimized out 
-     of existence, we do not simply suppress the generation of the entire
-     location attribute because the absence of a location attribute in
-     certain kinds of DIEs is used to indicate something else entirely...
-     i.e. that the DIE represents an object declaration, but not a
-     definition.  So sayeth the PLSIG.  */
-
-  if (!is_pseudo_reg (rtl)
-      && (GET_CODE (rtl) != MEM
-         || !is_pseudo_reg (XEXP (rtl, 0))))
-    loc_descr = loc_descriptor (eliminate_regs (rtl, 0, NULL_RTX, 0));
-
-#ifdef MIPS_DEBUGGING_INFO
-  /* ??? SGI's dwarf reader is buggy, and will not accept a zero size
-     location descriptor.  Lets just use r0 for now to represent a
-     variable that has been optimized away.  */
-  if (loc_descr == NULL)
-    loc_descr = loc_descriptor (gen_rtx (REG, word_mode, 0));
-#endif
+     question had been optimized out of existence.  */
+
+  if (is_pseudo_reg (rtl)
+      || (GET_CODE (rtl) == MEM
+         && is_pseudo_reg (XEXP (rtl, 0)))
+      || (GET_CODE (rtl) == CONCAT
+         && is_pseudo_reg (XEXP (rtl, 0))
+         && is_pseudo_reg (XEXP (rtl, 1))))
+    return;
 
-  add_AT_loc (die, attr_kind, loc_descr);
+  add_AT_loc (die, attr_kind, loc_descriptor (rtl));
 }
 
 /* Attach the specialized form of location attribute used for data
@@ -6428,9 +6956,7 @@ add_const_value_attribute (die, rtl)
          of the (artificial) local variable either.  Rather, it represents the 
          *value* which the artificial local variable always has during its
          lifetime.  We currently have no way to represent such quasi-constant 
-         values in Dwarf, so for now we just punt and generate an
-         DW_AT_const_value attribute with null address.  */
-      add_AT_addr (die, DW_AT_const_value, addr_to_string (const0_rtx));
+         values in Dwarf, so for now we just punt and generate nothing.  */
       break;
 
     default:
@@ -6538,7 +7064,7 @@ add_location_or_const_value_attribute (die, decl)
      get valid non-NULL DECL_INCOMING_RTL values, but integrate.c
      doesn't currently generate these values for inlined instances of
      inline function parameters, so when we see such cases, we are
-     just SOL (shit-out-of-luck) for the time being (until integrate.c
+     just out-of-luck for the time being (until integrate.c
      gets fixed).  */
 
   /* Use DECL_RTL as the "location" unless we find something better.  */
@@ -6566,8 +7092,19 @@ add_location_or_const_value_attribute (die, decl)
   if (rtl == NULL_RTX)
     return;
 
+  rtl = eliminate_regs (rtl, 0, NULL_RTX);
+#ifdef LEAF_REG_REMAP
+  if (leaf_function)
+    leaf_renumber_regs_insn (rtl);
+#endif
+
   switch (GET_CODE (rtl))
     {
+    case ADDRESSOF:
+      /* The address of a variable that was optimized away; don't emit
+        anything.  */
+      break;
+
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_STRING:
@@ -6582,6 +7119,7 @@ add_location_or_const_value_attribute (die, decl)
     case MEM:
     case REG:
     case SUBREG:
+    case CONCAT:
       add_AT_location_description (die, DW_AT_location, rtl);
       break;
 
@@ -6668,10 +7206,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);
        }
 
@@ -6680,6 +7230,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;
@@ -6697,7 +7248,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;
 
@@ -6748,14 +7301,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
     }
@@ -6829,8 +7391,10 @@ add_bit_offset_attribute (die, decl)
   register unsigned highest_order_field_bit_offset;
   register unsigned bit_offset;
 
-  assert (TREE_CODE (decl) == FIELD_DECL);     /* Must be a field.  */
-  assert (type);                               /* Must be a bit field.  */
+  /* Must be a field and a bit field.  */
+  if (!type
+      || TREE_CODE (decl) != FIELD_DECL)
+    abort ();
 
   /* We can't yet handle bit-fields whose offsets are variable, so if we
      encounter such things, just return without generating any attribute
@@ -6872,8 +7436,10 @@ add_bit_size_attribute (die, decl)
      register dw_die_ref die;
      register tree decl;
 {
-  assert (TREE_CODE (decl) == FIELD_DECL);     /* Must be a field.  */
-  assert (DECL_BIT_FIELD_TYPE (decl));         /* Must be a bit field.  */
+  /* Must be a field and a bit field.  */
+  if (TREE_CODE (decl) != FIELD_DECL
+      || ! DECL_BIT_FIELD_TYPE (decl))
+    abort ();
   add_AT_unsigned (die, DW_AT_bit_size,
                   (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl)));
 }
@@ -6973,19 +7539,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 = 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 (TREE_CODE_CLASS (TREE_CODE (scope)) == 't')
+    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_table[decl_scope_depth++] = scope;
+  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)
@@ -6994,7 +7596,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.  */
@@ -7005,6 +7607,10 @@ 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;
+
   /* 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
@@ -7015,17 +7621,38 @@ 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))
        {
-         assert (scope_die == comp_unit_die);
-         assert (TREE_CODE_CLASS (TREE_CODE (containing_scope)) == 't');
-         if (debug_info_level > DINFO_LEVEL_TERSE)
-           assert (TREE_ASM_WRITTEN (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')
+           abort ();
+         if (debug_info_level > DINFO_LEVEL_TERSE
+             && !TREE_ASM_WRITTEN (containing_scope))
+           abort ();
        }
     }
 
@@ -7036,7 +7663,8 @@ scope_die_for (t, context_die)
 static inline void
 pop_decl_scope ()
 {
-  assert (decl_scope_depth > 0);
+  if (decl_scope_depth <= 0)
+    abort ();
   --decl_scope_depth;
 }
 
@@ -7128,6 +7756,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;
@@ -7145,8 +7774,9 @@ decl_start_label (decl)
   fnname = XSTR (x, 0);
   return fnname;
 }
+#endif
 \f
-/* These routines generate the internnal representation of the DIE's for
+/* These routines generate the internal representation of the DIE's for
    the compilation unit.  Debugging information is collected by walking
    the declaration trees passed in from dwarf2out_decl().  */
 
@@ -7219,6 +7849,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;
@@ -7240,6 +7871,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.  */
 
@@ -7275,7 +7907,8 @@ output_pending_types_for_scope (context_die)
       --pending_types;
       type = pending_types_list[pending_types];
       gen_type_die (type, context_die);
-      assert (TREE_ASM_WRITTEN (type));
+      if (!TREE_ASM_WRITTEN (type))
+       abort ();
     }
 }
 
@@ -7289,7 +7922,8 @@ gen_inlined_enumeration_type_die (type, context_die)
   register dw_die_ref type_die = new_die (DW_TAG_enumeration_type,
                                          scope_die_for (type, context_die));
 
-  assert (TREE_ASM_WRITTEN (type));
+  if (!TREE_ASM_WRITTEN (type))
+    abort ();
   add_abstract_origin_attribute (type_die, type);
 }
 
@@ -7303,7 +7937,8 @@ gen_inlined_structure_type_die (type, context_die)
   register dw_die_ref type_die = new_die (DW_TAG_structure_type,
                                          scope_die_for (type, context_die));
 
-  assert (TREE_ASM_WRITTEN (type));
+  if (!TREE_ASM_WRITTEN (type))
+    abort ();
   add_abstract_origin_attribute (type_die, type);
 }
 
@@ -7317,7 +7952,8 @@ gen_inlined_union_type_die (type, context_die)
   register dw_die_ref type_die = new_die (DW_TAG_union_type,
                                          scope_die_for (type, context_die));
 
-  assert (TREE_ASM_WRITTEN (type));
+  if (!TREE_ASM_WRITTEN (type))
+    abort ();
   add_abstract_origin_attribute (type_die, type);
 }
 
@@ -7354,7 +7990,7 @@ gen_enumeration_type_die (type, context_die)
 
       TREE_ASM_WRITTEN (type) = 1;
       add_byte_size_attribute (type_die, type);
-      if (type_tag (type))
+      if (TYPE_STUB_DECL (type) != NULL_TREE)
        add_src_coords_attributes (type_die, TYPE_STUB_DECL (type));
 
       /* If the first reference to this type was as the return type of an
@@ -7443,8 +8079,7 @@ gen_unspecified_parameters_die (decl_or_type, context_die)
      register tree decl_or_type;
      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
@@ -7526,7 +8161,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;
@@ -7542,12 +8176,34 @@ gen_subprogram_die (decl, context_die)
       subr_die = new_die (DW_TAG_subprogram, context_die);
       add_abstract_origin_attribute (subr_die, origin);
     }
+  else if (old_die && DECL_ABSTRACT (decl)
+          && get_AT_unsigned (old_die, DW_AT_inline))
+    {
+      /* This must be a redefinition of an extern inline function.
+        We can just reuse the old die here.  */
+      subr_die = old_die;
+
+      /* Clear out the inlined attribute and parm types.  */
+      remove_AT (subr_die, DW_AT_inline);
+      remove_children (subr_die);
+    }
   else if (old_die)
     {
       register unsigned file_index
        = lookup_filename (DECL_SOURCE_FILE (decl));
 
-      assert (get_AT_flag (old_die, DW_AT_declaration) == 1);
+      if (get_AT_flag (old_die, DW_AT_declaration) != 1)
+       {
+         /* ??? 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.  */
+         extern int errorcount;
+         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
@@ -7621,11 +8277,15 @@ gen_subprogram_die (decl, context_die)
          the class to which it belongs.  We make sure of this by emitting
          the class first.  The next time is the definition, which is
          handled above.  The two may come from the same source text.  */
-      if (decl_class_context (decl))
+      if (DECL_CONTEXT (decl))
        equate_decl_number_to_die (decl, subr_die);
     }
   else if (DECL_ABSTRACT (decl))
     {
+      /* ??? Checking DECL_DEFER_OUTPUT is correct for static inline functions,
+        but not for extern inline functions.  We can't get this completely
+        correct because information about whether the function was declared
+        inline is not saved anywhere.  */
       if (DECL_DEFER_OUTPUT (decl))
        {
          if (DECL_INLINE (decl))
@@ -7636,9 +8296,6 @@ gen_subprogram_die (decl, context_die)
        }
       else if (DECL_INLINE (decl))
        add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined);
-      else if (declaration)
-       /* Block extern declaration in an inline function.  */
-       add_AT_flag (subr_die, DW_AT_declaration, 1);
       else
        abort ();
 
@@ -8070,6 +8727,9 @@ gen_compile_unit_die (main_input_filename)
   else if (strcmp (language_string, "GNU F77") == 0)
     add_AT_unsigned (comp_unit_die, DW_AT_language, DW_LANG_Fortran77);
 
+  else if (strcmp (language_string, "GNU Pascal") == 0)
+    add_AT_unsigned (comp_unit_die, DW_AT_language, DW_LANG_Pascal83);
+
   else if (flag_traditional)
     add_AT_unsigned (comp_unit_die, DW_AT_language, DW_LANG_C);
 
@@ -8121,7 +8781,7 @@ gen_inheritance_die (binfo, context_die)
     add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected);
 }
 
-/* Genearate a DIE for a class member.  */
+/* Generate a DIE for a class member.  */
 
 static void
 gen_member_die (type, context_die)
@@ -8214,7 +8874,7 @@ gen_struct_or_union_type_die (type, context_die)
          this type is expressed in terms of this type itself.  */
       TREE_ASM_WRITTEN (type) = 1;
       add_byte_size_attribute (type_die, type);
-      if (type_tag (type))
+      if (TYPE_STUB_DECL (type) != NULL_TREE)
        add_src_coords_attributes (type_die, TYPE_STUB_DECL (type));
 
       /* If the first reference to this type was as the return type of an
@@ -8304,7 +8964,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);
@@ -8327,6 +8987,13 @@ gen_type_die (type, context_die)
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
+      /* We must set TREE_ASM_WRITTEN in case this is a recursive type.  This
+        ensures that the gen_type_die recursion will terminate even if the
+        type is recursive.  Recursive types are possible in Ada.  */
+      /* ??? We could perhaps do this for all types before the switch
+        statement.  */
+      TREE_ASM_WRITTEN (type) = 1;
+
       /* For these types, all that is required is that we output a DIE (or a
          set of DIEs) to represent the "basis" type.  */
       gen_type_die (TREE_TYPE (type), context_die);
@@ -8442,12 +9109,13 @@ 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.  */
-  assert (type == type_main_variant (type));
-  assert (TREE_ASM_WRITTEN (type));
+  if (type != type_main_variant (type)
+      || !TREE_ASM_WRITTEN (type))
+    abort ();
 
   switch (TREE_CODE (type))
     {
@@ -8556,7 +9224,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)
@@ -8643,7 +9311,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)
@@ -8775,14 +9443,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;
@@ -8800,11 +9468,11 @@ dwarf2out_decl (decl)
       /* What we would really like to do here is to filter out all mere
          file-scope declarations of file-scope functions which are never
          referenced later within this translation unit (and keep all of ones
-         that *are* referenced later on) but we aren't clarvoiant, so we have 
+         that *are* referenced later on) but we aren't clairvoyant, so we have 
          no idea which functions will be referenced in the future (i.e. later 
          on within the current translation unit). So here we just ignore all
          file-scope function declarations which are not also definitions.  If 
-         and when the debugger needs to know something about these funcstion, 
+         and when the debugger needs to know something about these functions,
          it wil have to hunt around and find the DWARF information associated 
          with the definition of the function. Note that we can't just check
          `DECL_EXTERNAL' to find out which FUNCTION_DECL nodes represent
@@ -9045,7 +9713,7 @@ dwarf2out_line (filename, line)
 
 void
 dwarf2out_start_source_file (filename)
-     register char *filename;
+     register char *filename ATTRIBUTE_UNUSED;
 {
 }
 
@@ -9080,8 +9748,8 @@ dwarf2out_define (lineno, buffer)
 
 void
 dwarf2out_undef (lineno, buffer)
-     register unsigned lineno;
-     register char *buffer;
+     register unsigned lineno ATTRIBUTE_UNUSED;
+     register char *buffer ATTRIBUTE_UNUSED;
 {
 }
 
@@ -9113,9 +9781,10 @@ dwarf2out_init (asm_out_file, main_input_filename)
 
   /* Allocate the initial hunk of the decl_scope_table.  */
   decl_scope_table
-    = (tree *) xmalloc (DECL_SCOPE_TABLE_INCREMENT * sizeof (tree));
+    = (decl_scope_node *) xmalloc (DECL_SCOPE_TABLE_INCREMENT
+                                  * sizeof (decl_scope_node));
   bzero ((char *) decl_scope_table,
-        DECL_SCOPE_TABLE_INCREMENT * sizeof (tree));
+        DECL_SCOPE_TABLE_INCREMENT * sizeof (decl_scope_node));
   decl_scope_table_allocated = DECL_SCOPE_TABLE_INCREMENT;
   decl_scope_depth = 0;
 
@@ -9147,10 +9816,6 @@ 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);
-
-  /* Initialize the frame unwind information.  Eventually this should be
-     called from compile_file instead.  */
-  dwarf2out_frame_init ();
 }
 
 /* Output stuff that dwarf requires at the end of every file,
@@ -9207,10 +9872,6 @@ dwarf2out_finish ()
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BSS_END_LABEL, 0);
 #endif
 
-  /* Output the frame unwind information.  Eventually this should be called
-     from compile_file instead.  */
-  dwarf2out_frame_finish ();
-
   /* Output the source line correspondence table.  */
   if (line_info_table_in_use > 1 || separate_line_info_table_in_use)
     {
@@ -9222,7 +9883,8 @@ dwarf2out_finish ()
         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,
+                        stripattributes (TEXT_SECTION));
          add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
        }