OSDN Git Service

Fix mips64vr4100-elf build failure.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index f163535..40286de 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,19 +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"
-
 /* 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 (INCOMING_RETURN_ADDR_RTX)
-
-#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"
@@ -41,12 +37,35 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "insn-config.h"
 #include "reload.h"
 #include "output.h"
-#include "defaults.h"
 #include "expr.h"
 #include "except.h"
+#include "dwarf2.h"
+#include "dwarf2out.h"
+#include "toplev.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_UNWIND_INFO
+         || (flag_exceptions && ! exceptions_via_longjmp)
+#endif
+         );
+}
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 
 #ifndef __GNUC__
 #define inline
@@ -91,7 +110,6 @@ dw_cfi_node;
 
 typedef struct dw_fde_struct
 {
-  unsigned long dw_fde_offset;
   char *dw_fde_begin;
   char *dw_fde_current_label;
   char *dw_fde_end;
@@ -128,13 +146,6 @@ dw_fde_node;
 #define DWARF_ROUND(SIZE,BOUNDARY) \
   (((SIZE) + (BOUNDARY) - 1) & ~((BOUNDARY) - 1))
 
-/* Fixed size portion of the CIE (including the length field).  */
-#define DWARF_CIE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 5)
-
-/* The un-padded size of the CIE.  Initialized in calc_fde_sizes, used
-   in output_call_frame_info.  */
-static unsigned cie_size;
-
 /* Offsets recorded in opcodes are a multiple of this alignment factor.  */
 #ifdef STACK_GROWS_DOWNWARD
 #define DWARF_CIE_DATA_ALIGNMENT (-UNITS_PER_WORD)
@@ -142,13 +153,6 @@ static unsigned cie_size;
 #define DWARF_CIE_DATA_ALIGNMENT UNITS_PER_WORD
 #endif
 
-/* Fixed size portion of the FDE.  */
-#define DWARF_FDE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2 * PTR_SIZE)
-
-/* This location is used by calc_fde_sizes() to keep track
-   the offset of each FDE within the .debug_frame section.  */
-static unsigned long next_fde_offset;
-
 /* A pointer to the base of a table that contains frame description
    information for each routine.  */
 static dw_fde_ref fde_table;
@@ -189,7 +193,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));
-static 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 *));
@@ -197,18 +200,17 @@ static void lookup_cfa                    PROTO((unsigned long *, long *));
 static void reg_save                   PROTO((char *, unsigned, unsigned,
                                               long));
 static void initial_return_save                PROTO((rtx));
-static unsigned long size_of_cfi       PROTO((dw_cfi_ref));
-static unsigned long size_of_fde       PROTO((dw_fde_ref, unsigned long *));
-static void calc_fde_sizes             PROTO((void));
 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
@@ -218,20 +220,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)
@@ -246,15 +240,16 @@ static unsigned reg_number                PROTO((rtx));
    almost all svr4 assemblers, except for the sparc, where the section name
    must be enclosed in double quotes.  (See sparcv4.h).  */
 #ifndef SECTION_FORMAT
-#define SECTION_FORMAT "\t%s\t%s\n"
+#ifdef PUSHSECTION_FORMAT
+#define SECTION_FORMAT PUSHSECTION_FORMAT
+#else
+#define SECTION_FORMAT         "\t%s\t%s\n"
+#endif
 #endif
 
 #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"
@@ -262,16 +257,48 @@ static unsigned reg_number                PROTO((rtx));
 #ifndef FUNC_END_LABEL
 #define FUNC_END_LABEL         "LFE"
 #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, 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);             \
@@ -320,6 +347,13 @@ static unsigned reg_number         PROTO((rtx));
   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);            \
@@ -327,11 +361,6 @@ 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)
@@ -359,17 +388,98 @@ 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_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) \
+  do {                                                                       \
+    register int slen = strlen(P);                                            \
+    register char *p = (P);                                                  \
+    register int i;                                                          \
+    fprintf (FILE, "\t.ascii \"");                                           \
+    for (i = 0; i < slen; i++)                                               \
+      {                                                                              \
+         register int c = p[i];                                              \
+         if (c == '\"' || c == '\\')                                         \
+           putc ('\\', FILE);                                                \
+         if (c >= ' ' && c < 0177)                                           \
+           putc (c, FILE);                                                   \
+         else                                                                \
+           {                                                                 \
+             fprintf (FILE, "\\%o", c);                                      \
+           }                                                                 \
+      }                                                                              \
+    fprintf (FILE, "\\0\"");                                                 \
+  }                                                                          \
+  while (0)
+#endif
+
 /* The DWARF 2 CFA column which tracks the return address.  Normally this
    is the column for PC, or the first column after all of the hard
    registers.  */
@@ -387,6 +497,20 @@ 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
+#define INCOMING_FRAME_SP_OFFSET 0
+#endif
+
 /* Return a pointer to a copy of the section string name S with all
    attributes stripped off.  */
 
@@ -422,6 +546,108 @@ 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
+    {
+      --n_ranges;
+      t = build_int_2 (ranges[n_ranges].size, 0);
+      size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
+      for (; n_ranges--; )
+       {
+         if ((DWARF_FRAME_REGNUM (ranges[n_ranges].end)
+              - DWARF_FRAME_REGNUM (ranges[n_ranges].beg))
+             != ranges[n_ranges].end - ranges[n_ranges].beg)
+           abort ();
+         if (DWARF_FRAME_REGNUM (ranges[n_ranges].beg) >= size)
+           abort ();
+         size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
+         t2 = fold (build (LE_EXPR, integer_type_node, reg_tree,
+                           build_int_2 (DWARF_FRAME_REGNUM
+                                        (ranges[n_ranges].end), 0)));
+         t = fold (build (COND_EXPR, integer_type_node, t2,
+                          build_int_2 (ranges[n_ranges].size, 0), t));
+       }
+    }
+  return expand_expr (t, target, Pmode, 0);
+}
+
 /* Convert a DWARF call frame info. operation to its string name */
 
 static char *
@@ -466,9 +692,17 @@ dwarf_cfi_name (cfi_opc)
       return "DW_CFA_def_cfa_register";
     case DW_CFA_def_cfa_offset:
       return "DW_CFA_def_cfa_offset";
+
     /* SGI/MIPS specific */
     case DW_CFA_MIPS_advance_loc8:
       return "DW_CFA_MIPS_advance_loc8";
+
+    /* 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>";
     }
@@ -506,7 +740,7 @@ add_cfi (list_head, cfi)
 
 /* Generate a new label for the CFI info to refer to.  */
 
-static char *
+char *
 dwarf2out_cfi_label ()
 {
   static char label[20];
@@ -574,6 +808,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;
     }
 }
 
@@ -601,7 +837,7 @@ lookup_cfa (regp, offsetp)
 }
 
 /* The current rule for calculating the DWARF2 canonical frame address.  */
-static unsigned cfa_reg;
+static unsigned long cfa_reg;
 static long cfa_offset;
 
 /* The register used for saving registers to the stack, and its offset
@@ -609,6 +845,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.  */
@@ -676,7 +918,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
@@ -686,7 +930,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
@@ -698,8 +943,44 @@ reg_save (label, reg, sreg, offset)
   add_fde_cfi (label, cfi);
 }
 
-/* Entry point for saving a register.  REG is the GCC register number.
-   LABEL and OFFSET are passed to reg_save.  */
+/* Add the CFI for saving a register window.  LABEL is passed to reg_save.
+   This CFI tells the unwinder that it needs to restore the window registers
+   from the previous frame's window save area.
+   
+   ??? Perhaps we should note in the CIE where windows are saved (instead of
+   assuming 0(cfa)) and what registers are in the window.  */
+
+void
+dwarf2out_window_save (label)
+     register char * label;
+{
+  register dw_cfi_ref cfi = new_cfi ();
+  cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
+  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.  */
 
 void
 dwarf2out_reg_save (label, reg, offset)
@@ -710,6 +991,28 @@ dwarf2out_reg_save (label, reg, offset)
   reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset);
 }
 
+/* Entry point for saving the return address in the stack.
+   LABEL and OFFSET are passed to reg_save.  */
+
+void
+dwarf2out_return_save (label, offset)
+     register char * label;
+     register long offset;
+{
+  reg_save (label, DWARF_FRAME_RETURN_COLUMN, -1, offset);
+}
+
+/* Entry point for saving the return address in a register.
+   LABEL and SREG are passed to reg_save.  */
+
+void
+dwarf2out_return_reg (label, sreg)
+     register char * label;
+     register unsigned sreg;
+{
+  reg_save (label, DWARF_FRAME_RETURN_COLUMN, sreg, 0);
+}
+
 /* Record the initial position of the return address.  RTL is
    INCOMING_RETURN_ADDR_RTX.  */
 
@@ -732,26 +1035,138 @@ 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:
          abort ();
        }
       break;
+    case PLUS:
+      /* 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.  */
+      if (GET_CODE (XEXP (rtl, 1)) != CONST_INT)
+       abort ();
+      initial_return_save (XEXP (rtl, 0));
+      return;
     default:
       abort ();
     }
 
-  reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset);
+  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
@@ -773,19 +1188,32 @@ dwarf2out_frame_debug (insn)
   if (insn == NULL_RTX)
     {
       /* Set up state for generating call frame debug info.  */
+      lookup_cfa (&cfa_reg, &cfa_offset);
+      if (cfa_reg != DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
+       abort ();
       cfa_reg = STACK_POINTER_REGNUM;
-      cfa_offset = 0;
-      cfa_store_reg = STACK_POINTER_REGNUM;
-      cfa_store_offset = 0;
+      cfa_store_reg = cfa_reg;
+      cfa_store_offset = cfa_offset;
       cfa_temp_reg = -1;
       cfa_temp_value = 0;
       return;
     }
 
+  if (! RTX_FRAME_RELATED_P (insn))
+    {
+      dwarf2out_stack_adjust (insn);
+      return;
+    }
+
   label = dwarf2out_cfi_label ();
     
   insn = PATTERN (insn);
-  assert (GET_CODE (insn) == SET);
+  /* 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);
@@ -799,10 +1227,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 != REGNO (src))
+           abort ();
+         if (REGNO (dest) != STACK_POINTER_REGNUM
+             && !(frame_pointer_needed
+                  && REGNO (dest) == HARD_FRAME_POINTER_REGNUM))
+           abort ();
          cfa_reg = REGNO (dest);
          break;
 
@@ -817,31 +1247,76 @@ dwarf2out_frame_debug (insn)
                  offset = INTVAL (XEXP (src, 1));
                  break;
                case REG:
-                 assert (REGNO (XEXP (src, 1)) == cfa_temp_reg);
+                 if (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 != 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 != 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
+                 || 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;
 
@@ -851,10 +1326,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
+             || REGNO (XEXP (src, 0)) != cfa_temp_reg
+             || REGNO (dest) != cfa_temp_reg
+             || GET_CODE (XEXP (src, 1)) != CONST_INT)
+           abort ();
          cfa_temp_value |= INTVAL (XEXP (src, 1));
          break;
 
@@ -867,18 +1343,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;
@@ -893,7 +1371,8 @@ 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 != REGNO (XEXP (XEXP (dest, 0), 0)))
+           abort ();
          offset -= cfa_store_offset;
          break;
 
@@ -905,157 +1384,49 @@ dwarf2out_frame_debug (insn)
       break;
 
     default:
-      abort ();
-    }
-}
-
-/* Return the size of an unsigned LEB128 quantity.  */
-
-static inline unsigned long
-size_of_uleb128 (value)
-     register unsigned long value;
-{
-  register unsigned long size = 0;
-  register unsigned byte;
-
-  do
-    {
-      byte = (value & 0x7f);
-      value >>= 7;
-      size += 1;
-    }
-  while (value != 0);
-
-  return size;
-}
-
-/* Return the size of a signed LEB128 quantity.  */
-
-static inline unsigned long
-size_of_sleb128 (value)
-     register long value;
-{
-  register unsigned long size = 0;
-  register unsigned byte;
-
-  do
-    {
-      byte = (value & 0x7f);
-      value >>= 7;
-      size += 1;
-    }
-  while (!(((value == 0) && ((byte & 0x40) == 0))
-          || ((value == -1) && ((byte & 0x40) != 0))));
-
-  return size;
-}
-
-/* Return the size of a Call Frame Instruction.  */
-
-static unsigned long
-size_of_cfi (cfi)
-     dw_cfi_ref cfi;
-{
-  register unsigned long size;
-
-  /* Count the 1-byte opcode */
-  size = 1;
-  switch (cfi->dw_cfi_opc)
-    {
-    case DW_CFA_offset:
-      size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
-      break;
-    case DW_CFA_set_loc:
-      size += PTR_SIZE;
-      break;
-    case DW_CFA_advance_loc1:
-      size += 1;
-      break;
-    case DW_CFA_advance_loc2:
-      size += 2;
-      break;
-    case DW_CFA_advance_loc4:
-      size += 4;
-      break;
-#ifdef MIPS_DEBUGGING_INFO
-    case DW_CFA_MIPS_advance_loc8:
-      size += 8;
-      break;
-#endif
-    case DW_CFA_offset_extended:
-    case DW_CFA_def_cfa:
-      size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
-      size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
-      break;
-    case DW_CFA_restore_extended:
-    case DW_CFA_undefined:
-      size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
-      break;
-    case DW_CFA_same_value:
-    case DW_CFA_def_cfa_register:
-      size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
-      break;
-    case DW_CFA_register:
-      size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
-      size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num);
-      break;
-    case DW_CFA_def_cfa_offset:
-      size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
-      break;
-    default:
-      break;
+      abort ();
     }
-
-    return size;
 }
 
-/* Return the size of an FDE sans the length word.  */
+/* Return the size of an unsigned LEB128 quantity.  */
 
 static inline unsigned long
-size_of_fde (fde, npad)
-    dw_fde_ref fde;
-    unsigned long *npad;
+size_of_uleb128 (value)
+     register unsigned long value;
 {
-  register dw_cfi_ref cfi;
-  register unsigned long aligned_size;
-  register unsigned long size;
+  register unsigned long size = 0;
+  register unsigned byte;
 
-  size = DWARF_FDE_HEADER_SIZE;
-  for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
-    size += size_of_cfi(cfi);
+  do
+    {
+      byte = (value & 0x7f);
+      value >>= 7;
+      size += 1;
+    }
+  while (value != 0);
 
-  /* Round the size up to a word boundary.  */
-  aligned_size = DWARF_ROUND (size, PTR_SIZE);
-  *npad = aligned_size - size;
-  return aligned_size;
+  return size;
 }
 
-/* Calculate the size of the FDE table, and establish the offset
-   of each FDE in the .debug_frame section.  */
+/* Return the size of a signed LEB128 quantity.  */
 
-static void
-calc_fde_sizes ()
+static inline unsigned long
+size_of_sleb128 (value)
+     register long value;
 {
-  register unsigned long i;
-  register dw_fde_ref fde;
-  register unsigned long fde_size;
-  register dw_cfi_ref cfi;
-  unsigned long fde_pad;
-
-  cie_size = DWARF_CIE_HEADER_SIZE;
-  for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
-    cie_size += size_of_cfi (cfi);
-
-  /* Initialize the beginning FDE offset.  */
-  next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
+  register unsigned long size = 0;
+  register unsigned byte;
 
-  for (i = 0; i < fde_table_in_use; ++i)
+  do
     {
-      fde = &fde_table[i];
-      fde->dw_fde_offset = next_fde_offset;
-      fde_size = size_of_fde (fde, &fde_pad);
-      next_fde_offset += fde_size;
+      byte = (value & 0x7f);
+      value >>= 7;
+      size += 1;
     }
+  while (!(((value == 0) && ((byte & 0x40) == 0))
+          || ((value == -1) && ((byte & 0x40) != 0))));
+
+  return size;
 }
 
 /* Output an unsigned LEB128 quantity.  */
@@ -1081,8 +1452,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.  */
@@ -1112,8 +1483,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).  */
@@ -1128,8 +1499,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);
     }
@@ -1139,8 +1510,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);
@@ -1152,8 +1523,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);
@@ -1161,7 +1532,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));
 
@@ -1173,8 +1544,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,
@@ -1223,12 +1597,31 @@ output_cfi (cfi, fde)
          output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
           fputc ('\n', asm_out_file);
          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
+
 /* 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.  */
@@ -1237,29 +1630,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;
-
-  /* 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;
+  char l1[20], l2[20];
+#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
+  char ld[20];
+#endif
 
-  /* (re-)initialize the beginning FDE offset.  */
-  next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
+  /* Do we want to include a pointer to the exception table?  */
+  int eh_ptr = for_eh && exception_table_p ();
 
   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__");
     }
@@ -1267,45 +1665,92 @@ output_call_frame_info (for_eh)
     ASM_OUTPUT_SECTION (asm_out_file, FRAME_SECTION);
 
   /* Output the CIE. */
-  ASM_OUTPUT_DWARF_DATA (asm_out_file, next_fde_offset - DWARF_OFFSET_SIZE);
-  if (flag_verbose_asm)
+  ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
+  ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
+#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_DWARF_DATA4 (asm_out_file, DW_CIE_ID);
-  if (flag_verbose_asm)
+  ASM_OUTPUT_LABEL (asm_out_file, l1);
+
+  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);
-  ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s CIE Augmentation (none)", ASM_COMMENT_START);
+  if (eh_ptr)
+    {
+      /* 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_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);
@@ -1314,45 +1759,55 @@ output_call_frame_info (for_eh)
     output_cfi (cfi, NULL);
 
   /* Pad the CIE out to an address sized boundary.  */
-  for (i = next_fde_offset - cie_size; i; --i)
-    {
-      /* Pad out to a pointer size boundary */
-      ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CFA_nop);
-      if (flag_verbose_asm)
-       fprintf (asm_out_file, "\t%s CIE DW_CFA_nop (pad)", ASM_COMMENT_START);
-
-      fputc ('\n', asm_out_file);
-    }
+  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;
 
-      fde_size = size_of_fde (fde, &fde_pad);
-      ASM_OUTPUT_DWARF_DATA (asm_out_file, fde_size - DWARF_OFFSET_SIZE);
-      if (flag_verbose_asm)
+      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);
+#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);
+
       if (for_eh)
-       ASM_OUTPUT_DWARF_ADDR (asm_out_file, "__FRAME_BEGIN__");
+       ASM_OUTPUT_DWARF_DELTA (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);
@@ -1363,25 +1818,33 @@ output_call_frame_info (for_eh)
       for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
        output_cfi (cfi, fde);
 
-      /* Pad to a double word boundary.  */
-      for (j = 0; j < fde_pad; ++j)
-       {
-         ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CFA_nop);
-         if (flag_verbose_asm)
-           fprintf (asm_out_file, "\t%s CIE DW_CFA_nop (pad)",
-                    ASM_COMMENT_START);
-
-         fputc ('\n', asm_out_file);
-       }
+      /* 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
+#ifdef MIPS_DEBUGGING_INFO
+  /* Work around Irix 6 assembler bug whereby labels at the end of a section
+     get a value of 0.  Putting .align 0 after the label fixes it.  */
+  ASM_OUTPUT_ALIGN (asm_out_file, 0);
+#endif
+
+  /* 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
@@ -1418,6 +1881,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
@@ -1451,9 +1916,9 @@ dwarf2out_frame_init ()
   /* Generate the CFA instructions common to all FDE's.  Do it now for the
      sake of lookup_cfa.  */
 
-#ifdef INCOMING_RETURN_ADDR_RTX
-  /* On entry, the Canonical Frame Address is at SP+0.  */
-  dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, 0);
+#ifdef DWARF2_UNWIND_INFO
+  /* On entry, the Canonical Frame Address is at SP.  */
+  dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
   initial_return_save (INCOMING_RETURN_ADDR_RTX);
 #endif
 }
@@ -1461,14 +1926,17 @@ dwarf2out_frame_init ()
 void
 dwarf2out_frame_finish ()
 {
-  /* calculate sizes/offsets for FDEs.  */
-  calc_fde_sizes ();
-
   /* Output call frame information.  */
+#ifdef MIPS_DEBUGGING_INFO
   if (write_symbols == DWARF2_DEBUG)
     output_call_frame_info (0);
   if (flag_exceptions && ! exceptions_via_longjmp)
     output_call_frame_info (1);
+#else
+  if (write_symbols == DWARF2_DEBUG
+      || (flag_exceptions && ! exceptions_via_longjmp))
+    output_call_frame_info (1);  
+#endif
 }  
 
 #endif /* .debug_frame support */
@@ -1543,7 +2011,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.  */
 
@@ -1564,7 +2032,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
@@ -1757,7 +2225,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.  */
@@ -1770,18 +2238,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.  */
@@ -1873,7 +2352,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
@@ -1892,7 +2373,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));
@@ -1926,7 +2409,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,
@@ -1957,7 +2440,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));
@@ -1965,7 +2448,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));
@@ -1979,8 +2462,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));
@@ -1988,10 +2471,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));
@@ -2014,7 +2498,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));
@@ -2022,10 +2506,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));
@@ -2039,7 +2527,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 *));
@@ -2058,8 +2546,8 @@ static void gen_decl_die          PROTO((tree, dw_die_ref));
 static unsigned lookup_filename                PROTO((char *));
 
 /* Section names used to hold DWARF debugging information.  */
-#ifndef DEBUG_SECTION
-#define DEBUG_SECTION          ".debug_info"
+#ifndef DEBUG_INFO_SECTION
+#define DEBUG_INFO_SECTION     ".debug_info"
 #endif
 #ifndef ABBREV_SECTION
 #define ABBREV_SECTION         ".debug_abbrev"
@@ -2070,8 +2558,8 @@ static unsigned lookup_filename           PROTO((char *));
 #ifndef DW_MACINFO_SECTION
 #define DW_MACINFO_SECTION     ".debug_macinfo"
 #endif
-#ifndef LINE_SECTION
-#define LINE_SECTION           ".debug_line"
+#ifndef DEBUG_LINE_SECTION
+#define DEBUG_LINE_SECTION     ".debug_line"
 #endif
 #ifndef LOC_SECTION
 #define LOC_SECTION            ".debug_loc"
@@ -2083,7 +2571,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
@@ -2134,33 +2622,6 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 #define SEPARATE_LINE_CODE_LABEL       "LSM"
 #endif
 
-/* 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
-   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) \
-  do {                                                                       \
-    register int slen = strlen(P);                                            \
-    register char *p = (P);                                                  \
-    register int i;                                                          \
-    fprintf (FILE, "\t.ascii \"");                                           \
-    for (i = 0; i < slen; i++)                                               \
-      {                                                                              \
-         register int c = p[i];                                              \
-         if (c == '\"' || c == '\\')                                         \
-           putc ('\\', FILE);                                                \
-         if (c >= ' ' && c < 0177)                                           \
-           putc (c, FILE);                                                   \
-         else                                                                \
-           {                                                                 \
-             fprintf (FILE, "\\%o", c);                                      \
-           }                                                                 \
-      }                                                                              \
-    fprintf (FILE, "\\0\"");                                                 \
-  }                                                                          \
-  while (0)
-#endif
-
 /* Convert a reference to the assembler name of a C-level name.  This
    macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
    a string rather than writing to a file.  */
@@ -2321,7 +2782,7 @@ addr_to_string (x)
   return xstrdup (buf);
 }
 
-/* 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)
@@ -3015,6 +3476,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;
@@ -3041,6 +3503,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
@@ -3591,7 +4054,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;
 
@@ -3681,7 +4145,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)
@@ -3759,7 +4222,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
@@ -3771,11 +4234,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)
     {
@@ -3791,13 +4254,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;
@@ -3809,7 +4272,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>");
@@ -3826,6 +4289,8 @@ print_die (die, outfile)
          else
            fprintf (outfile, "<null>");
          break;
+       default:
+         break;
        }
 
       fprintf (outfile, "\n");
@@ -3857,7 +4322,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");
     }
 
@@ -3962,8 +4427,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));
@@ -4206,10 +4671,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
@@ -4244,7 +4709,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)
@@ -4439,7 +4904,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 ()
@@ -4523,7 +4988,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);
@@ -4543,12 +5008,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));
 
@@ -4556,7 +5021,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
@@ -4568,7 +5033,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));
 
@@ -4730,8 +5195,8 @@ output_die (die)
   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);
@@ -4761,7 +5226,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));
 
@@ -4771,7 +5236,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));
 
@@ -4813,7 +5278,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));
 
@@ -4822,7 +5287,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);
          
@@ -4832,7 +5297,7 @@ output_die (die)
        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)
+         if (flag_debug_asm)
            fprintf (asm_out_file, "\t%s %s",
                     ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
 
@@ -4841,7 +5306,7 @@ output_die (die)
            {
              ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
                                      a->dw_attr_val.v.val_float.array[i]);
-             if (flag_verbose_asm)
+             if (flag_debug_asm)
                fprintf (asm_out_file, "\t%s fp constant word %d",
                         ASM_COMMENT_START, i);
 
@@ -4865,9 +5330,13 @@ output_die (die)
          break;
 
        case dw_val_class_fde_ref:
-         ref_offset = fde_table[a->dw_attr_val.v.val_fde_index].dw_fde_offset;
-         fprintf (asm_out_file, "\t%s\t%s+0x%x", UNALIGNED_OFFSET_ASM_OP,
-                  stripattributes (FRAME_SECTION), ref_offset);
+         {
+           char l1[20];
+           ASM_GENERATE_INTERNAL_LABEL
+             (l1, FDE_AFTER_SIZE_LABEL, a->dw_attr_val.v.val_fde_index * 2);
+           ASM_OUTPUT_DWARF_OFFSET (asm_out_file, l1);
+           fprintf (asm_out_file, " - %d", DWARF_OFFSET_SIZE);
+         }
          break;
 
        case dw_val_class_lbl_id:
@@ -4881,7 +5350,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,
+                             strlen (a->dw_attr_val.v.val_str) + 1);
          break;
 
        default:
@@ -4892,7 +5366,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));
 
@@ -4907,8 +5381,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);
@@ -4922,24 +5396,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);
@@ -4994,25 +5468,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_SECTION));
-  if (flag_verbose_asm)
+  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (DEBUG_INFO_SECTION));
+  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);
@@ -5021,14 +5495,20 @@ 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, strlen (pub->name) + 1);
+       }
 
       fputc ('\n', asm_out_file);
     }
@@ -5069,29 +5549,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_SECTION));
-  if (flag_verbose_asm)
+  ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (DEBUG_INFO_SECTION));
+  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);
 
@@ -5100,18 +5580,18 @@ 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)
+  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)
+  if (flag_debug_asm)
     fprintf (asm_out_file, "%s Length", ASM_COMMENT_START);
 
   fputc ('\n', asm_out_file);
@@ -5130,7 +5610,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);
@@ -5141,7 +5621,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);
@@ -5176,47 +5656,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);
@@ -5236,27 +5716,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],
+                           strlen (file_table[ft_index]) + 1);
+       }
 
       fputc ('\n', asm_out_file);
 
@@ -5279,7 +5767,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);
@@ -5314,7 +5802,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);
 
@@ -5326,7 +5814,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);
@@ -5346,12 +5834,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);
@@ -5369,9 +5857,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);
        }
@@ -5380,8 +5868,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);
@@ -5396,7 +5884,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);
 
@@ -5407,7 +5895,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);
@@ -5420,7 +5908,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);
@@ -5448,7 +5936,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);
 
@@ -5466,7 +5954,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);
 
@@ -5478,7 +5966,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);
@@ -5498,12 +5986,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);
@@ -5520,17 +6008,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);
@@ -5555,7 +6043,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);
 
@@ -5567,7 +6055,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);
@@ -5581,7 +6069,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);
 
@@ -5695,7 +6183,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;
@@ -5860,7 +6348,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 ();
        }
     }
 
@@ -5900,7 +6389,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);
@@ -5925,7 +6414,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);
@@ -6036,6 +6525,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
@@ -6067,6 +6580,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 ();
     }
@@ -6263,38 +6780,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
@@ -6431,9 +6934,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:
@@ -6541,7 +7042,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.  */
@@ -6569,8 +7070,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:
@@ -6585,6 +7097,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;
 
@@ -6671,10 +7184,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);
        }
 
@@ -6683,6 +7208,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;
@@ -6700,7 +7226,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;
 
@@ -6751,14 +7279,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
     }
@@ -6832,8 +7369,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
@@ -6875,8 +7414,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)));
 }
@@ -6976,19 +7517,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)
@@ -6997,7 +7574,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.  */
@@ -7008,6 +7585,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
@@ -7018,17 +7599,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 ();
        }
     }
 
@@ -7039,7 +7641,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;
 }
 
@@ -7131,6 +7734,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;
@@ -7148,8 +7752,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().  */
 
@@ -7222,6 +7827,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;
@@ -7243,6 +7849,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.  */
 
@@ -7278,7 +7885,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 ();
     }
 }
 
@@ -7292,7 +7900,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);
 }
 
@@ -7306,7 +7915,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);
 }
 
@@ -7320,7 +7930,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);
 }
 
@@ -7357,7 +7968,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
@@ -7446,8 +8057,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
@@ -7529,7 +8139,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;
@@ -7545,12 +8154,24 @@ 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)
+       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
@@ -7624,11 +8245,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))
@@ -7639,9 +8264,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 ();
 
@@ -8073,6 +8695,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);
 
@@ -8124,7 +8749,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)
@@ -8217,7 +8842,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
@@ -8307,7 +8932,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);
@@ -8330,6 +8955,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);
@@ -8445,12 +9077,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))
     {
@@ -8646,7 +9279,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)
@@ -8778,7 +9411,7 @@ 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!) */
@@ -8803,11 +9436,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
@@ -9048,7 +9681,7 @@ dwarf2out_line (filename, line)
 
 void
 dwarf2out_start_source_file (filename)
-     register char *filename;
+     register char *filename ATTRIBUTE_UNUSED;
 {
 }
 
@@ -9083,8 +9716,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;
 {
 }
 
@@ -9116,9 +9749,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;
 
@@ -9150,10 +9784,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,
@@ -9210,15 +9840,11 @@ 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)
     {
       fputc ('\n', asm_out_file);
-      ASM_OUTPUT_SECTION (asm_out_file, LINE_SECTION);
+      ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
       output_line_info ();
 
       /* We can only use the low/high_pc attributes if all of the code
@@ -9229,7 +9855,7 @@ dwarf2out_finish ()
          add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
        }
 
-      add_AT_section_offset (comp_unit_die, DW_AT_stmt_list, LINE_SECTION);
+      add_AT_section_offset (comp_unit_die, DW_AT_stmt_list, DEBUG_LINE_SECTION);
     }
 
   /* Output the abbreviation table.  */
@@ -9244,7 +9870,7 @@ dwarf2out_finish ()
 
   /* Output debugging information.  */
   fputc ('\n', asm_out_file);
-  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_SECTION);
+  ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION);
   output_compilation_unit_header ();
   output_die (comp_unit_die);