OSDN Git Service

2003-07-15 J"orn Rennecke <joern.rennecke@superh.com>
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index 47edc43..94269b1 100644 (file)
@@ -1,6 +1,6 @@
-/* Output Dwarf2 format symbol table information from the GNU C compiler.
-   Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+/* Output Dwarf2 format symbol table information from GCC.
+   Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+   2003 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).
@@ -36,8 +36,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "flags.h"
+#include "real.h"
 #include "rtl.h"
 #include "hard-reg-set.h"
 #include "regs.h"
@@ -60,10 +63,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "debug.h"
 #include "target.h"
 #include "langhooks.h"
-#include "hashtable.h"
+#include "hashtab.h"
 
 #ifdef DWARF2_DEBUGGING_INFO
-static void dwarf2out_source_line      PARAMS ((unsigned int, const char *));
+static void dwarf2out_source_line (unsigned int, const char *);
 #endif
 
 /* DWARF2 Abbreviation Glossary:
@@ -88,7 +91,7 @@ static void dwarf2out_source_line     PARAMS ((unsigned int, const char *));
    translation unit.  */
 
 int
-dwarf2out_do_frame ()
+dwarf2out_do_frame (void)
 {
   return (write_symbols == DWARF2_DEBUG
          || write_symbols == VMS_AND_DWARF2_DEBUG
@@ -102,13 +105,6 @@ dwarf2out_do_frame ()
          );
 }
 
-/* The number of the current function definition for which debugging
-   information is being generated.  These numbers range from 1 up to the
-   maximum number of function definitions contained within the current
-   compilation unit.  These numbers are used to create unique label id's
-   unique to each function definition.  */
-unsigned current_funcdef_number = 0;
-
 /* The size of the target's pointer type.  */
 #ifndef PTR_SIZE
 #define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
@@ -119,21 +115,52 @@ unsigned current_funcdef_number = 0;
    guards.  */
 
 void
-default_eh_frame_section ()
+default_eh_frame_section (void)
 {
 #ifdef EH_FRAME_SECTION_NAME
+#ifdef HAVE_LD_RO_RW_SECTION_MIXING
+  int fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
+  int per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
+  int lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
+  int flags;
+
+  flags = (! flag_pic
+          || ((fde_encoding & 0x70) != DW_EH_PE_absptr
+              && (fde_encoding & 0x70) != DW_EH_PE_aligned
+              && (per_encoding & 0x70) != DW_EH_PE_absptr
+              && (per_encoding & 0x70) != DW_EH_PE_aligned
+              && (lsda_encoding & 0x70) != DW_EH_PE_absptr
+              && (lsda_encoding & 0x70) != DW_EH_PE_aligned))
+         ? 0 : SECTION_WRITE;
+  named_section_flags (EH_FRAME_SECTION_NAME, flags);
+#else
   named_section_flags (EH_FRAME_SECTION_NAME, SECTION_WRITE);
+#endif
 #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));
+  (*targetm.asm_out.globalize_label) (asm_out_file, IDENTIFIER_POINTER (label));
   ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
 #endif
 }
 
-#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+/* Array of RTXes referenced by the debugging information, which therefore
+   must be kept around forever.  */
+static GTY(()) varray_type used_rtx_varray;
+
+/* A pointer to the base of a list of incomplete types which might be
+   completed at some later time.  incomplete_types_list needs to be a VARRAY
+   because we want to tell the garbage collector about it.  */
+static GTY(()) varray_type incomplete_types;
+
+/* 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 GTY(()) varray_type decl_scope_table;
 
 /* How to start an assembler comment.  */
 #ifndef ASM_COMMENT_START
@@ -149,21 +176,31 @@ typedef union  dw_cfi_oprnd_struct *dw_cfi_oprnd_ref;
    and address fields are provided as possible operands;
    their use is selected by the opcode field.  */
 
-typedef union dw_cfi_oprnd_struct
+enum dw_cfi_oprnd_type {
+  dw_cfi_oprnd_unused,
+  dw_cfi_oprnd_reg_num,
+  dw_cfi_oprnd_offset,
+  dw_cfi_oprnd_addr,
+  dw_cfi_oprnd_loc
+};
+
+typedef union dw_cfi_oprnd_struct GTY(())
 {
-  unsigned long dw_cfi_reg_num;
-  long int dw_cfi_offset;
-  const char *dw_cfi_addr;
-  struct dw_loc_descr_struct *dw_cfi_loc;
+  unsigned long GTY ((tag ("dw_cfi_oprnd_reg_num"))) dw_cfi_reg_num;
+  long int GTY ((tag ("dw_cfi_oprnd_offset"))) dw_cfi_offset;
+  const char * GTY ((tag ("dw_cfi_oprnd_addr"))) dw_cfi_addr;
+  struct dw_loc_descr_struct * GTY ((tag ("dw_cfi_oprnd_loc"))) dw_cfi_loc;
 }
 dw_cfi_oprnd;
 
-typedef struct dw_cfi_struct
+typedef struct dw_cfi_struct GTY(())
 {
   dw_cfi_ref dw_cfi_next;
   enum dwarf_call_frame_info dw_cfi_opc;
-  dw_cfi_oprnd dw_cfi_oprnd1;
-  dw_cfi_oprnd dw_cfi_oprnd2;
+  dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd1_desc (%1.dw_cfi_opc)")))
+    dw_cfi_oprnd1;
+  dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd2_desc (%1.dw_cfi_opc)")))
+    dw_cfi_oprnd2;
 }
 dw_cfi_node;
 
@@ -172,7 +209,7 @@ dw_cfi_node;
    It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET.
    Instead of passing around REG and OFFSET, we pass a copy
    of this structure.  */
-typedef struct cfa_loc
+typedef struct cfa_loc GTY(())
 {
   unsigned long reg;
   long offset;
@@ -186,13 +223,14 @@ typedef struct cfa_loc
    CIE obviates the need to keep track of multiple CIE's
    in the DWARF generation routines below.  */
 
-typedef struct dw_fde_struct
+typedef struct dw_fde_struct GTY(())
 {
   const char *dw_fde_begin;
   const char *dw_fde_current_label;
   const char *dw_fde_end;
   dw_cfi_ref dw_fde_cfi;
   unsigned funcdef_number;
+  unsigned all_throwers_are_sibcalls : 1;
   unsigned nothrow : 1;
   unsigned uses_eh_lsda : 1;
 }
@@ -219,6 +257,18 @@ dw_fde_node;
 #define DWARF_OFFSET_SIZE 4
 #endif
 
+/* According to the (draft) DWARF 3 specification, the initial length
+   should either be 4 or 12 bytes.  When it's 12 bytes, the first 4
+   bytes are 0xffffffff, followed by the length stored in the next 8
+   bytes.
+
+   However, the SGI/MIPS ABI uses an initial length which is equal to
+   DWARF_OFFSET_SIZE.  It is defined (elsewhere) accordingly.  */
+
+#ifndef DWARF_INITIAL_LENGTH_SIZE
+#define DWARF_INITIAL_LENGTH_SIZE (DWARF_OFFSET_SIZE == 4 ? 4 : 12)
+#endif
+
 #define DWARF_VERSION 2
 
 /* Round SIZE up to the nearest BOUNDARY.  */
@@ -236,67 +286,71 @@ dw_fde_node;
 
 /* A pointer to the base of a table that contains frame description
    information for each routine.  */
-static dw_fde_ref fde_table;
+static GTY((length ("fde_table_allocated"))) dw_fde_ref fde_table;
 
 /* Number of elements currently allocated for fde_table.  */
-static unsigned fde_table_allocated;
+static GTY(()) unsigned fde_table_allocated;
 
 /* Number of elements in fde_table currently in use.  */
-static unsigned fde_table_in_use;
+static GTY(()) unsigned fde_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
    fde_table.  */
 #define FDE_TABLE_INCREMENT 256
 
 /* A list of call frame insns for the CIE.  */
-static dw_cfi_ref cie_cfi_head;
+static GTY(()) dw_cfi_ref cie_cfi_head;
 
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 /* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram
    attribute that accelerates the lookup of the FDE associated
    with the subprogram.  This variable holds the table index of the FDE
    associated with the current function (body) definition.  */
 static unsigned current_funcdef_fde;
+#endif
 
-struct ht *debug_str_hash;
-
-struct indirect_string_node
+struct indirect_string_node GTY(())
 {
-  struct ht_identifier id;
+  const char *str;
   unsigned int refcount;
   unsigned int form;
   char *label;
 };
 
+static GTY ((param_is (struct indirect_string_node))) htab_t debug_str_hash;
+
+static GTY(()) int dw2_string_counter;
+static GTY(()) unsigned long dwarf2out_cfi_label_num;
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+
 /* Forward declarations for functions defined in this file.  */
 
-static char *stripattributes           PARAMS ((const char *));
-static const char *dwarf_cfi_name      PARAMS ((unsigned));
-static dw_cfi_ref new_cfi              PARAMS ((void));
-static void add_cfi                    PARAMS ((dw_cfi_ref *, dw_cfi_ref));
-static void add_fde_cfi                        PARAMS ((const char *, dw_cfi_ref));
-static void lookup_cfa_1               PARAMS ((dw_cfi_ref,
-                                                dw_cfa_location *));
-static void lookup_cfa                 PARAMS ((dw_cfa_location *));
-static void reg_save                   PARAMS ((const char *, unsigned,
-                                                unsigned, long));
-static void initial_return_save                PARAMS ((rtx));
-static long stack_adjust_offset                PARAMS ((rtx));
-static void output_cfi                 PARAMS ((dw_cfi_ref, dw_fde_ref, int));
-static void output_call_frame_info     PARAMS ((int));
-static void dwarf2out_stack_adjust     PARAMS ((rtx));
-static void queue_reg_save             PARAMS ((const char *, rtx, long));
-static void flush_queued_reg_saves     PARAMS ((void));
-static bool clobbers_queued_reg_save   PARAMS ((rtx));
-static void dwarf2out_frame_debug_expr PARAMS ((rtx, const char *));
+static char *stripattributes (const char *);
+static const char *dwarf_cfi_name (unsigned);
+static dw_cfi_ref new_cfi (void);
+static void add_cfi (dw_cfi_ref *, dw_cfi_ref);
+static void add_fde_cfi (const char *, dw_cfi_ref);
+static void lookup_cfa_1 (dw_cfi_ref, dw_cfa_location *);
+static void lookup_cfa (dw_cfa_location *);
+static void reg_save (const char *, unsigned, unsigned, long);
+static void initial_return_save (rtx);
+static long stack_adjust_offset (rtx);
+static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
+static void output_call_frame_info (int);
+static void dwarf2out_stack_adjust (rtx);
+static void queue_reg_save (const char *, rtx, long);
+static void flush_queued_reg_saves (void);
+static bool clobbers_queued_reg_save (rtx);
+static void dwarf2out_frame_debug_expr (rtx, const char *);
 
 /* Support for complex CFA locations.  */
-static void output_cfa_loc             PARAMS ((dw_cfi_ref));
-static void get_cfa_from_loc_descr     PARAMS ((dw_cfa_location *,
-                                               struct dw_loc_descr_struct *));
+static void output_cfa_loc (dw_cfi_ref);
+static void get_cfa_from_loc_descr (dw_cfa_location *,
+                                   struct dw_loc_descr_struct *);
 static struct dw_loc_descr_struct *build_cfa_loc
-                                       PARAMS ((dw_cfa_location *));
-static void def_cfa_1                  PARAMS ((const char *,
-                                                dw_cfa_location *));
+ (dw_cfa_location *);
+static void def_cfa_1 (const char *, dw_cfa_location *);
 
 /* How to start an assembler comment.  */
 #ifndef ASM_COMMENT_START
@@ -307,11 +361,6 @@ static void def_cfa_1                      PARAMS ((const char *,
 #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)
 
-/* Pseudo-op for defining a new section.  */
-#ifndef SECTION_ASM_OP
-#define SECTION_ASM_OP "\t.section\t"
-#endif
-
 #ifndef DEBUG_FRAME_SECTION
 #define DEBUG_FRAME_SECTION    ".debug_frame"
 #endif
@@ -327,45 +376,23 @@ static void def_cfa_1                     PARAMS ((const char *,
 #define FRAME_BEGIN_LABEL      "Lframe"
 #define CIE_AFTER_SIZE_LABEL   "LSCIE"
 #define CIE_END_LABEL          "LECIE"
-#define CIE_LENGTH_LABEL       "LLCIE"
 #define FDE_LABEL              "LSFDE"
 #define FDE_AFTER_SIZE_LABEL   "LASFDE"
 #define FDE_END_LABEL          "LEFDE"
-#define FDE_LENGTH_LABEL       "LLFDE"
 #define LINE_NUMBER_BEGIN_LABEL        "LSLT"
 #define LINE_NUMBER_END_LABEL  "LELT"
 #define LN_PROLOG_AS_LABEL     "LASLTP"
 #define LN_PROLOG_END_LABEL    "LELTP"
 #define DIE_LABEL_PREFIX       "DW"
 
-/* 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 unnecessary.  */
-
-#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, "%s", SET_ASM_OP);                                        \
-      assemble_name (FILE, SY);                                                \
-      fputc (',', FILE);                                               \
-      assemble_name (FILE, HI);                                                \
-      fputc ('-', FILE);                                               \
-      assemble_name (FILE, LO);                                                \
-    }                                                                  \
-  while (0)
-#endif
-#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.  */
 #ifndef DWARF_FRAME_RETURN_COLUMN
 #ifdef PC_REGNUM
-#define DWARF_FRAME_RETURN_COLUMN      DWARF_FRAME_REGNUM (PC_REGNUM)
+#define DWARF_FRAME_RETURN_COLUMN      DWARF_FRAME_REGNUM (PC_REGNUM)
 #else
-#define DWARF_FRAME_RETURN_COLUMN      DWARF_FRAME_REGISTERS
+#define DWARF_FRAME_RETURN_COLUMN      DWARF_FRAME_REGISTERS
 #endif
 #endif
 
@@ -384,17 +411,16 @@ static void def_cfa_1                     PARAMS ((const char *,
 /* Hook used by __throw.  */
 
 rtx
-expand_builtin_dwarf_fp_regnum ()
+expand_builtin_dwarf_sp_column (void)
 {
-  return GEN_INT (DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM));
+  return GEN_INT (DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM));
 }
 
 /* Return a pointer to a copy of the section string name S with all
    attributes stripped off, and an asterisk prepended (for assemble_name).  */
 
 static inline char *
-stripattributes (s)
-     const char *s;
+stripattributes (const char *s)
 {
   char *stripped = xmalloc (strlen (s) + 2);
   char *p = stripped;
@@ -411,22 +437,40 @@ stripattributes (s)
 /* Generate code to initialize the register size table.  */
 
 void
-expand_builtin_init_dwarf_reg_sizes (address)
-     tree address;
+expand_builtin_init_dwarf_reg_sizes (tree address)
 {
   int i;
   enum machine_mode mode = TYPE_MODE (char_type_node);
   rtx addr = expand_expr (address, NULL_RTX, VOIDmode, 0);
   rtx mem = gen_rtx_MEM (BLKmode, addr);
+  bool wrote_return_column = false;
 
-  for (i = 0; i < DWARF_FRAME_REGISTERS; i++)
-    {
-      HOST_WIDE_INT offset = DWARF_FRAME_REGNUM (i) * GET_MODE_SIZE (mode);
-      HOST_WIDE_INT size = GET_MODE_SIZE (reg_raw_mode[i]);
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (DWARF_FRAME_REGNUM (i) < DWARF_FRAME_REGISTERS)
+      {
+       HOST_WIDE_INT offset = DWARF_FRAME_REGNUM (i) * GET_MODE_SIZE (mode);
+       enum machine_mode save_mode = reg_raw_mode[i];
+       HOST_WIDE_INT size;
 
-      if (offset < 0)
-       continue;
+       if (HARD_REGNO_CALL_PART_CLOBBERED (i, save_mode))
+         save_mode = choose_hard_reg_mode (i, 1, true);
+       if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN)
+         {
+           if (save_mode == VOIDmode)
+             continue;
+           wrote_return_column = true;
+         }
+       size = GET_MODE_SIZE (save_mode);
+       if (offset < 0)
+         continue;
 
+       emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
+      }
+  if (! wrote_return_column)
+    {
+      enum machine_mode save_mode = Pmode;
+      HOST_WIDE_INT offset = DWARF_FRAME_RETURN_COLUMN * GET_MODE_SIZE (mode);
+      HOST_WIDE_INT size = GET_MODE_SIZE (save_mode);
       emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
     }
 }
@@ -434,8 +478,7 @@ expand_builtin_init_dwarf_reg_sizes (address)
 /* Convert a DWARF call frame info. operation to its string name */
 
 static const char *
-dwarf_cfi_name (cfi_opc)
-     unsigned cfi_opc;
+dwarf_cfi_name (unsigned int cfi_opc)
 {
   switch (cfi_opc)
     {
@@ -508,9 +551,9 @@ dwarf_cfi_name (cfi_opc)
 /* Return a pointer to a newly allocated Call Frame Instruction.  */
 
 static inline dw_cfi_ref
-new_cfi ()
+new_cfi (void)
 {
-  dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node));
+  dw_cfi_ref cfi = (dw_cfi_ref) ggc_alloc (sizeof (dw_cfi_node));
 
   cfi->dw_cfi_next = NULL;
   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
@@ -522,9 +565,7 @@ new_cfi ()
 /* Add a Call Frame Instruction to list of instructions.  */
 
 static inline void
-add_cfi (list_head, cfi)
-     dw_cfi_ref *list_head;
-     dw_cfi_ref cfi;
+add_cfi (dw_cfi_ref *list_head, dw_cfi_ref cfi)
 {
   dw_cfi_ref *p;
 
@@ -538,12 +579,11 @@ add_cfi (list_head, cfi)
 /* Generate a new label for the CFI info to refer to.  */
 
 char *
-dwarf2out_cfi_label ()
+dwarf2out_cfi_label (void)
 {
   static char label[20];
-  static unsigned long label_num = 0;
 
-  ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++);
+  ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", dwarf2out_cfi_label_num++);
   ASM_OUTPUT_LABEL (asm_out_file, label);
   return label;
 }
@@ -552,9 +592,7 @@ dwarf2out_cfi_label ()
    or to the CIE if LABEL is NULL.  */
 
 static void
-add_fde_cfi (label, cfi)
-     const char *label;
-     dw_cfi_ref cfi;
+add_fde_cfi (const char *label, dw_cfi_ref cfi)
 {
   if (label)
     {
@@ -587,9 +625,7 @@ add_fde_cfi (label, cfi)
 /* Subroutine of lookup_cfa.  */
 
 static inline void
-lookup_cfa_1 (cfi, loc)
-     dw_cfi_ref cfi;
-     dw_cfa_location *loc;
+lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc)
 {
   switch (cfi->dw_cfi_opc)
     {
@@ -614,8 +650,7 @@ lookup_cfa_1 (cfi, loc)
 /* Find the previous value for the CFA.  */
 
 static void
-lookup_cfa (loc)
-     dw_cfa_location *loc;
+lookup_cfa (dw_cfa_location *loc)
 {
   dw_cfi_ref cfi;
 
@@ -653,10 +688,7 @@ static long old_args_size;
    calculated from REG+OFFSET.  */
 
 void
-dwarf2out_def_cfa (label, reg, offset)
-     const char *label;
-     unsigned reg;
-     long offset;
+dwarf2out_def_cfa (const char *label, unsigned int reg, long int offset)
 {
   dw_cfa_location loc;
   loc.indirect = 0;
@@ -670,9 +702,7 @@ dwarf2out_def_cfa (label, reg, offset)
    the dw_cfa_location structure.  */
 
 static void
-def_cfa_1 (label, loc_p)
-     const char *label;
-     dw_cfa_location *loc_p;
+def_cfa_1 (const char *label, dw_cfa_location *loc_p)
 {
   dw_cfi_ref cfi;
   dw_cfa_location old_cfa, loc;
@@ -745,11 +775,7 @@ def_cfa_1 (label, loc_p)
    otherwise it is saved in SREG.  */
 
 static void
-reg_save (label, reg, sreg, offset)
-     const char *label;
-     unsigned reg;
-     unsigned sreg;
-     long offset;
+reg_save (const char *label, unsigned int reg, unsigned int sreg, long int offset)
 {
   dw_cfi_ref cfi = new_cfi ();
 
@@ -804,8 +830,7 @@ reg_save (label, reg, sreg, offset)
    assuming 0(cfa)) and what registers are in the window.  */
 
 void
-dwarf2out_window_save (label)
-     const char *label;
+dwarf2out_window_save (const char *label)
 {
   dw_cfi_ref cfi = new_cfi ();
 
@@ -817,9 +842,7 @@ dwarf2out_window_save (label)
    pushed onto the stack.  */
 
 void
-dwarf2out_args_size (label, size)
-     const char *label;
-     long size;
+dwarf2out_args_size (const char *label, long int size)
 {
   dw_cfi_ref cfi;
 
@@ -838,10 +861,7 @@ dwarf2out_args_size (label, size)
    number.  LABEL and OFFSET are passed to reg_save.  */
 
 void
-dwarf2out_reg_save (label, reg, offset)
-     const char *label;
-     unsigned reg;
-     long offset;
+dwarf2out_reg_save (const char *label, unsigned int reg, long int offset)
 {
   reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset);
 }
@@ -850,9 +870,7 @@ dwarf2out_reg_save (label, reg, offset)
    LABEL and OFFSET are passed to reg_save.  */
 
 void
-dwarf2out_return_save (label, offset)
-     const char *label;
-     long offset;
+dwarf2out_return_save (const char *label, long int offset)
 {
   reg_save (label, DWARF_FRAME_RETURN_COLUMN, -1, offset);
 }
@@ -861,9 +879,7 @@ dwarf2out_return_save (label, offset)
    LABEL and SREG are passed to reg_save.  */
 
 void
-dwarf2out_return_reg (label, sreg)
-     const char *label;
-     unsigned sreg;
+dwarf2out_return_reg (const char *label, unsigned int sreg)
 {
   reg_save (label, DWARF_FRAME_RETURN_COLUMN, sreg, 0);
 }
@@ -872,8 +888,7 @@ dwarf2out_return_reg (label, sreg)
    INCOMING_RETURN_ADDR_RTX.  */
 
 static void
-initial_return_save (rtl)
-     rtx rtl;
+initial_return_save (rtx rtl)
 {
   unsigned int reg = (unsigned int) -1;
   HOST_WIDE_INT offset = 0;
@@ -934,8 +949,7 @@ initial_return_save (rtl)
    contains.  */
 
 static long
-stack_adjust_offset (pattern)
-     rtx pattern;
+stack_adjust_offset (rtx pattern)
 {
   rtx src = SET_SRC (pattern);
   rtx dest = SET_DEST (pattern);
@@ -1010,8 +1024,7 @@ stack_adjust_offset (pattern)
    much extra space it needs to pop off the stack.  */
 
 static void
-dwarf2out_stack_adjust (insn)
-     rtx insn;
+dwarf2out_stack_adjust (rtx insn)
 {
   HOST_WIDE_INT offset;
   const char *label;
@@ -1081,27 +1094,28 @@ dwarf2out_stack_adjust (insn)
   dwarf2out_args_size (label, args_size);
 }
 
+#endif
+
 /* We delay emitting a register save until either (a) we reach the end
    of the prologue or (b) the register is clobbered.  This clusters
    register saves so that there are fewer pc advances.  */
 
-struct queued_reg_save
+struct queued_reg_save GTY(())
 {
   struct queued_reg_save *next;
   rtx reg;
   long cfa_offset;
 };
 
-static struct queued_reg_save *queued_reg_saves;
+static GTY(()) struct queued_reg_save *queued_reg_saves;
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 static const char *last_reg_save_label;
 
 static void
-queue_reg_save (label, reg, offset)
-     const char *label;
-     rtx reg;
-     long offset;
+queue_reg_save (const char *label, rtx reg, long int offset)
 {
-  struct queued_reg_save *q = (struct queued_reg_save *) xmalloc (sizeof (*q));
+  struct queued_reg_save *q = ggc_alloc (sizeof (*q));
 
   q->next = queued_reg_saves;
   q->reg = reg;
@@ -1112,7 +1126,7 @@ queue_reg_save (label, reg, offset)
 }
 
 static void
-flush_queued_reg_saves ()
+flush_queued_reg_saves (void)
 {
   struct queued_reg_save *q, *next;
 
@@ -1120,7 +1134,6 @@ flush_queued_reg_saves ()
     {
       dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset);
       next = q->next;
-      free (q);
     }
 
   queued_reg_saves = NULL;
@@ -1128,8 +1141,7 @@ flush_queued_reg_saves ()
 }
 
 static bool
-clobbers_queued_reg_save (insn)
-     rtx insn;
+clobbers_queued_reg_save (rtx insn)
 {
   struct queued_reg_save *q;
 
@@ -1175,7 +1187,7 @@ static dw_cfa_location cfa_temp;
   had better be the one we think we're using for this purpose.
 
   Except: If the register being saved is the CFA register, and the
-  offset is non-zero, we are saving the CFA, so we assume we have to
+  offset is nonzero, we are saving the CFA, so we assume we have to
   use DW_CFA_def_cfa_expression.  If the offset is 0, we assume that
   the intent is to save the value of SP from the previous frame.
 
@@ -1192,7 +1204,7 @@ static dw_cfa_location cfa_temp;
               to track stores to the stack via fp or a temp reg.
 
   Rules  1- 4: Setting a register's value to cfa.reg or an expression
-              with cfa.reg as the first operand changes the cfa.reg and its
+              with cfa.reg as the first operand changes the cfa.reg and its
               cfa.offset.  Rule 1 and 4 also set cfa_temp.reg and
               cfa_temp.offset.
 
@@ -1215,7 +1227,7 @@ static dw_cfa_location cfa_temp;
   Rule 1:
   (set <reg1> <reg2>:cfa.reg)
   effects: cfa.reg = <reg1>
-           cfa.offset unchanged
+          cfa.offset unchanged
           cfa_temp.reg = <reg1>
           cfa_temp.offset = cfa.offset
 
@@ -1223,19 +1235,19 @@ static dw_cfa_location cfa_temp;
   (set sp ({minus,plus,losum} {sp,fp}:cfa.reg
                              {<const_int>,<reg>:cfa_temp.reg}))
   effects: cfa.reg = sp if fp used
-          cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp
+          cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp
           cfa_store.offset += {+/- <const_int>, cfa_temp.offset}
             if cfa_store.reg==sp
 
   Rule 3:
   (set fp ({minus,plus,losum} <reg>:cfa.reg <const_int>))
   effects: cfa.reg = fp
-          cfa_offset += +/- <const_int>
+          cfa_offset += +/- <const_int>
 
   Rule 4:
   (set <reg1> ({plus,losum} <reg2>:cfa.reg <const_int>))
   constraints: <reg1> != fp
-              <reg1> != sp
+              <reg1> != sp
   effects: cfa.reg = <reg1>
           cfa_temp.reg = <reg1>
           cfa_temp.offset = cfa.offset
@@ -1243,14 +1255,14 @@ static dw_cfa_location cfa_temp;
   Rule 5:
   (set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg))
   constraints: <reg1> != fp
-              <reg1> != sp
+              <reg1> != sp
   effects: cfa_store.reg = <reg1>
-          cfa_store.offset = cfa.offset - cfa_temp.offset
+          cfa_store.offset = cfa.offset - cfa_temp.offset
 
   Rule 6:
   (set <reg> <const_int>)
   effects: cfa_temp.reg = <reg>
-          cfa_temp.offset = <const_int>
+          cfa_temp.offset = <const_int>
 
   Rule 7:
   (set <reg1>:cfa_temp.reg (ior <reg2>:cfa_temp.reg <const_int>))
@@ -1264,7 +1276,7 @@ static dw_cfa_location cfa_temp;
   Rule 9:
   (set <reg> (lo_sum <exp> <const_int>))
   effects: cfa_temp.reg = <reg>
-          cfa_temp.offset = <const_int>
+          cfa_temp.offset = <const_int>
 
   Rule 10:
   (set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>)
@@ -1299,9 +1311,7 @@ static dw_cfa_location cfa_temp;
           cfa_temp.offset -= mode_size(mem)  */
 
 static void
-dwarf2out_frame_debug_expr (expr, label)
-     rtx expr;
-     const char *label;
+dwarf2out_frame_debug_expr (rtx expr, const char *label)
 {
   rtx src, dest;
   HOST_WIDE_INT offset;
@@ -1336,7 +1346,7 @@ dwarf2out_frame_debug_expr (expr, label)
     case REG:
       /* Rule 1 */
       /* Update the CFA rule wrt SP or FP.  Make sure src is
-         relative to the current CFA register.  */
+        relative to the current CFA register.  */
       switch (GET_CODE (src))
        {
          /* Setting FP from SP.  */
@@ -1599,7 +1609,7 @@ dwarf2out_frame_debug_expr (expr, label)
          else
            {
              /* Otherwise, we'll need to look in the stack to
-                 calculate the CFA.  */
+                calculate the CFA.  */
              rtx x = XEXP (dest, 0);
 
              if (GET_CODE (x) != REG)
@@ -1629,8 +1639,7 @@ dwarf2out_frame_debug_expr (expr, label)
    register to the stack.  If INSN is NULL_RTX, initialize our state.  */
 
 void
-dwarf2out_frame_debug (insn)
-     rtx insn;
+dwarf2out_frame_debug (rtx insn)
 {
   const char *label;
   rtx src;
@@ -1673,13 +1682,84 @@ dwarf2out_frame_debug (insn)
   dwarf2out_frame_debug_expr (insn, label);
 }
 
+#endif
+
+/* Describe for the GTY machinery what parts of dw_cfi_oprnd1 are used.  */
+static enum dw_cfi_oprnd_type dw_cfi_oprnd1_desc
+ (enum dwarf_call_frame_info cfi);
+
+static enum dw_cfi_oprnd_type
+dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi)
+{
+  switch (cfi)
+    {
+    case DW_CFA_nop:
+    case DW_CFA_GNU_window_save:
+      return dw_cfi_oprnd_unused;
+
+    case DW_CFA_set_loc:
+    case DW_CFA_advance_loc1:
+    case DW_CFA_advance_loc2:
+    case DW_CFA_advance_loc4:
+    case DW_CFA_MIPS_advance_loc8:
+      return dw_cfi_oprnd_addr;
+
+    case DW_CFA_offset:
+    case DW_CFA_offset_extended:
+    case DW_CFA_def_cfa:
+    case DW_CFA_offset_extended_sf:
+    case DW_CFA_def_cfa_sf:
+    case DW_CFA_restore_extended:
+    case DW_CFA_undefined:
+    case DW_CFA_same_value:
+    case DW_CFA_def_cfa_register:
+    case DW_CFA_register:
+      return dw_cfi_oprnd_reg_num;
+
+    case DW_CFA_def_cfa_offset:
+    case DW_CFA_GNU_args_size:
+    case DW_CFA_def_cfa_offset_sf:
+      return dw_cfi_oprnd_offset;
+
+    case DW_CFA_def_cfa_expression:
+    case DW_CFA_expression:
+      return dw_cfi_oprnd_loc;
+
+    default:
+      abort ();
+    }
+}
+
+/* Describe for the GTY machinery what parts of dw_cfi_oprnd2 are used.  */
+static enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc
+ (enum dwarf_call_frame_info cfi);
+
+static enum dw_cfi_oprnd_type
+dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi)
+{
+  switch (cfi)
+    {
+    case DW_CFA_def_cfa:
+    case DW_CFA_def_cfa_sf:
+    case DW_CFA_offset:
+    case DW_CFA_offset_extended_sf:
+    case DW_CFA_offset_extended:
+      return dw_cfi_oprnd_offset;
+
+    case DW_CFA_register:
+      return dw_cfi_oprnd_reg_num;
+
+    default:
+      return dw_cfi_oprnd_unused;
+    }
+}
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+
 /* Output a Call Frame Information opcode and its operand(s).  */
 
 static void
-output_cfi (cfi, fde, for_eh)
-     dw_cfi_ref cfi;
-     dw_fde_ref fde;
-     int for_eh;
+output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
 {
   if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
     dw2_asm_output_data (1, (cfi->dw_cfi_opc
@@ -1802,14 +1882,13 @@ output_cfi (cfi, fde, for_eh)
    location of saved registers.  */
 
 static void
-output_call_frame_info (for_eh)
-     int for_eh;
+output_call_frame_info (int for_eh)
 {
   unsigned int i;
   dw_fde_ref fde;
   dw_cfi_ref cfi;
   char l1[20], l2[20], section_start_label[20];
-  int any_lsda_needed = 0;
+  bool any_lsda_needed = false;
   char augmentation[6];
   int augmentation_size;
   int fde_encoding = DW_EH_PE_absptr;
@@ -1820,17 +1899,20 @@ output_call_frame_info (for_eh)
   if (fde_table_in_use == 0)
     return;
 
-  /* If we don't have any functions we'll want to unwind out of, don't emit any
-     EH unwind information.  */
+  /* If we don't have any functions we'll want to unwind out of, don't
+     emit any EH unwind information.  Note that if exceptions aren't
+     enabled, we won't have collected nothrow information, and if we
+     asked for asynchronous tables, we always want this info.  */
   if (for_eh)
     {
-      int any_eh_needed = flag_asynchronous_unwind_tables;
+      bool any_eh_needed = !flag_exceptions || flag_asynchronous_unwind_tables;
 
       for (i = 0; i < fde_table_in_use; i++)
        if (fde_table[i].uses_eh_lsda)
-         any_eh_needed = any_lsda_needed = 1;
-       else if (! fde_table[i].nothrow)
-         any_eh_needed = 1;
+         any_eh_needed = any_lsda_needed = true;
+       else if (! fde_table[i].nothrow
+                && ! fde_table[i].all_throwers_are_sibcalls)
+         any_eh_needed = true;
 
       if (! any_eh_needed)
        return;
@@ -1871,7 +1953,7 @@ output_call_frame_info (for_eh)
 
       /* Augmentation:
         z      Indicates that a uleb128 is present to size the
-               augmentation section.
+               augmentation section.
         L      Indicates the encoding (and thus presence) of
                an LSDA pointer in the FDE augmentation.
         R      Indicates a non-default pointer encoding for
@@ -1968,10 +2050,12 @@ output_call_frame_info (for_eh)
       fde = &fde_table[i];
 
       /* Don't emit EH unwind info for leaf functions that don't need it.  */
-      if (for_eh && fde->nothrow && ! fde->uses_eh_lsda)
+      if (for_eh && !flag_asynchronous_unwind_tables && flag_exceptions
+         && (fde->nothrow || fde->all_throwers_are_sibcalls)
+         && !fde->uses_eh_lsda)
        continue;
 
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2);
+      (*targetm.asm_out.internal_label) (asm_out_file, FDE_LABEL, for_eh + i * 2);
       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);
       dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
@@ -2024,13 +2108,13 @@ output_call_frame_info (for_eh)
              dw2_asm_output_data_uleb128 (size, "Augmentation size");
 
              if (fde->uses_eh_lsda)
-               {
-                 ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA",
+               {
+                 ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA",
                                               fde->funcdef_number);
-                 dw2_asm_output_encoded_addr_rtx (
+                 dw2_asm_output_encoded_addr_rtx (
                        lsda_encoding, gen_rtx_SYMBOL_REF (Pmode, l1),
-                       "Language Specific Data Area");
-               }
+                       "Language Specific Data Area");
+               }
              else
                {
                  if (lsda_encoding == DW_EH_PE_aligned)
@@ -2052,14 +2136,12 @@ output_call_frame_info (for_eh)
 
       /* Pad the FDE out to an address sized boundary.  */
       ASM_OUTPUT_ALIGN (asm_out_file,
-                       floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)));
+                       floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)));
       ASM_OUTPUT_LABEL (asm_out_file, l2);
     }
 
-#ifndef EH_FRAME_SECTION_NAME
-  if (for_eh)
+  if (for_eh && targetm.terminate_dw2_eh_frame_info)
     dw2_asm_output_data (4, 0, "End of Table");
-#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.  */
@@ -2075,9 +2157,8 @@ output_call_frame_info (for_eh)
    the prologue.  */
 
 void
-dwarf2out_begin_prologue (line, file)
-     unsigned int line ATTRIBUTE_UNUSED;
-     const char *file ATTRIBUTE_UNUSED;
+dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
+                         const char *file ATTRIBUTE_UNUSED)
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
   dw_fde_ref fde;
@@ -2096,12 +2177,11 @@ dwarf2out_begin_prologue (line, file)
     return;
 #endif
 
-  current_funcdef_number++;
   function_section (current_function_decl);
   ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
-                              current_funcdef_number);
+                              current_function_funcdef_no);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL,
-                         current_funcdef_number);
+                         current_function_funcdef_no);
   current_function_func_begin_label = get_identifier (label);
 
 #ifdef IA64_UNWIND_INFO
@@ -2114,9 +2194,10 @@ dwarf2out_begin_prologue (line, file)
   if (fde_table_in_use == fde_table_allocated)
     {
       fde_table_allocated += FDE_TABLE_INCREMENT;
-      fde_table
-       = (dw_fde_ref) xrealloc (fde_table,
-                                fde_table_allocated * sizeof (dw_fde_node));
+      fde_table = ggc_realloc (fde_table,
+                              fde_table_allocated * sizeof (dw_fde_node));
+      memset (fde_table + fde_table_in_use, 0,
+             FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
     }
 
   /* Record the FDE associated with this function.  */
@@ -2128,9 +2209,10 @@ dwarf2out_begin_prologue (line, file)
   fde->dw_fde_current_label = NULL;
   fde->dw_fde_end = NULL;
   fde->dw_fde_cfi = NULL;
-  fde->funcdef_number = current_funcdef_number;
+  fde->funcdef_number = current_function_funcdef_no;
   fde->nothrow = current_function_nothrow;
   fde->uses_eh_lsda = cfun->uses_eh_lsda;
+  fde->all_throwers_are_sibcalls = cfun->all_throwers_are_sibcalls;
 
   args_size = old_args_size = 0;
 
@@ -2147,24 +2229,27 @@ dwarf2out_begin_prologue (line, file)
    been generated.  */
 
 void
-dwarf2out_end_epilogue ()
+dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
+                       const char *file ATTRIBUTE_UNUSED)
 {
   dw_fde_ref fde;
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   /* Output a label to mark the endpoint of the code generated for this
      function.  */
-  ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number);
+  ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
+                              current_function_funcdef_no);
   ASM_OUTPUT_LABEL (asm_out_file, label);
   fde = &fde_table[fde_table_in_use - 1];
   fde->dw_fde_end = xstrdup (label);
 }
 
 void
-dwarf2out_frame_init ()
+dwarf2out_frame_init (void)
 {
   /* Allocate the initial hunk of the fde_table.  */
-  fde_table = (dw_fde_ref) xcalloc (FDE_TABLE_INCREMENT, sizeof (dw_fde_node));
+  fde_table = (dw_fde_ref) ggc_alloc_cleared (FDE_TABLE_INCREMENT
+                                             * sizeof (dw_fde_node));
   fde_table_allocated = FDE_TABLE_INCREMENT;
   fde_table_in_use = 0;
 
@@ -2179,7 +2264,7 @@ dwarf2out_frame_init ()
 }
 
 void
-dwarf2out_frame_finish ()
+dwarf2out_frame_finish (void)
 {
   /* Output call frame information.  */
   if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
@@ -2188,10 +2273,16 @@ dwarf2out_frame_finish ()
   if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions))
     output_call_frame_info (1);
 }
+#endif
 \f
 /* And now, the subset of the debugging information support code necessary
    for emitting location expressions.  */
 
+/* We need some way to distinguish DW_OP_addr with a direct symbol
+   relocation from DW_OP_addr with a dtp-relative symbol relocation.  */
+#define INTERNAL_DW_OP_tls_addr                (0x100 + DW_OP_addr)
+
+
 typedef struct dw_val_struct *dw_val_ref;
 typedef struct die_struct *dw_die_ref;
 typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
@@ -2201,7 +2292,7 @@ typedef struct dw_loc_list_struct *dw_loc_list_ref;
    can take on several forms.  The forms that are used in this
    implementation are listed below.  */
 
-typedef enum
+enum dw_val_class
 {
   dw_val_class_addr,
   dw_val_class_offset,
@@ -2218,13 +2309,12 @@ typedef enum
   dw_val_class_lbl_id,
   dw_val_class_lbl_offset,
   dw_val_class_str
-}
-dw_val_class;
+};
 
 /* Describe a double word constant value.  */
 /* ??? Every instance of long_long in the code really means CONST_DOUBLE.  */
 
-typedef struct dw_long_long_struct
+typedef struct dw_long_long_struct GTY(())
 {
   unsigned long hi;
   unsigned long low;
@@ -2233,9 +2323,9 @@ dw_long_long_const;
 
 /* Describe a floating point constant value.  */
 
-typedef struct dw_fp_struct
+typedef struct dw_fp_struct GTY(())
 {
-  long *array;
+  long * GTY((length ("%h.length"))) array;
   unsigned length;
 }
 dw_float_const;
@@ -2243,37 +2333,37 @@ dw_float_const;
 /* The dw_val_node describes an attribute's value, as it is
    represented internally.  */
 
-typedef struct dw_val_struct
+typedef struct dw_val_struct GTY(())
 {
-  dw_val_class val_class;
-  union
+  enum dw_val_class val_class;
+  union dw_val_struct_union
     {
-      rtx val_addr;
-      long unsigned val_offset;
-      dw_loc_list_ref  val_loc_list;
-      dw_loc_descr_ref val_loc;
-      long int val_int;
-      long unsigned val_unsigned;
-      dw_long_long_const val_long_long;
-      dw_float_const val_float;
-      struct
+      rtx GTY ((tag ("dw_val_class_addr"))) val_addr;
+      long unsigned GTY ((tag ("dw_val_class_offset"))) val_offset;
+      dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list;
+      dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
+      long int GTY ((default (""))) val_int;
+      long unsigned GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
+      dw_long_long_const GTY ((tag ("dw_val_class_long_long"))) val_long_long;
+      dw_float_const GTY ((tag ("dw_val_class_float"))) val_float;
+      struct dw_val_die_union
        {
          dw_die_ref die;
          int external;
-       } val_die_ref;
-      unsigned val_fde_index;
-      struct indirect_string_node *val_str;
-      char *val_lbl_id;
-      unsigned char val_flag;
+       } GTY ((tag ("dw_val_class_die_ref"))) val_die_ref;
+      unsigned GTY ((tag ("dw_val_class_fde_ref"))) val_fde_index;
+      struct indirect_string_node * GTY ((tag ("dw_val_class_str"))) val_str;
+      char * GTY ((tag ("dw_val_class_lbl_id"))) val_lbl_id;
+      unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag;
     }
-  v;
+  GTY ((desc ("%1.val_class"))) v;
 }
 dw_val_node;
 
 /* Locations in memory are described using a sequence of stack machine
    operations.  */
 
-typedef struct dw_loc_descr_struct
+typedef struct dw_loc_descr_struct GTY(())
 {
   dw_loc_descr_ref dw_loc_next;
   enum dwarf_location_atom dw_loc_opc;
@@ -2286,7 +2376,7 @@ dw_loc_descr_node;
 /* Location lists are ranges + location descriptions for that range,
    so you can track variables that are in different places over
    their entire life.  */
-typedef struct dw_loc_list_struct
+typedef struct dw_loc_list_struct GTY(())
 {
   dw_loc_list_ref dw_loc_next;
   const char *begin; /* Label for begin address of range */
@@ -2297,26 +2387,26 @@ typedef struct dw_loc_list_struct
   dw_loc_descr_ref expr;
 } dw_loc_list_node;
 
-static const char *dwarf_stack_op_name PARAMS ((unsigned));
-static dw_loc_descr_ref new_loc_descr  PARAMS ((enum dwarf_location_atom,
-                                                unsigned long,
-                                                unsigned long));
-static void add_loc_descr              PARAMS ((dw_loc_descr_ref *,
-                                                dw_loc_descr_ref));
-static unsigned long size_of_loc_descr PARAMS ((dw_loc_descr_ref));
-static unsigned long size_of_locs      PARAMS ((dw_loc_descr_ref));
-static void output_loc_operands                PARAMS ((dw_loc_descr_ref));
-static void output_loc_sequence                PARAMS ((dw_loc_descr_ref));
+#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
+
+static const char *dwarf_stack_op_name (unsigned);
+static dw_loc_descr_ref new_loc_descr (enum dwarf_location_atom,
+                                      unsigned long, unsigned long);
+static void add_loc_descr (dw_loc_descr_ref *, dw_loc_descr_ref);
+static unsigned long size_of_loc_descr (dw_loc_descr_ref);
+static unsigned long size_of_locs (dw_loc_descr_ref);
+static void output_loc_operands (dw_loc_descr_ref);
+static void output_loc_sequence (dw_loc_descr_ref);
 
 /* Convert a DWARF stack opcode into its string name.  */
 
 static const char *
-dwarf_stack_op_name (op)
-     unsigned op;
+dwarf_stack_op_name (unsigned int op)
 {
   switch (op)
     {
     case DW_OP_addr:
+    case INTERNAL_DW_OP_tls_addr:
       return "DW_OP_addr";
     case DW_OP_deref:
       return "DW_OP_deref";
@@ -2606,6 +2696,16 @@ dwarf_stack_op_name (op)
       return "DW_OP_xderef_size";
     case DW_OP_nop:
       return "DW_OP_nop";
+    case DW_OP_push_object_address:
+      return "DW_OP_push_object_address";
+    case DW_OP_call2:
+      return "DW_OP_call2";
+    case DW_OP_call4:
+      return "DW_OP_call4";
+    case DW_OP_call_ref:
+      return "DW_OP_call_ref";
+    case DW_OP_GNU_push_tls_address:
+      return "DW_OP_GNU_push_tls_address";
     default:
       return "OP_<unknown>";
     }
@@ -2616,15 +2716,11 @@ dwarf_stack_op_name (op)
    together to form more complicated location (address) descriptions.  */
 
 static inline dw_loc_descr_ref
-new_loc_descr (op, oprnd1, oprnd2)
-     enum dwarf_location_atom op;
-     unsigned long oprnd1;
-     unsigned long oprnd2;
+new_loc_descr (enum dwarf_location_atom op, long unsigned int oprnd1,
+              long unsigned int oprnd2)
 {
-  /* Use xcalloc here so we clear out all of the long_long constant in
-     the union.  */
   dw_loc_descr_ref descr
-    = (dw_loc_descr_ref) xcalloc (1, sizeof (dw_loc_descr_node));
+    = (dw_loc_descr_ref) ggc_alloc_cleared (sizeof (dw_loc_descr_node));
 
   descr->dw_loc_opc = op;
   descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
@@ -2639,9 +2735,7 @@ new_loc_descr (op, oprnd1, oprnd2)
 /* Add a location description term to a location description expression.  */
 
 static inline void
-add_loc_descr (list_head, descr)
-     dw_loc_descr_ref *list_head;
-     dw_loc_descr_ref descr;
+add_loc_descr (dw_loc_descr_ref *list_head, dw_loc_descr_ref descr)
 {
   dw_loc_descr_ref *d;
 
@@ -2655,14 +2749,14 @@ add_loc_descr (list_head, descr)
 /* Return the size of a location descriptor.  */
 
 static unsigned long
-size_of_loc_descr (loc)
-     dw_loc_descr_ref loc;
+size_of_loc_descr (dw_loc_descr_ref loc)
 {
   unsigned long size = 1;
 
   switch (loc->dw_loc_opc)
     {
     case DW_OP_addr:
+    case INTERNAL_DW_OP_tls_addr:
       size += DWARF2_ADDR_SIZE;
       break;
     case DW_OP_const1u:
@@ -2748,6 +2842,15 @@ size_of_loc_descr (loc)
     case DW_OP_xderef_size:
       size += 1;
       break;
+    case DW_OP_call2:
+      size += 2;
+      break;
+    case DW_OP_call4:
+      size += 4;
+      break;
+    case DW_OP_call_ref:
+      size += DWARF2_ADDR_SIZE;
+      break;
     default:
       break;
     }
@@ -2758,8 +2861,7 @@ size_of_loc_descr (loc)
 /* Return the size of a series of location descriptors.  */
 
 static unsigned long
-size_of_locs (loc)
-     dw_loc_descr_ref loc;
+size_of_locs (dw_loc_descr_ref loc)
 {
   unsigned long size;
 
@@ -2775,8 +2877,7 @@ size_of_locs (loc)
 /* Output location description stack opcode's operands (if any).  */
 
 static void
-output_loc_operands (loc)
-     dw_loc_descr_ref loc;
+output_loc_operands (dw_loc_descr_ref loc)
 {
   dw_val_ref val1 = &loc->dw_loc_oprnd1;
   dw_val_ref val2 = &loc->dw_loc_oprnd2;
@@ -2825,9 +2926,9 @@ output_loc_operands (loc)
     case DW_OP_skip:
     case DW_OP_bra:
       /* We currently don't make any attempt to make sure these are
-         aligned properly like we do for the main unwind info, so
-         don't support emitting things larger than a byte if we're
-         only doing unwinding.  */
+        aligned properly like we do for the main unwind info, so
+        don't support emitting things larger than a byte if we're
+        only doing unwinding.  */
       abort ();
 #endif
     case DW_OP_const1u:
@@ -2897,6 +2998,17 @@ output_loc_operands (loc)
     case DW_OP_xderef_size:
       dw2_asm_output_data (1, val1->v.val_int, NULL);
       break;
+
+    case INTERNAL_DW_OP_tls_addr:
+#ifdef ASM_OUTPUT_DWARF_DTPREL
+      ASM_OUTPUT_DWARF_DTPREL (asm_out_file, DWARF2_ADDR_SIZE,
+                              val1->v.val_addr);
+      fputc ('\n', asm_out_file);
+#else
+      abort ();
+#endif
+      break;
+
     default:
       /* Other codes have no operands.  */
       break;
@@ -2906,8 +3018,7 @@ output_loc_operands (loc)
 /* Output a sequence of location operations.  */
 
 static void
-output_loc_sequence (loc)
-     dw_loc_descr_ref loc;
+output_loc_sequence (dw_loc_descr_ref loc)
 {
   for (; loc != NULL; loc = loc->dw_loc_next)
     {
@@ -2924,8 +3035,7 @@ output_loc_sequence (loc)
    description based on a cfi entry with a complex address.  */
 
 static void
-output_cfa_loc (cfi)
-     dw_cfi_ref cfi;
+output_cfa_loc (dw_cfi_ref cfi)
 {
   dw_loc_descr_ref loc;
   unsigned long size;
@@ -2943,8 +3053,7 @@ output_cfa_loc (cfi)
    a dw_cfa_location.  */
 
 static struct dw_loc_descr_struct *
-build_cfa_loc (cfa)
-     dw_cfa_location *cfa;
+build_cfa_loc (dw_cfa_location *cfa)
 {
   struct dw_loc_descr_struct *head, *tmp;
 
@@ -2979,9 +3088,7 @@ build_cfa_loc (cfa)
    descriptor sequence.  */
 
 static void
-get_cfa_from_loc_descr (cfa, loc)
-     dw_cfa_location *cfa;
-     struct dw_loc_descr_struct *loc;
+get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_struct *loc)
 {
   struct dw_loc_descr_struct *ptr;
   cfa->offset = 0;
@@ -3089,22 +3196,19 @@ get_cfa_from_loc_descr (cfa, loc)
 #ifdef DWARF2_DEBUGGING_INFO
 
 /* .debug_str support.  */
-static hashnode indirect_string_alloc  PARAMS ((hash_table *));
-static int output_indirect_string      PARAMS ((struct cpp_reader *,
-                                                 hashnode, const PTR));
-
-
-static void dwarf2out_init             PARAMS ((const char *));
-static void dwarf2out_finish           PARAMS ((const char *));
-static void dwarf2out_define           PARAMS ((unsigned int, const char *));
-static void dwarf2out_undef            PARAMS ((unsigned int, const char *));
-static void dwarf2out_start_source_file        PARAMS ((unsigned, const char *));
-static void dwarf2out_end_source_file  PARAMS ((unsigned));
-static void dwarf2out_begin_block      PARAMS ((unsigned, unsigned));
-static void dwarf2out_end_block                PARAMS ((unsigned, unsigned));
-static bool dwarf2out_ignore_block     PARAMS ((tree));
-static void dwarf2out_global_decl      PARAMS ((tree));
-static void dwarf2out_abstract_function PARAMS ((tree));
+static int output_indirect_string (void **, void *);
+
+static void dwarf2out_init (const char *);
+static void dwarf2out_finish (const char *);
+static void dwarf2out_define (unsigned int, const char *);
+static void dwarf2out_undef (unsigned int, const char *);
+static void dwarf2out_start_source_file (unsigned, const char *);
+static void dwarf2out_end_source_file (unsigned);
+static void dwarf2out_begin_block (unsigned, unsigned);
+static void dwarf2out_end_block (unsigned, unsigned);
+static bool dwarf2out_ignore_block (tree);
+static void dwarf2out_global_decl (tree);
+static void dwarf2out_abstract_function (tree);
 
 /* The debug hooks structure.  */
 
@@ -3121,7 +3225,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   dwarf2out_ignore_block,
   dwarf2out_source_line,
   dwarf2out_begin_prologue,
-  debug_nothing_int,           /* end_prologue */
+  debug_nothing_int_charstar,  /* end_prologue */
   dwarf2out_end_epilogue,
   debug_nothing_tree,          /* begin_function */
   debug_nothing_int,           /* end_function */
@@ -3132,8 +3236,10 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
      emitting the abstract description of inline functions until
      something tries to reference them.  */
   dwarf2out_abstract_function, /* outlining_inline_function */
-  debug_nothing_rtx            /* label */
+  debug_nothing_rtx,           /* label */
+  debug_nothing_int            /* handle_pch */
 };
+#endif
 \f
 /* NOTE: In the comments in this file, many references are made to
    "Debugging Information Entries".  This term is abbreviated as `DIE'
@@ -3162,7 +3268,7 @@ typedef struct dw_ranges_struct *dw_ranges_ref;
    entry.  The label gives the PC value associated with
    the line number entry.  */
 
-typedef struct dw_line_info_struct
+typedef struct dw_line_info_struct GTY(())
 {
   unsigned long dw_file_num;
   unsigned long dw_line_num;
@@ -3171,7 +3277,7 @@ dw_line_info_entry;
 
 /* Line information for functions in separate sections; each one gets its
    own sequence.  */
-typedef struct dw_separate_line_info_struct
+typedef struct dw_separate_line_info_struct GTY(())
 {
   unsigned long dw_file_num;
   unsigned long dw_line_num;
@@ -3183,7 +3289,7 @@ dw_separate_line_info_entry;
    a link to the next attribute in the chain, and an attribute value.
    Attributes are typically linked below the DIE they modify.  */
 
-typedef struct dw_attr_struct
+typedef struct dw_attr_struct GTY(())
 {
   enum dwarf_attribute dw_attr;
   dw_attr_ref dw_attr_next;
@@ -3193,7 +3299,7 @@ dw_attr_node;
 
 /* The Debugging Information Entry (DIE) structure */
 
-typedef struct die_struct
+typedef struct die_struct GTY(())
 {
   enum dwarf_tag die_tag;
   char *die_symbol;
@@ -3209,20 +3315,20 @@ die_node;
 
 /* The pubname structure */
 
-typedef struct pubname_struct
+typedef struct pubname_struct GTY(())
 {
   dw_die_ref die;
   char *name;
 }
 pubname_entry;
 
-struct dw_ranges_struct
+struct dw_ranges_struct GTY(())
 {
   int block_num;
 };
 
 /* The limbo die list structure.  */
-typedef struct limbo_die_struct
+typedef struct limbo_die_struct GTY(())
 {
   dw_die_ref die;
   tree created_for;
@@ -3235,7 +3341,7 @@ limbo_die_node;
 #define ASM_COMMENT_START ";#"
 #endif
 
-/* Define a macro which returns non-zero for a TYPE_DECL which was
+/* Define a macro which returns nonzero for a TYPE_DECL which was
    implicitly generated for a tagged type.
 
    Note that unlike the gcc front end (which generates a NULL named
@@ -3260,24 +3366,24 @@ limbo_die_node;
    language, and compiler version.  */
 
 /* Fixed size portion of the DWARF compilation unit header.  */
-#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
-
-/* Fixed size portion of debugging line information prolog.  */
-#define DWARF_LINE_PROLOG_HEADER_SIZE 5
+#define DWARF_COMPILE_UNIT_HEADER_SIZE \
+  (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 3)
 
 /* Fixed size portion of public names info.  */
 #define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
 
 /* Fixed size portion of the address range info.  */
 #define DWARF_ARANGES_HEADER_SIZE                                      \
-  (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2)       \
-   - DWARF_OFFSET_SIZE)
+  (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4,     \
+                DWARF2_ADDR_SIZE * 2)                                  \
+   - DWARF_INITIAL_LENGTH_SIZE)
 
 /* Size of padding portion in the address range info.  It must be
    aligned to twice the pointer size.  */
 #define DWARF_ARANGES_PAD_SIZE \
-  (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \
-   - (2 * DWARF_OFFSET_SIZE + 4))
+  (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \
+                DWARF2_ADDR_SIZE * 2) \
+   - (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4))
 
 /* Use assembler line directives if available.  */
 #ifndef DWARF2_ASM_LINE_DEBUG_INFO
@@ -3304,68 +3410,55 @@ limbo_die_node;
    is not made available by the GCC front-end.  */
 #define        DWARF_LINE_DEFAULT_IS_STMT_START 1
 
+#ifdef DWARF2_DEBUGGING_INFO
 /* This location is used by calc_die_sizes() to keep track
    the offset of each DIE within the .debug_info section.  */
 static unsigned long next_die_offset;
+#endif
 
 /* Record the root of the DIE's built for the current compilation unit.  */
-static dw_die_ref comp_unit_die;
-
-/* A list of DIEs with a NULL parent waiting to be relocated.  */
-static limbo_die_node *limbo_die_list = 0;
+static GTY(()) dw_die_ref comp_unit_die;
 
-/* Structure used by lookup_filename to manage sets of filenames.  */
-struct file_table
-{
-  char **table;
-  unsigned allocated;
-  unsigned in_use;
-  unsigned last_lookup_index;
-};
+#ifdef DWARF2_DEBUGGING_INFO
+/* We need special handling in dwarf2out_start_source_file if it is
+   first one.  */
+static int is_main_source;
+#endif
 
-/* Size (in elements) of increments by which we may expand the filename
-   table.  */
-#define FILE_TABLE_INCREMENT 64
+/* A list of DIEs with a NULL parent waiting to be relocated.  */
+static GTY(()) limbo_die_node *limbo_die_list;
 
 /* Filenames referenced by this compilation unit.  */
-static struct file_table file_table;
-
-/* Local pointer to the name of the main input file.  Initialized in
-   dwarf2out_init.  */
-static const char *primary_filename;
+static GTY(()) varray_type file_table;
+static GTY(()) varray_type file_table_emitted;
+static GTY(()) size_t file_table_last_lookup_index;
 
 /* 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 identifying each decl.  */
-static dw_die_ref *decl_die_table;
+static GTY((length ("decl_die_table_allocated"))) dw_die_ref *decl_die_table;
 
 /* Number of elements currently allocated for the decl_die_table.  */
-static unsigned decl_die_table_allocated;
+static GTY(()) unsigned decl_die_table_allocated;
 
 /* Number of elements in decl_die_table currently in use.  */
-static unsigned decl_die_table_in_use;
+static GTY(()) unsigned decl_die_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
    decl_die_table.  */
 #define DECL_DIE_TABLE_INCREMENT 256
 
-/* 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.  */
-varray_type decl_scope_table;
-
 /* A pointer to the base of a list of references to DIE's that
    are uniquely identified by their tag, presence/absence of
    children DIE's, and list of attribute/value pairs.  */
-static dw_die_ref *abbrev_die_table;
+static GTY((length ("abbrev_die_table_allocated")))
+  dw_die_ref *abbrev_die_table;
 
 /* Number of elements currently allocated for abbrev_die_table.  */
-static unsigned abbrev_die_table_allocated;
+static GTY(()) unsigned abbrev_die_table_allocated;
 
 /* Number of elements in type_die_table currently in use.  */
-static unsigned abbrev_die_table_in_use;
+static GTY(()) unsigned abbrev_die_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
    abbrev_die_table.  */
@@ -3373,23 +3466,25 @@ static unsigned abbrev_die_table_in_use;
 
 /* A pointer to the base of a table that contains line information
    for each source code line in .text in the compilation unit.  */
-static dw_line_info_ref line_info_table;
+static GTY((length ("line_info_table_allocated")))
+     dw_line_info_ref line_info_table;
 
 /* Number of elements currently allocated for line_info_table.  */
-static unsigned line_info_table_allocated;
+static GTY(()) unsigned line_info_table_allocated;
 
-/* Number of elements in separate_line_info_table currently in use.  */
-static unsigned separate_line_info_table_in_use;
+/* Number of elements in line_info_table currently in use.  */
+static GTY(()) unsigned line_info_table_in_use;
 
 /* A pointer to the base of a table that contains line information
    for each source code line outside of .text in the compilation unit.  */
-static dw_separate_line_info_ref separate_line_info_table;
+static GTY ((length ("separate_line_info_table_allocated")))
+     dw_separate_line_info_ref separate_line_info_table;
 
 /* Number of elements currently allocated for separate_line_info_table.  */
-static unsigned separate_line_info_table_allocated;
+static GTY(()) unsigned separate_line_info_table_allocated;
 
-/* Number of elements in line_info_table currently in use.  */
-static unsigned line_info_table_in_use;
+/* Number of elements in separate_line_info_table currently in use.  */
+static GTY(()) unsigned separate_line_info_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
    line_info_table.  */
@@ -3397,305 +3492,292 @@ static unsigned line_info_table_in_use;
 
 /* A pointer to the base of a table that contains a list of publicly
    accessible names.  */
-static pubname_ref pubname_table;
+static GTY ((length ("pubname_table_allocated"))) pubname_ref pubname_table;
 
 /* Number of elements currently allocated for pubname_table.  */
-static unsigned pubname_table_allocated;
+static GTY(()) unsigned pubname_table_allocated;
 
 /* Number of elements in pubname_table currently in use.  */
-static unsigned pubname_table_in_use;
+static GTY(()) unsigned pubname_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
    pubname_table.  */
 #define PUBNAME_TABLE_INCREMENT 64
 
 /* Array of dies for which we should generate .debug_arange info.  */
-static dw_die_ref *arange_table;
+static GTY((length ("arange_table_allocated"))) dw_die_ref *arange_table;
 
 /* Number of elements currently allocated for arange_table.  */
-static unsigned arange_table_allocated;
+static GTY(()) unsigned arange_table_allocated;
 
 /* Number of elements in arange_table currently in use.  */
-static unsigned arange_table_in_use;
+static GTY(()) unsigned arange_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
    arange_table.  */
 #define ARANGE_TABLE_INCREMENT 64
 
 /* Array of dies for which we should generate .debug_ranges info.  */
-static dw_ranges_ref ranges_table;
+static GTY ((length ("ranges_table_allocated"))) dw_ranges_ref ranges_table;
 
 /* Number of elements currently allocated for ranges_table.  */
-static unsigned ranges_table_allocated;
+static GTY(()) unsigned ranges_table_allocated;
 
 /* Number of elements in ranges_table currently in use.  */
-static unsigned ranges_table_in_use;
+static GTY(()) unsigned ranges_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
    ranges_table.  */
 #define RANGES_TABLE_INCREMENT 64
 
 /* Whether we have location lists that need outputting */
-static unsigned have_location_lists;
-
-/* A pointer to the base of a list of incomplete types which might be
-   completed at some later time.  incomplete_types_list needs to be a VARRAY
-   because we want to tell the garbage collector about it.  */
-varray_type incomplete_types;
+static GTY(()) unsigned have_location_lists;
 
+#ifdef DWARF2_DEBUGGING_INFO
 /* Record whether the function being analyzed contains inlined functions.  */
 static int current_function_has_inlines;
+#endif
 #if 0 && defined (MIPS_DEBUGGING_INFO)
 static int comp_unit_has_inlines;
 #endif
 
-/* Array of RTXes referenced by the debugging information, which therefore
-   must be kept around forever.  This is a GC root.  */
-static varray_type used_rtx_varray;
+/* Number of file tables emitted in maybe_emit_file().  */
+static GTY(()) int emitcount = 0;
+
+/* Number of internal labels generated by gen_internal_sym().  */
+static GTY(()) int label_num;
+
+#ifdef DWARF2_DEBUGGING_INFO
 
 /* Forward declarations for functions defined in this file.  */
 
-static int is_pseudo_reg               PARAMS ((rtx));
-static tree type_main_variant          PARAMS ((tree));
-static int is_tagged_type              PARAMS ((tree));
-static const char *dwarf_tag_name      PARAMS ((unsigned));
-static const char *dwarf_attr_name     PARAMS ((unsigned));
-static const char *dwarf_form_name     PARAMS ((unsigned));
+static int is_pseudo_reg (rtx);
+static tree type_main_variant (tree);
+static int is_tagged_type (tree);
+static const char *dwarf_tag_name (unsigned);
+static const char *dwarf_attr_name (unsigned);
+static const char *dwarf_form_name (unsigned);
 #if 0
-static const char *dwarf_type_encoding_name PARAMS ((unsigned));
+static const char *dwarf_type_encoding_name (unsigned);
 #endif
-static tree decl_ultimate_origin       PARAMS ((tree));
-static tree block_ultimate_origin      PARAMS ((tree));
-static tree decl_class_context         PARAMS ((tree));
-static void add_dwarf_attr             PARAMS ((dw_die_ref, dw_attr_ref));
-static inline dw_val_class AT_class    PARAMS ((dw_attr_ref));
-static void add_AT_flag                        PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned));
-static inline unsigned AT_flag         PARAMS ((dw_attr_ref));
-static void add_AT_int                 PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute, long));
-static inline long int AT_int          PARAMS ((dw_attr_ref));
-static void add_AT_unsigned            PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned long));
-static inline unsigned long            AT_unsigned PARAMS ((dw_attr_ref));
-static void add_AT_long_long           PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned long,
-                                                unsigned long));
-static void add_AT_float               PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned, long *));
-static void add_AT_string              PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                const char *));
-static inline const char *AT_string    PARAMS ((dw_attr_ref));
-static int AT_string_form              PARAMS ((dw_attr_ref));
-static void add_AT_die_ref             PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                dw_die_ref));
-static inline dw_die_ref AT_ref                PARAMS ((dw_attr_ref));
-static inline int AT_ref_external      PARAMS ((dw_attr_ref));
-static inline void set_AT_ref_external PARAMS ((dw_attr_ref, int));
-static void add_AT_fde_ref             PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned));
-static void add_AT_loc                 PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                dw_loc_descr_ref));
-static inline dw_loc_descr_ref AT_loc  PARAMS ((dw_attr_ref));
-static void add_AT_loc_list            PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                dw_loc_list_ref));
-static inline dw_loc_list_ref AT_loc_list PARAMS ((dw_attr_ref));
-static void add_AT_addr                        PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                rtx));
-static inline rtx AT_addr              PARAMS ((dw_attr_ref));
-static void add_AT_lbl_id              PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                const char *));
-static void add_AT_lbl_offset          PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                const char *));
-static void add_AT_offset              PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned long));
-static void add_AT_range_list          PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute,
-                                                unsigned long));
-static inline const char *AT_lbl       PARAMS ((dw_attr_ref));
-static dw_attr_ref get_AT              PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static const char *get_AT_low_pc       PARAMS ((dw_die_ref));
-static const char *get_AT_hi_pc                PARAMS ((dw_die_ref));
-static const char *get_AT_string       PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static int get_AT_flag                 PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static unsigned get_AT_unsigned                PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static inline dw_die_ref get_AT_ref    PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static int is_c_family                 PARAMS ((void));
-static int is_cxx                      PARAMS ((void));
-static int is_java                     PARAMS ((void));
-static int is_fortran                  PARAMS ((void));
-static void remove_AT                  PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute));
-static inline void free_die            PARAMS ((dw_die_ref));
-static void remove_children            PARAMS ((dw_die_ref));
-static void add_child_die              PARAMS ((dw_die_ref, dw_die_ref));
-static dw_die_ref new_die              PARAMS ((enum dwarf_tag, dw_die_ref,
-                                                tree));
-static dw_die_ref lookup_type_die      PARAMS ((tree));
-static void equate_type_number_to_die  PARAMS ((tree, dw_die_ref));
-static dw_die_ref lookup_decl_die      PARAMS ((tree));
-static void equate_decl_number_to_die  PARAMS ((tree, dw_die_ref));
-static void print_spaces               PARAMS ((FILE *));
-static void print_die                  PARAMS ((dw_die_ref, FILE *));
-static void print_dwarf_line_table     PARAMS ((FILE *));
-static void reverse_die_lists          PARAMS ((dw_die_ref));
-static void reverse_all_dies           PARAMS ((dw_die_ref));
-static dw_die_ref push_new_compile_unit PARAMS ((dw_die_ref, dw_die_ref));
-static dw_die_ref pop_compile_unit     PARAMS ((dw_die_ref));
-static void loc_checksum               PARAMS ((dw_loc_descr_ref,
-                                                struct md5_ctx *));
-static void attr_checksum              PARAMS ((dw_attr_ref,
-                                                struct md5_ctx *));
-static void die_checksum               PARAMS ((dw_die_ref,
-                                                struct md5_ctx *));
-static void compute_section_prefix     PARAMS ((dw_die_ref));
-static int is_type_die                 PARAMS ((dw_die_ref));
-static int is_comdat_die               PARAMS ((dw_die_ref));
-static int is_symbol_die               PARAMS ((dw_die_ref));
-static void assign_symbol_names                PARAMS ((dw_die_ref));
-static void break_out_includes         PARAMS ((dw_die_ref));
-static void add_sibling_attributes     PARAMS ((dw_die_ref));
-static void build_abbrev_table         PARAMS ((dw_die_ref));
-static void output_location_lists      PARAMS ((dw_die_ref));
-static int constant_size               PARAMS ((long unsigned));
-static unsigned long size_of_die       PARAMS ((dw_die_ref));
-static void calc_die_sizes             PARAMS ((dw_die_ref));
-static void mark_dies                  PARAMS ((dw_die_ref));
-static void unmark_dies                        PARAMS ((dw_die_ref));
-static unsigned long size_of_pubnames  PARAMS ((void));
-static unsigned long size_of_aranges   PARAMS ((void));
-static enum dwarf_form value_format    PARAMS ((dw_attr_ref));
-static void output_value_format                PARAMS ((dw_attr_ref));
-static void output_abbrev_section      PARAMS ((void));
-static void output_die_symbol          PARAMS ((dw_die_ref));
-static void output_die                 PARAMS ((dw_die_ref));
-static void output_compilation_unit_header PARAMS ((void));
-static void output_comp_unit           PARAMS ((dw_die_ref));
-static const char *dwarf2_name         PARAMS ((tree, int));
-static void add_pubname                        PARAMS ((tree, dw_die_ref));
-static void output_pubnames            PARAMS ((void));
-static void add_arange                 PARAMS ((tree, dw_die_ref));
-static void output_aranges             PARAMS ((void));
-static unsigned int add_ranges         PARAMS ((tree));
-static void output_ranges              PARAMS ((void));
-static void output_line_info           PARAMS ((void));
-static void output_file_names           PARAMS ((void));
-static dw_die_ref base_type_die                PARAMS ((tree));
-static tree root_type                  PARAMS ((tree));
-static int is_base_type                        PARAMS ((tree));
-static dw_die_ref modified_type_die    PARAMS ((tree, int, int, dw_die_ref));
-static int type_is_enum                        PARAMS ((tree));
-static unsigned int reg_number         PARAMS ((rtx));
-static dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx));
-static dw_loc_descr_ref int_loc_descriptor PARAMS ((HOST_WIDE_INT));
-static dw_loc_descr_ref based_loc_descr        PARAMS ((unsigned, long));
-static int is_based_loc                        PARAMS ((rtx));
-static dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode));
-static dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx));
-static dw_loc_descr_ref loc_descriptor PARAMS ((rtx));
-static dw_loc_descr_ref loc_descriptor_from_tree PARAMS ((tree, int));
-static HOST_WIDE_INT ceiling           PARAMS ((HOST_WIDE_INT, unsigned int));
-static tree field_type                 PARAMS ((tree));
-static unsigned int simple_type_align_in_bits PARAMS ((tree));
-static unsigned int simple_decl_align_in_bits PARAMS ((tree));
-static unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree));
-static HOST_WIDE_INT field_byte_offset PARAMS ((tree));
-static void add_AT_location_description        PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute, rtx));
-static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
-static void add_const_value_attribute  PARAMS ((dw_die_ref, rtx));
-static rtx rtl_for_decl_location       PARAMS ((tree));
-static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree));
-static void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree));
-static void add_name_attribute         PARAMS ((dw_die_ref, const char *));
-static void add_bound_info             PARAMS ((dw_die_ref,
-                                                enum dwarf_attribute, tree));
-static void add_subscript_info         PARAMS ((dw_die_ref, tree));
-static void add_byte_size_attribute    PARAMS ((dw_die_ref, tree));
-static void add_bit_offset_attribute   PARAMS ((dw_die_ref, tree));
-static void add_bit_size_attribute     PARAMS ((dw_die_ref, tree));
-static void add_prototyped_attribute   PARAMS ((dw_die_ref, tree));
-static void add_abstract_origin_attribute PARAMS ((dw_die_ref, tree));
-static void add_pure_or_virtual_attribute PARAMS ((dw_die_ref, tree));
-static void add_src_coords_attributes  PARAMS ((dw_die_ref, tree));
-static void add_name_and_src_coords_attributes PARAMS ((dw_die_ref, tree));
-static void push_decl_scope            PARAMS ((tree));
-static void pop_decl_scope             PARAMS ((void));
-static dw_die_ref scope_die_for                PARAMS ((tree, dw_die_ref));
-static inline int local_scope_p                PARAMS ((dw_die_ref));
-static inline int class_scope_p                PARAMS ((dw_die_ref));
-static void add_type_attribute         PARAMS ((dw_die_ref, tree, int, int,
-                                                dw_die_ref));
-static const char *type_tag            PARAMS ((tree));
-static tree member_declared_type       PARAMS ((tree));
+static tree decl_ultimate_origin (tree);
+static tree block_ultimate_origin (tree);
+static tree decl_class_context (tree);
+static void add_dwarf_attr (dw_die_ref, dw_attr_ref);
+static inline enum dw_val_class AT_class (dw_attr_ref);
+static void add_AT_flag (dw_die_ref, enum dwarf_attribute, unsigned);
+static inline unsigned AT_flag (dw_attr_ref);
+static void add_AT_int (dw_die_ref, enum dwarf_attribute, long);
+static inline long int AT_int (dw_attr_ref);
+static void add_AT_unsigned (dw_die_ref, enum dwarf_attribute, unsigned long);
+static inline unsigned long AT_unsigned (dw_attr_ref);
+static void add_AT_long_long (dw_die_ref, enum dwarf_attribute, unsigned long,
+                             unsigned long);
+static void add_AT_float (dw_die_ref, enum dwarf_attribute, unsigned, long *);
+static hashval_t debug_str_do_hash (const void *);
+static int debug_str_eq (const void *, const void *);
+static void add_AT_string (dw_die_ref, enum dwarf_attribute, const char *);
+static inline const char *AT_string (dw_attr_ref);
+static int AT_string_form (dw_attr_ref);
+static void add_AT_die_ref (dw_die_ref, enum dwarf_attribute, dw_die_ref);
+static inline dw_die_ref AT_ref (dw_attr_ref);
+static inline int AT_ref_external (dw_attr_ref);
+static inline void set_AT_ref_external (dw_attr_ref, int);
+static void add_AT_fde_ref (dw_die_ref, enum dwarf_attribute, unsigned);
+static void add_AT_loc (dw_die_ref, enum dwarf_attribute, dw_loc_descr_ref);
+static inline dw_loc_descr_ref AT_loc (dw_attr_ref);
+static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute,
+                            dw_loc_list_ref);
+static inline dw_loc_list_ref AT_loc_list (dw_attr_ref);
+static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx);
+static inline rtx AT_addr (dw_attr_ref);
+static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *);
+static void add_AT_lbl_offset (dw_die_ref, enum dwarf_attribute, const char *);
+static void add_AT_offset (dw_die_ref, enum dwarf_attribute, unsigned long);
+static void add_AT_range_list (dw_die_ref, enum dwarf_attribute,
+                              unsigned long);
+static inline const char *AT_lbl (dw_attr_ref);
+static dw_attr_ref get_AT (dw_die_ref, enum dwarf_attribute);
+static const char *get_AT_low_pc (dw_die_ref);
+static const char *get_AT_hi_pc (dw_die_ref);
+static const char *get_AT_string (dw_die_ref, enum dwarf_attribute);
+static int get_AT_flag (dw_die_ref, enum dwarf_attribute);
+static unsigned get_AT_unsigned (dw_die_ref, enum dwarf_attribute);
+static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
+static bool is_c_family (void);
+static bool is_cxx (void);
+static bool is_java (void);
+static bool is_fortran (void);
+static bool is_ada (void);
+static void remove_AT (dw_die_ref, enum dwarf_attribute);
+static inline void free_die (dw_die_ref);
+static void remove_children (dw_die_ref);
+static void add_child_die (dw_die_ref, dw_die_ref);
+static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
+static dw_die_ref lookup_type_die (tree);
+static void equate_type_number_to_die (tree, dw_die_ref);
+static dw_die_ref lookup_decl_die (tree);
+static void equate_decl_number_to_die (tree, dw_die_ref);
+static void print_spaces (FILE *);
+static void print_die (dw_die_ref, FILE *);
+static void print_dwarf_line_table (FILE *);
+static void reverse_die_lists (dw_die_ref);
+static void reverse_all_dies (dw_die_ref);
+static dw_die_ref push_new_compile_unit (dw_die_ref, dw_die_ref);
+static dw_die_ref pop_compile_unit (dw_die_ref);
+static void loc_checksum (dw_loc_descr_ref, struct md5_ctx *);
+static void attr_checksum (dw_attr_ref, struct md5_ctx *, int *);
+static void die_checksum (dw_die_ref, struct md5_ctx *, int *);
+static int same_loc_p (dw_loc_descr_ref, dw_loc_descr_ref, int *);
+static int same_dw_val_p (dw_val_node *, dw_val_node *, int *);
+static int same_attr_p (dw_attr_ref, dw_attr_ref, int *);
+static int same_die_p (dw_die_ref, dw_die_ref, int *);
+static int same_die_p_wrap (dw_die_ref, dw_die_ref);
+static void compute_section_prefix (dw_die_ref);
+static int is_type_die (dw_die_ref);
+static int is_comdat_die (dw_die_ref);
+static int is_symbol_die (dw_die_ref);
+static void assign_symbol_names (dw_die_ref);
+static void break_out_includes (dw_die_ref);
+static hashval_t htab_cu_hash (const void *);
+static int htab_cu_eq (const void *, const void *);
+static void htab_cu_del (void *);
+static int check_duplicate_cu (dw_die_ref, htab_t, unsigned *);
+static void record_comdat_symbol_number (dw_die_ref, htab_t, unsigned);
+static void add_sibling_attributes (dw_die_ref);
+static void build_abbrev_table (dw_die_ref);
+static void output_location_lists (dw_die_ref);
+static int constant_size (long unsigned);
+static unsigned long size_of_die (dw_die_ref);
+static void calc_die_sizes (dw_die_ref);
+static void mark_dies (dw_die_ref);
+static void unmark_dies (dw_die_ref);
+static void unmark_all_dies (dw_die_ref);
+static unsigned long size_of_pubnames (void);
+static unsigned long size_of_aranges (void);
+static enum dwarf_form value_format (dw_attr_ref);
+static void output_value_format (dw_attr_ref);
+static void output_abbrev_section (void);
+static void output_die_symbol (dw_die_ref);
+static void output_die (dw_die_ref);
+static void output_compilation_unit_header (void);
+static void output_comp_unit (dw_die_ref, int);
+static const char *dwarf2_name (tree, int);
+static void add_pubname (tree, dw_die_ref);
+static void output_pubnames (void);
+static void add_arange (tree, dw_die_ref);
+static void output_aranges (void);
+static unsigned int add_ranges (tree);
+static void output_ranges (void);
+static void output_line_info (void);
+static void output_file_names (void);
+static dw_die_ref base_type_die (tree);
+static tree root_type (tree);
+static int is_base_type (tree);
+static bool is_ada_subrange_type (tree);
+static dw_die_ref subrange_type_die (tree);
+static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
+static int type_is_enum (tree);
+static unsigned int reg_number (rtx);
+static dw_loc_descr_ref reg_loc_descriptor (rtx);
+static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int);
+static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx);
+static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
+static dw_loc_descr_ref based_loc_descr (unsigned, long);
+static int is_based_loc (rtx);
+static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode);
+static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx);
+static dw_loc_descr_ref loc_descriptor (rtx);
+static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
+static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
+static tree field_type (tree);
+static unsigned int simple_type_align_in_bits (tree);
+static unsigned int simple_decl_align_in_bits (tree);
+static unsigned HOST_WIDE_INT simple_type_size_in_bits (tree);
+static HOST_WIDE_INT field_byte_offset (tree);
+static void add_AT_location_description        (dw_die_ref, enum dwarf_attribute,
+                                        dw_loc_descr_ref);
+static void add_data_member_location_attribute (dw_die_ref, tree);
+static void add_const_value_attribute (dw_die_ref, rtx);
+static rtx rtl_for_decl_location (tree);
+static void add_location_or_const_value_attribute (dw_die_ref, tree);
+static void tree_add_const_value_attribute (dw_die_ref, tree);
+static void add_name_attribute (dw_die_ref, const char *);
+static void add_comp_dir_attribute (dw_die_ref);
+static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
+static void add_subscript_info (dw_die_ref, tree);
+static void add_byte_size_attribute (dw_die_ref, tree);
+static void add_bit_offset_attribute (dw_die_ref, tree);
+static void add_bit_size_attribute (dw_die_ref, tree);
+static void add_prototyped_attribute (dw_die_ref, tree);
+static void add_abstract_origin_attribute (dw_die_ref, tree);
+static void add_pure_or_virtual_attribute (dw_die_ref, tree);
+static void add_src_coords_attributes (dw_die_ref, tree);
+static void add_name_and_src_coords_attributes (dw_die_ref, tree);
+static void push_decl_scope (tree);
+static void pop_decl_scope (void);
+static dw_die_ref scope_die_for (tree, dw_die_ref);
+static inline int local_scope_p (dw_die_ref);
+static inline int class_scope_p (dw_die_ref);
+static void add_type_attribute (dw_die_ref, tree, int, int, dw_die_ref);
+static const char *type_tag (tree);
+static tree member_declared_type (tree);
 #if 0
-static const char *decl_start_label    PARAMS ((tree));
+static const char *decl_start_label (tree);
 #endif
-static void gen_array_type_die         PARAMS ((tree, dw_die_ref));
-static void gen_set_type_die           PARAMS ((tree, dw_die_ref));
+static void gen_array_type_die (tree, dw_die_ref);
+static void gen_set_type_die (tree, dw_die_ref);
 #if 0
-static void gen_entry_point_die                PARAMS ((tree, dw_die_ref));
+static void gen_entry_point_die (tree, dw_die_ref);
 #endif
-static void gen_inlined_enumeration_type_die PARAMS ((tree, dw_die_ref));
-static void gen_inlined_structure_type_die PARAMS ((tree, dw_die_ref));
-static void gen_inlined_union_type_die PARAMS ((tree, dw_die_ref));
-static void gen_enumeration_type_die   PARAMS ((tree, dw_die_ref));
-static dw_die_ref gen_formal_parameter_die PARAMS ((tree, dw_die_ref));
-static void gen_unspecified_parameters_die PARAMS ((tree, dw_die_ref));
-static void gen_formal_types_die       PARAMS ((tree, dw_die_ref));
-static void gen_subprogram_die         PARAMS ((tree, dw_die_ref));
-static void gen_variable_die           PARAMS ((tree, dw_die_ref));
-static void gen_label_die              PARAMS ((tree, dw_die_ref));
-static void gen_lexical_block_die      PARAMS ((tree, dw_die_ref, int));
-static void gen_inlined_subroutine_die PARAMS ((tree, dw_die_ref, int));
-static void gen_field_die              PARAMS ((tree, dw_die_ref));
-static void gen_ptr_to_mbr_type_die    PARAMS ((tree, dw_die_ref));
-static dw_die_ref gen_compile_unit_die PARAMS ((const char *));
-static void gen_string_type_die                PARAMS ((tree, dw_die_ref));
-static void gen_inheritance_die                PARAMS ((tree, dw_die_ref));
-static void gen_member_die             PARAMS ((tree, dw_die_ref));
-static void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref));
-static void gen_subroutine_type_die    PARAMS ((tree, dw_die_ref));
-static void gen_typedef_die            PARAMS ((tree, dw_die_ref));
-static void gen_type_die               PARAMS ((tree, dw_die_ref));
-static void gen_tagged_type_instantiation_die PARAMS ((tree, dw_die_ref));
-static void gen_block_die              PARAMS ((tree, dw_die_ref, int));
-static void decls_for_scope            PARAMS ((tree, dw_die_ref, int));
-static int is_redundant_typedef                PARAMS ((tree));
-static void gen_decl_die               PARAMS ((tree, dw_die_ref));
-static unsigned lookup_filename                PARAMS ((const char *));
-static void init_file_table            PARAMS ((void));
-static void retry_incomplete_types     PARAMS ((void));
-static void gen_type_die_for_member    PARAMS ((tree, tree, dw_die_ref));
-static void splice_child_die           PARAMS ((dw_die_ref, dw_die_ref));
-static int file_info_cmp               PARAMS ((const void *, const void *));
-static dw_loc_list_ref new_loc_list     PARAMS ((dw_loc_descr_ref,
-                                                const char *, const char *,
-                                                const char *, unsigned));
-static void add_loc_descr_to_loc_list   PARAMS ((dw_loc_list_ref *,
-                                                dw_loc_descr_ref,
-                                                const char *, const char *, const char *));
-static void output_loc_list            PARAMS ((dw_loc_list_ref));
-static char *gen_internal_sym          PARAMS ((const char *));
-static void mark_limbo_die_list                PARAMS ((void *));
+static void gen_inlined_enumeration_type_die (tree, dw_die_ref);
+static void gen_inlined_structure_type_die (tree, dw_die_ref);
+static void gen_inlined_union_type_die (tree, dw_die_ref);
+static void gen_enumeration_type_die (tree, dw_die_ref);
+static dw_die_ref gen_formal_parameter_die (tree, dw_die_ref);
+static void gen_unspecified_parameters_die (tree, dw_die_ref);
+static void gen_formal_types_die (tree, dw_die_ref);
+static void gen_subprogram_die (tree, dw_die_ref);
+static void gen_variable_die (tree, dw_die_ref);
+static void gen_label_die (tree, dw_die_ref);
+static void gen_lexical_block_die (tree, dw_die_ref, int);
+static void gen_inlined_subroutine_die (tree, dw_die_ref, int);
+static void gen_field_die (tree, dw_die_ref);
+static void gen_ptr_to_mbr_type_die (tree, dw_die_ref);
+static dw_die_ref gen_compile_unit_die (const char *);
+static void gen_string_type_die (tree, dw_die_ref);
+static void gen_inheritance_die (tree, tree, dw_die_ref);
+static void gen_member_die (tree, dw_die_ref);
+static void gen_struct_or_union_type_die (tree, dw_die_ref);
+static void gen_subroutine_type_die (tree, dw_die_ref);
+static void gen_typedef_die (tree, dw_die_ref);
+static void gen_type_die (tree, dw_die_ref);
+static void gen_tagged_type_instantiation_die (tree, dw_die_ref);
+static void gen_block_die (tree, dw_die_ref, int);
+static void decls_for_scope (tree, dw_die_ref, int);
+static int is_redundant_typedef (tree);
+static void gen_decl_die (tree, dw_die_ref);
+static unsigned lookup_filename (const char *);
+static void init_file_table (void);
+static void retry_incomplete_types (void);
+static void gen_type_die_for_member (tree, tree, dw_die_ref);
+static void splice_child_die (dw_die_ref, dw_die_ref);
+static int file_info_cmp (const void *, const void *);
+static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *,
+                                    const char *, const char *, unsigned);
+static void add_loc_descr_to_loc_list (dw_loc_list_ref *, dw_loc_descr_ref,
+                                      const char *, const char *,
+                                      const char *);
+static void output_loc_list (dw_loc_list_ref);
+static char *gen_internal_sym (const char *);
+
+static void prune_unmark_dies (dw_die_ref);
+static void prune_unused_types_mark (dw_die_ref, int);
+static void prune_unused_types_walk (dw_die_ref);
+static void prune_unused_types_walk_attribs (dw_die_ref);
+static void prune_unused_types_prune (dw_die_ref);
+static void prune_unused_types (void);
+static int maybe_emit_file (int);
 
 /* Section names used to hold DWARF debugging information.  */
 #ifndef DEBUG_INFO_SECTION
@@ -3734,7 +3816,9 @@ static void mark_limbo_die_list           PARAMS ((void *));
 /* Section flags for .debug_str section.  */
 #ifdef HAVE_GAS_SHF_MERGE
 #define DEBUG_STR_SECTION_FLAGS \
-  (SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1)
+  (flag_merge_constants                                                \
+   ? SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1       \
+   : SECTION_DEBUG)
 #else
 #define DEBUG_STR_SECTION_FLAGS        SECTION_DEBUG
 #endif
@@ -3782,24 +3866,12 @@ static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
 #ifndef TEXT_END_LABEL
 #define TEXT_END_LABEL         "Letext"
 #endif
-#ifndef DATA_END_LABEL
-#define DATA_END_LABEL         "Ledata"
-#endif
-#ifndef BSS_END_LABEL
-#define BSS_END_LABEL           "Lebss"
-#endif
 #ifndef BLOCK_BEGIN_LABEL
 #define BLOCK_BEGIN_LABEL      "LBB"
 #endif
 #ifndef BLOCK_END_LABEL
 #define BLOCK_END_LABEL                "LBE"
 #endif
-#ifndef BODY_BEGIN_LABEL
-#define BODY_BEGIN_LABEL       "Lbb"
-#endif
-#ifndef BODY_END_LABEL
-#define BODY_END_LABEL         "Lbe"
-#endif
 #ifndef LINE_CODE_LABEL
 #define LINE_CODE_LABEL                "LM"
 #endif
@@ -3810,11 +3882,10 @@ static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
 /* We allow a language front-end to designate a function that is to be
    called to "demangle" any name before it it put into a DIE.  */
 
-static const char *(*demangle_name_func) PARAMS ((const char *));
+static const char *(*demangle_name_func) (const char *);
 
 void
-dwarf2out_set_demangle_name_func (func)
-     const char *(*func) PARAMS ((const char *));
+dwarf2out_set_demangle_name_func (const char *(*func) (const char *))
 {
   demangle_name_func = func;
 }
@@ -3822,8 +3893,7 @@ dwarf2out_set_demangle_name_func (func)
 /* Test if rtl node points to a pseudo register.  */
 
 static inline int
-is_pseudo_reg (rtl)
-     rtx rtl;
+is_pseudo_reg (rtx rtl)
 {
   return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
          || (GET_CODE (rtl) == SUBREG
@@ -3834,8 +3904,7 @@ is_pseudo_reg (rtl)
    removed.  */
 
 static inline tree
-type_main_variant (type)
-     tree type;
+type_main_variant (tree type)
 {
   type = TYPE_MAIN_VARIANT (type);
 
@@ -3851,11 +3920,10 @@ type_main_variant (type)
   return type;
 }
 
-/* Return non-zero if the given type node represents a tagged type.  */
+/* Return nonzero if the given type node represents a tagged type.  */
 
 static inline int
-is_tagged_type (type)
-     tree type;
+is_tagged_type (tree type)
 {
   enum tree_code code = TREE_CODE (type);
 
@@ -3866,8 +3934,7 @@ is_tagged_type (type)
 /* Convert a DIE tag into its string name.  */
 
 static const char *
-dwarf_tag_name (tag)
-     unsigned tag;
+dwarf_tag_name (unsigned int tag)
 {
   switch (tag)
     {
@@ -3987,8 +4054,7 @@ dwarf_tag_name (tag)
 /* Convert a DWARF attribute code into its string name.  */
 
 static const char *
-dwarf_attr_name (attr)
-     unsigned attr;
+dwarf_attr_name (unsigned int attr)
 {
   switch (attr)
     {
@@ -4191,8 +4257,7 @@ dwarf_attr_name (attr)
 /* Convert a DWARF value form code into its string name.  */
 
 static const char *
-dwarf_form_name (form)
-     unsigned form;
+dwarf_form_name (unsigned int form)
 {
   switch (form)
     {
@@ -4247,8 +4312,7 @@ dwarf_form_name (form)
 
 #if 0
 static const char *
-dwarf_type_encoding_name (enc)
-     unsigned enc;
+dwarf_type_encoding_name (unsigned enc)
 {
   switch (enc)
     {
@@ -4281,8 +4345,7 @@ dwarf_type_encoding_name (enc)
    given block.  */
 
 static tree
-decl_ultimate_origin (decl)
-     tree decl;
+decl_ultimate_origin (tree decl)
 {
   /* output_inline_function sets DECL_ABSTRACT_ORIGIN for all the
      nodes in the function to point to themselves; ignore that if
@@ -4307,8 +4370,7 @@ decl_ultimate_origin (decl)
    given block.  */
 
 static tree
-block_ultimate_origin (block)
-     tree block;
+block_ultimate_origin (tree block)
 {
   tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
 
@@ -4342,8 +4404,7 @@ block_ultimate_origin (block)
    parameter.  */
 
 static tree
-decl_class_context (decl)
-     tree decl;
+decl_class_context (tree decl)
 {
   tree context = NULL_TREE;
 
@@ -4363,9 +4424,7 @@ decl_class_context (decl)
    addition order, and correct that in reverse_all_dies.  */
 
 static inline void
-add_dwarf_attr (die, attr)
-     dw_die_ref die;
-     dw_attr_ref attr;
+add_dwarf_attr (dw_die_ref die, dw_attr_ref attr)
 {
   if (die != NULL && attr != NULL)
     {
@@ -4374,9 +4433,8 @@ add_dwarf_attr (die, attr)
     }
 }
 
-static inline dw_val_class
-AT_class (a)
-     dw_attr_ref a;
+static inline enum dw_val_class
+AT_class (dw_attr_ref a)
 {
   return a->dw_attr_val.val_class;
 }
@@ -4384,12 +4442,9 @@ AT_class (a)
 /* Add a flag value attribute to a DIE.  */
 
 static inline void
-add_AT_flag (die, attr_kind, flag)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     unsigned flag;
+add_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int flag)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4399,8 +4454,7 @@ add_AT_flag (die, attr_kind, flag)
 }
 
 static inline unsigned
-AT_flag (a)
-     dw_attr_ref a;
+AT_flag (dw_attr_ref a)
 {
   if (a && AT_class (a) == dw_val_class_flag)
     return a->dw_attr_val.v.val_flag;
@@ -4411,12 +4465,9 @@ AT_flag (a)
 /* Add a signed integer attribute value to a DIE.  */
 
 static inline void
-add_AT_int (die, attr_kind, int_val)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     long int int_val;
+add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, long int int_val)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4426,8 +4477,7 @@ add_AT_int (die, attr_kind, int_val)
 }
 
 static inline long int
-AT_int (a)
-     dw_attr_ref a;
+AT_int (dw_attr_ref a)
 {
   if (a && AT_class (a) == dw_val_class_const)
     return a->dw_attr_val.v.val_int;
@@ -4438,12 +4488,10 @@ AT_int (a)
 /* Add an unsigned integer attribute value to a DIE.  */
 
 static inline void
-add_AT_unsigned (die, attr_kind, unsigned_val)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     unsigned long unsigned_val;
+add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind,
+                long unsigned int unsigned_val)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4453,8 +4501,7 @@ add_AT_unsigned (die, attr_kind, unsigned_val)
 }
 
 static inline unsigned long
-AT_unsigned (a)
-     dw_attr_ref a;
+AT_unsigned (dw_attr_ref a)
 {
   if (a && AT_class (a) == dw_val_class_unsigned_const)
     return a->dw_attr_val.v.val_unsigned;
@@ -4465,13 +4512,10 @@ AT_unsigned (a)
 /* Add an unsigned double integer attribute value to a DIE.  */
 
 static inline void
-add_AT_long_long (die, attr_kind, val_hi, val_low)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     unsigned long val_hi;
-     unsigned long val_low;
+add_AT_long_long (dw_die_ref die, enum dwarf_attribute attr_kind,
+                 long unsigned int val_hi, long unsigned int val_low)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4484,13 +4528,10 @@ add_AT_long_long (die, attr_kind, val_hi, val_low)
 /* Add a floating point attribute value to a DIE and return it.  */
 
 static inline void
-add_AT_float (die, attr_kind, length, array)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     unsigned length;
-     long *array;
+add_AT_float (dw_die_ref die, enum dwarf_attribute attr_kind,
+             unsigned int length, long int *array)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4500,26 +4541,40 @@ add_AT_float (die, attr_kind, length, array)
   add_dwarf_attr (die, attr);
 }
 
+/* Hash and equality functions for debug_str_hash.  */
+
+static hashval_t
+debug_str_do_hash (const void *x)
+{
+  return htab_hash_string (((const struct indirect_string_node *)x)->str);
+}
+
+static int
+debug_str_eq (const void *x1, const void *x2)
+{
+  return strcmp ((((const struct indirect_string_node *)x1)->str),
+                (const char *)x2) == 0;
+}
+
 /* Add a string attribute value to a DIE.  */
 
 static inline void
-add_AT_string (die, attr_kind, str)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     const char *str;
+add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
   struct indirect_string_node *node;
+  void **slot;
 
   if (! debug_str_hash)
-    {
-      debug_str_hash = ht_create (10);
-      debug_str_hash->alloc_node = indirect_string_alloc;
-    }
-
-  node = (struct indirect_string_node *)
-        ht_lookup (debug_str_hash, (const unsigned char *) str,
-                   strlen (str), HT_ALLOC);
+    debug_str_hash = htab_create_ggc (10, debug_str_do_hash,
+                                     debug_str_eq, NULL);
+
+  slot = htab_find_slot_with_hash (debug_str_hash, str,
+                                  htab_hash_string (str), INSERT);
+  if (*slot == NULL)
+    *slot = ggc_alloc_cleared (sizeof (struct indirect_string_node));
+  node = (struct indirect_string_node *) *slot;
+  node->str = ggc_strdup (str);
   node->refcount++;
 
   attr->dw_attr_next = NULL;
@@ -4530,11 +4585,10 @@ add_AT_string (die, attr_kind, str)
 }
 
 static inline const char *
-AT_string (a)
-     dw_attr_ref a;
+AT_string (dw_attr_ref a)
 {
   if (a && AT_class (a) == dw_val_class_str)
-    return (const char *) HT_STR (&a->dw_attr_val.v.val_str->id);
+    return a->dw_attr_val.v.val_str->str;
 
   abort ();
 }
@@ -4543,21 +4597,19 @@ AT_string (a)
    or out-of-line in .debug_str section.  */
 
 static int
-AT_string_form (a)
-     dw_attr_ref a;
+AT_string_form (dw_attr_ref a)
 {
   if (a && AT_class (a) == dw_val_class_str)
     {
       struct indirect_string_node *node;
       unsigned int len;
-      extern int const_labelno;
       char label[32];
 
       node = a->dw_attr_val.v.val_str;
       if (node->form)
        return node->form;
 
-      len = HT_LEN (&node->id) + 1;
+      len = strlen (node->str) + 1;
 
       /* If the string is shorter or equal to the size of the reference, it is
         always better to put it inline.  */
@@ -4571,8 +4623,8 @@ AT_string_form (a)
          && (len - DWARF_OFFSET_SIZE) * node->refcount <= len)
        return node->form = DW_FORM_string;
 
-      ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
-      ++const_labelno;
+      ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
+      ++dw2_string_counter;
       node->label = xstrdup (label);
 
       return node->form = DW_FORM_strp;
@@ -4584,12 +4636,9 @@ AT_string_form (a)
 /* Add a DIE reference attribute value to a DIE.  */
 
 static inline void
-add_AT_die_ref (die, attr_kind, targ_die)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     dw_die_ref targ_die;
+add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_die)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4600,8 +4649,7 @@ add_AT_die_ref (die, attr_kind, targ_die)
 }
 
 static inline dw_die_ref
-AT_ref (a)
-     dw_attr_ref a;
+AT_ref (dw_attr_ref a)
 {
   if (a && AT_class (a) == dw_val_class_die_ref)
     return a->dw_attr_val.v.val_die_ref.die;
@@ -4610,8 +4658,7 @@ AT_ref (a)
 }
 
 static inline int
-AT_ref_external (a)
-     dw_attr_ref a;
+AT_ref_external (dw_attr_ref a)
 {
   if (a && AT_class (a) == dw_val_class_die_ref)
     return a->dw_attr_val.v.val_die_ref.external;
@@ -4620,9 +4667,7 @@ AT_ref_external (a)
 }
 
 static inline void
-set_AT_ref_external (a, i)
-     dw_attr_ref a;
-     int i;
+set_AT_ref_external (dw_attr_ref a, int i)
 {
   if (a && AT_class (a) == dw_val_class_die_ref)
     a->dw_attr_val.v.val_die_ref.external = i;
@@ -4633,12 +4678,9 @@ set_AT_ref_external (a, i)
 /* Add an FDE reference attribute value to a DIE.  */
 
 static inline void
-add_AT_fde_ref (die, attr_kind, targ_fde)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     unsigned targ_fde;
+add_AT_fde_ref (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int targ_fde)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4650,12 +4692,9 @@ add_AT_fde_ref (die, attr_kind, targ_fde)
 /* Add a location description attribute value to a DIE.  */
 
 static inline void
-add_AT_loc (die, attr_kind, loc)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     dw_loc_descr_ref loc;
+add_AT_loc (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_descr_ref loc)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4665,8 +4704,7 @@ add_AT_loc (die, attr_kind, loc)
 }
 
 static inline dw_loc_descr_ref
-AT_loc (a)
-     dw_attr_ref a;
+AT_loc (dw_attr_ref a)
 {
   if (a && AT_class (a) == dw_val_class_loc)
     return a->dw_attr_val.v.val_loc;
@@ -4675,12 +4713,9 @@ AT_loc (a)
 }
 
 static inline void
-add_AT_loc_list (die, attr_kind, loc_list)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     dw_loc_list_ref loc_list;
+add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref loc_list)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4691,8 +4726,7 @@ add_AT_loc_list (die, attr_kind, loc_list)
 }
 
 static inline dw_loc_list_ref
-AT_loc_list (a)
-     dw_attr_ref a;
+AT_loc_list (dw_attr_ref a)
 {
   if (a && AT_class (a) == dw_val_class_loc_list)
     return a->dw_attr_val.v.val_loc_list;
@@ -4703,12 +4737,9 @@ AT_loc_list (a)
 /* Add an address constant attribute value to a DIE.  */
 
 static inline void
-add_AT_addr (die, attr_kind, addr)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     rtx addr;
+add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4718,8 +4749,7 @@ add_AT_addr (die, attr_kind, addr)
 }
 
 static inline rtx
-AT_addr (a)
-     dw_attr_ref a;
+AT_addr (dw_attr_ref a)
 {
   if (a && AT_class (a) == dw_val_class_addr)
     return a->dw_attr_val.v.val_addr;
@@ -4730,12 +4760,9 @@ AT_addr (a)
 /* Add a label identifier attribute value to a DIE.  */
 
 static inline void
-add_AT_lbl_id (die, attr_kind, lbl_id)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     const char *lbl_id;
+add_AT_lbl_id (dw_die_ref die, enum dwarf_attribute attr_kind, const char *lbl_id)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4747,12 +4774,9 @@ add_AT_lbl_id (die, attr_kind, lbl_id)
 /* Add a section offset attribute value to a DIE.  */
 
 static inline void
-add_AT_lbl_offset (die, attr_kind, label)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     const char *label;
+add_AT_lbl_offset (dw_die_ref die, enum dwarf_attribute attr_kind, const char *label)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4764,12 +4788,9 @@ add_AT_lbl_offset (die, attr_kind, label)
 /* Add an offset attribute value to a DIE.  */
 
 static inline void
-add_AT_offset (die, attr_kind, offset)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     unsigned long offset;
+add_AT_offset (dw_die_ref die, enum dwarf_attribute attr_kind, long unsigned int offset)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4781,12 +4802,10 @@ add_AT_offset (die, attr_kind, offset)
 /* Add an range_list attribute value to a DIE.  */
 
 static void
-add_AT_range_list (die, attr_kind, offset)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     unsigned long offset;
+add_AT_range_list (dw_die_ref die, enum dwarf_attribute attr_kind,
+                  long unsigned int offset)
 {
-  dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+  dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node));
 
   attr->dw_attr_next = NULL;
   attr->dw_attr = attr_kind;
@@ -4796,8 +4815,7 @@ add_AT_range_list (die, attr_kind, offset)
 }
 
 static inline const char *
-AT_lbl (a)
-     dw_attr_ref a;
+AT_lbl (dw_attr_ref a)
 {
   if (a && (AT_class (a) == dw_val_class_lbl_id
            || AT_class (a) == dw_val_class_lbl_offset))
@@ -4809,9 +4827,7 @@ AT_lbl (a)
 /* Get the attribute of type attr_kind.  */
 
 static inline dw_attr_ref
-get_AT (die, attr_kind)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
+get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
   dw_attr_ref a;
   dw_die_ref spec = NULL;
@@ -4837,8 +4853,7 @@ get_AT (die, attr_kind)
    cannot be represented as an assembler label identifier.  */
 
 static inline const char *
-get_AT_low_pc (die)
-     dw_die_ref die;
+get_AT_low_pc (dw_die_ref die)
 {
   dw_attr_ref a = get_AT (die, DW_AT_low_pc);
 
@@ -4850,8 +4865,7 @@ get_AT_low_pc (die)
    cannot be represented as an assembler label identifier.  */
 
 static inline const char *
-get_AT_hi_pc (die)
-     dw_die_ref die;
+get_AT_hi_pc (dw_die_ref die)
 {
   dw_attr_ref a = get_AT (die, DW_AT_high_pc);
 
@@ -4862,9 +4876,7 @@ get_AT_hi_pc (die)
    NULL if it is not present.  */
 
 static inline const char *
-get_AT_string (die, attr_kind)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
+get_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
   dw_attr_ref a = get_AT (die, attr_kind);
 
@@ -4875,9 +4887,7 @@ get_AT_string (die, attr_kind)
    if it is not present.  */
 
 static inline int
-get_AT_flag (die, attr_kind)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
+get_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
   dw_attr_ref a = get_AT (die, attr_kind);
 
@@ -4888,9 +4898,7 @@ get_AT_flag (die, attr_kind)
    if it is not present.  */
 
 static inline unsigned
-get_AT_unsigned (die, attr_kind)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
+get_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
   dw_attr_ref a = get_AT (die, attr_kind);
 
@@ -4898,83 +4906,78 @@ get_AT_unsigned (die, attr_kind)
 }
 
 static inline dw_die_ref
-get_AT_ref (die, attr_kind)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
+get_AT_ref (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
   dw_attr_ref a = get_AT (die, attr_kind);
 
   return a ? AT_ref (a) : NULL;
 }
 
-static inline int
-is_c_family ()
+/* Return TRUE if the language is C or C++.  */
+
+static inline bool
+is_c_family (void)
 {
-  unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
+  unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
 
   return (lang == DW_LANG_C || lang == DW_LANG_C89
          || lang == DW_LANG_C_plus_plus);
 }
 
-static inline int
-is_cxx ()
+/* Return TRUE if the language is C++.  */
+
+static inline bool
+is_cxx (void)
 {
   return (get_AT_unsigned (comp_unit_die, DW_AT_language)
          == DW_LANG_C_plus_plus);
 }
 
-static inline int
-is_fortran ()
+/* Return TRUE if the language is Fortran.  */
+
+static inline bool
+is_fortran (void)
 {
-  unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
+  unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
 
-  return (lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90);
+  return lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90;
 }
 
-static inline int
-is_java ()
+/* Return TRUE if the language is Java.  */
+
+static inline bool
+is_java (void)
 {
-  unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
+  unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
 
-  return (lang == DW_LANG_Java);
+  return lang == DW_LANG_Java;
 }
 
-/* Free up the memory used by A.  */
+/* Return TRUE if the language is Ada.  */
 
-static inline void free_AT PARAMS ((dw_attr_ref));
-static inline void
-free_AT (a)
-     dw_attr_ref a;
+static inline bool
+is_ada (void)
 {
-  switch (AT_class (a))
-    {
-    case dw_val_class_str:
-      if (a->dw_attr_val.v.val_str->refcount)
-       a->dw_attr_val.v.val_str->refcount--;
-      break;
+  unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
 
-    case dw_val_class_lbl_id:
-    case dw_val_class_lbl_offset:
-      free (a->dw_attr_val.v.val_lbl_id);
-      break;
-
-    case dw_val_class_float:
-      free (a->dw_attr_val.v.val_float.array);
-      break;
+  return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
+}
 
-    default:
-      break;
-    }
+/* Free up the memory used by A.  */
 
-  free (a);
+static inline void free_AT (dw_attr_ref);
+static inline void
+free_AT (dw_attr_ref a)
+{
+  if (AT_class (a) == dw_val_class_str)
+    if (a->dw_attr_val.v.val_str->refcount)
+      a->dw_attr_val.v.val_str->refcount--;
 }
 
 /* Remove the specified attribute if present.  */
 
 static void
-remove_AT (die, attr_kind)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
+remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
   dw_attr_ref *p;
   dw_attr_ref removed = NULL;
@@ -4997,18 +5000,15 @@ remove_AT (die, attr_kind)
 /* Free up the memory used by DIE.  */
 
 static inline void
-free_die (die)
-     dw_die_ref die;
+free_die (dw_die_ref die)
 {
   remove_children (die);
-  free (die);
 }
 
 /* Discard the children of this DIE.  */
 
 static void
-remove_children (die)
-     dw_die_ref die;
+remove_children (dw_die_ref die)
 {
   dw_die_ref child_die = die->die_child;
 
@@ -5037,9 +5037,7 @@ remove_children (die)
    addition order, and correct that in reverse_all_dies.  */
 
 static inline void
-add_child_die (die, child_die)
-     dw_die_ref die;
-     dw_die_ref child_die;
+add_child_die (dw_die_ref die, dw_die_ref child_die)
 {
   if (die != NULL && child_die != NULL)
     {
@@ -5056,8 +5054,7 @@ add_child_die (die, child_die)
    is the specification, to the front of PARENT's list of children.  */
 
 static void
-splice_child_die (parent, child)
-     dw_die_ref parent, child;
+splice_child_die (dw_die_ref parent, dw_die_ref child)
 {
   dw_die_ref *p;
 
@@ -5082,6 +5079,7 @@ splice_child_die (parent, child)
        break;
       }
 
+  child->die_parent = parent;
   child->die_sib = parent->die_child;
   parent->die_child = child;
 }
@@ -5089,12 +5087,9 @@ splice_child_die (parent, child)
 /* Return a pointer to a newly created DIE node.  */
 
 static inline dw_die_ref
-new_die (tag_value, parent_die, t)
-     enum dwarf_tag tag_value;
-     dw_die_ref parent_die;
-     tree t;
+new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
 {
-  dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node));
+  dw_die_ref die = (dw_die_ref) ggc_alloc_cleared (sizeof (die_node));
 
   die->die_tag = tag_value;
 
@@ -5104,7 +5099,7 @@ new_die (tag_value, parent_die, t)
     {
       limbo_die_node *limbo_node;
 
-      limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node));
+      limbo_node = ggc_alloc_cleared (sizeof (limbo_die_node));
       limbo_node->die = die;
       limbo_node->created_for = t;
       limbo_node->next = limbo_die_list;
@@ -5117,27 +5112,23 @@ new_die (tag_value, parent_die, t)
 /* Return the DIE associated with the given type specifier.  */
 
 static inline dw_die_ref
-lookup_type_die (type)
-     tree type;
+lookup_type_die (tree type)
 {
-  return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
+  return TYPE_SYMTAB_DIE (type);
 }
 
 /* Equate a DIE to a given type specifier.  */
 
 static inline void
-equate_type_number_to_die (type, type_die)
-     tree type;
-     dw_die_ref type_die;
+equate_type_number_to_die (tree type, dw_die_ref type_die)
 {
-  TYPE_SYMTAB_POINTER (type) = (char *) type_die;
+  TYPE_SYMTAB_DIE (type) = type_die;
 }
 
 /* Return the DIE associated with a given declaration.  */
 
 static inline dw_die_ref
-lookup_decl_die (decl)
-     tree decl;
+lookup_decl_die (tree decl)
 {
   unsigned decl_id = DECL_UID (decl);
 
@@ -5147,9 +5138,7 @@ lookup_decl_die (decl)
 /* Equate a DIE to a particular declaration.  */
 
 static void
-equate_decl_number_to_die (decl, decl_die)
-     tree decl;
-     dw_die_ref decl_die;
+equate_decl_number_to_die (tree decl, dw_die_ref decl_die)
 {
   unsigned int decl_id = DECL_UID (decl);
   unsigned int num_allocated;
@@ -5161,9 +5150,8 @@ equate_decl_number_to_die (decl, decl_die)
           / DECL_DIE_TABLE_INCREMENT)
          * DECL_DIE_TABLE_INCREMENT;
 
-      decl_die_table
-       = (dw_die_ref *) xrealloc (decl_die_table,
-                                  sizeof (dw_die_ref) * num_allocated);
+      decl_die_table = ggc_realloc (decl_die_table,
+                                   sizeof (dw_die_ref) * num_allocated);
 
       memset ((char *) &decl_die_table[decl_die_table_allocated], 0,
             (num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref));
@@ -5184,8 +5172,7 @@ static int print_indent;
 /* Indent the line the number of spaces given by print_indent.  */
 
 static inline void
-print_spaces (outfile)
-     FILE *outfile;
+print_spaces (FILE *outfile)
 {
   fprintf (outfile, "%*s", print_indent, "");
 }
@@ -5194,9 +5181,7 @@ print_spaces (outfile)
    This routine is a debugging aid only.  */
 
 static void
-print_die (die, outfile)
-     dw_die_ref die;
-     FILE *outfile;
+print_die (dw_die_ref die, FILE *outfile)
 {
   dw_attr_ref a;
   dw_die_ref c;
@@ -5292,8 +5277,7 @@ print_die (die, outfile)
    This routine is a debugging aid only.  */
 
 static void
-print_dwarf_line_table (outfile)
-     FILE *outfile;
+print_dwarf_line_table (FILE *outfile)
 {
   unsigned i;
   dw_line_info_ref line_info;
@@ -5303,7 +5287,8 @@ print_dwarf_line_table (outfile)
     {
       line_info = &line_info_table[i];
       fprintf (outfile, "%5d: ", i);
-      fprintf (outfile, "%-20s", file_table.table[line_info->dw_file_num]);
+      fprintf (outfile, "%-20s",
+              VARRAY_CHAR_PTR (file_table, line_info->dw_file_num));
       fprintf (outfile, "%6ld", line_info->dw_line_num);
       fprintf (outfile, "\n");
     }
@@ -5314,8 +5299,7 @@ print_dwarf_line_table (outfile)
 /* Print the information collected for a given DIE.  */
 
 void
-debug_dwarf_die (die)
-     dw_die_ref die;
+debug_dwarf_die (dw_die_ref die)
 {
   print_die (die, stderr);
 }
@@ -5324,7 +5308,7 @@ debug_dwarf_die (die)
    This routine is a debugging aid only.  */
 
 void
-debug_dwarf ()
+debug_dwarf (void)
 {
   print_indent = 0;
   print_die (comp_unit_die, stderr);
@@ -5337,8 +5321,7 @@ debug_dwarf ()
    they are in order of addition.  */
 
 static void
-reverse_die_lists (die)
-     dw_die_ref die;
+reverse_die_lists (dw_die_ref die)
 {
   dw_die_ref c, cp, cn;
   dw_attr_ref a, ap, an;
@@ -5369,8 +5352,7 @@ reverse_die_lists (die)
    recursively reverse all the dies. This is that routine.  */
 
 static void
-reverse_all_dies (die)
-     dw_die_ref die;
+reverse_all_dies (dw_die_ref die)
 {
   dw_die_ref c;
 
@@ -5385,8 +5367,7 @@ reverse_all_dies (die)
    DIE that marks the start of the DIEs for this include file.  */
 
 static dw_die_ref
-push_new_compile_unit (old_unit, bincl_die)
-     dw_die_ref old_unit, bincl_die;
+push_new_compile_unit (dw_die_ref old_unit, dw_die_ref bincl_die)
 {
   const char *filename = get_AT_string (bincl_die, DW_AT_name);
   dw_die_ref new_unit = gen_compile_unit_die (filename);
@@ -5398,8 +5379,7 @@ push_new_compile_unit (old_unit, bincl_die)
 /* Close an include-file CU and reopen the enclosing one.  */
 
 static dw_die_ref
-pop_compile_unit (old_unit)
-     dw_die_ref old_unit;
+pop_compile_unit (dw_die_ref old_unit)
 {
   dw_die_ref new_unit = old_unit->die_sib;
 
@@ -5413,9 +5393,7 @@ pop_compile_unit (old_unit)
 /* Calculate the checksum of a location expression.  */
 
 static inline void
-loc_checksum (loc, ctx)
-     dw_loc_descr_ref loc;
-     struct md5_ctx *ctx;
+loc_checksum (dw_loc_descr_ref loc, struct md5_ctx *ctx)
 {
   CHECKSUM (loc->dw_loc_opc);
   CHECKSUM (loc->dw_loc_oprnd1);
@@ -5425,9 +5403,7 @@ loc_checksum (loc, ctx)
 /* Calculate the checksum of an attribute.  */
 
 static void
-attr_checksum (at, ctx)
-     dw_attr_ref at;
-     struct md5_ctx *ctx;
+attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark)
 {
   dw_loc_descr_ref loc;
   rtx r;
@@ -5485,9 +5461,8 @@ attr_checksum (at, ctx)
       break;
 
     case dw_val_class_die_ref:
-      if (AT_ref (at)->die_offset)
-       CHECKSUM (AT_ref (at)->die_offset);
-      /* FIXME else use target die name or something.  */
+      die_checksum (AT_ref (at), ctx, mark);
+      break;
 
     case dw_val_class_fde_ref:
     case dw_val_class_lbl_id:
@@ -5502,72 +5477,225 @@ attr_checksum (at, ctx)
 /* Calculate the checksum of a DIE.  */
 
 static void
-die_checksum (die, ctx)
-     dw_die_ref die;
-     struct md5_ctx *ctx;
+die_checksum (dw_die_ref die, struct md5_ctx *ctx, int *mark)
 {
   dw_die_ref c;
   dw_attr_ref a;
 
+  /* To avoid infinite recursion.  */
+  if (die->die_mark)
+    {
+      CHECKSUM (die->die_mark);
+      return;
+    }
+  die->die_mark = ++(*mark);
+
   CHECKSUM (die->die_tag);
 
   for (a = die->die_attr; a; a = a->dw_attr_next)
-    attr_checksum (a, ctx);
+    attr_checksum (a, ctx, mark);
 
   for (c = die->die_child; c; c = c->die_sib)
-    die_checksum (c, ctx);
+    die_checksum (c, ctx, mark);
 }
 
 #undef CHECKSUM
 #undef CHECKSUM_STRING
 
-/* The prefix to attach to symbols on DIEs in the current comdat debug
-   info section.  */
-static char *comdat_symbol_id;
-
-/* The index of the current symbol within the current comdat CU.  */
-static unsigned int comdat_symbol_number;
-
-/* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its
-   children, and set comdat_symbol_id accordingly.  */
-
-static void
-compute_section_prefix (unit_die)
-     dw_die_ref unit_die;
+/* Do the location expressions look same?  */
+static inline int
+same_loc_p (dw_loc_descr_ref loc1, dw_loc_descr_ref loc2, int *mark)
 {
-  const char *base = lbasename (get_AT_string (unit_die, DW_AT_name));
-  char *name = (char *) alloca (strlen (base) + 64);
-  char *p;
-  int i;
-  unsigned char checksum[16];
-  struct md5_ctx ctx;
-
-  /* Compute the checksum of the DIE, then append part of it as hex digits to
-     the name filename of the unit.  */
+  return loc1->dw_loc_opc == loc2->dw_loc_opc
+        && same_dw_val_p (&loc1->dw_loc_oprnd1, &loc2->dw_loc_oprnd1, mark)
+        && same_dw_val_p (&loc1->dw_loc_oprnd2, &loc2->dw_loc_oprnd2, mark);
+}
 
-  md5_init_ctx (&ctx);
-  die_checksum (unit_die, &ctx);
-  md5_finish_ctx (&ctx, checksum);
+/* Do the values look the same?  */
+static int
+same_dw_val_p (dw_val_node *v1, dw_val_node *v2, int *mark)
+{
+  dw_loc_descr_ref loc1, loc2;
+  rtx r1, r2;
+  unsigned i;
 
-  sprintf (name, "%s.", base);
-  clean_symbol_name (name);
+  if (v1->val_class != v2->val_class)
+    return 0;
 
-  p = name + strlen (name);
-  for (i = 0; i < 4; i++)
+  switch (v1->val_class)
     {
-      sprintf (p, "%.2x", checksum[i]);
-      p += 2;
-    }
+    case dw_val_class_const:
+      return v1->v.val_int == v2->v.val_int;
+    case dw_val_class_unsigned_const:
+      return v1->v.val_unsigned == v2->v.val_unsigned;
+    case dw_val_class_long_long:
+      return v1->v.val_long_long.hi == v2->v.val_long_long.hi
+            && v1->v.val_long_long.low == v2->v.val_long_long.low;
+    case dw_val_class_float:
+      if (v1->v.val_float.length != v2->v.val_float.length)
+       return 0;
+      for (i = 0; i < v1->v.val_float.length; i++)
+       if (v1->v.val_float.array[i] != v2->v.val_float.array[i])
+         return 0;
+      return 1;
+    case dw_val_class_flag:
+      return v1->v.val_flag == v2->v.val_flag;
+    case dw_val_class_str:
+      return !strcmp(v1->v.val_str->str, v2->v.val_str->str);
 
-  comdat_symbol_id = unit_die->die_symbol = xstrdup (name);
-  comdat_symbol_number = 0;
-}
+    case dw_val_class_addr:
+      r1 = v1->v.val_addr;
+      r2 = v2->v.val_addr;
+      if (GET_CODE (r1) != GET_CODE (r2))
+       return 0;
+      switch (GET_CODE (r1))
+       {
+       case SYMBOL_REF:
+         return !strcmp (XSTR (r1, 0), XSTR (r2, 0));
 
-/* Returns nonzero if DIE represents a type, in the sense of TYPE_P.  */
+       default:
+         abort ();
+       }
+
+    case dw_val_class_offset:
+      return v1->v.val_offset == v2->v.val_offset;
+
+    case dw_val_class_loc:
+      for (loc1 = v1->v.val_loc, loc2 = v2->v.val_loc;
+          loc1 && loc2;
+          loc1 = loc1->dw_loc_next, loc2 = loc2->dw_loc_next)
+       if (!same_loc_p (loc1, loc2, mark))
+         return 0;
+      return !loc1 && !loc2;
+
+    case dw_val_class_die_ref:
+      return same_die_p (v1->v.val_die_ref.die, v2->v.val_die_ref.die, mark);
+
+    case dw_val_class_fde_ref:
+    case dw_val_class_lbl_id:
+    case dw_val_class_lbl_offset:
+      return 1;
+
+    default:
+      return 1;
+    }
+}
+
+/* Do the attributes look the same?  */
+
+static int
+same_attr_p (dw_attr_ref at1, dw_attr_ref at2, int *mark)
+{
+  if (at1->dw_attr != at2->dw_attr)
+    return 0;
+
+  /* We don't care about differences in file numbering.  */
+  if (at1->dw_attr == DW_AT_decl_file
+      /* Or that this was compiled with a different compiler snapshot; if
+        the output is the same, that's what matters.  */
+      || at1->dw_attr == DW_AT_producer)
+    return 1;
+
+  return same_dw_val_p (&at1->dw_attr_val, &at2->dw_attr_val, mark);
+}
+
+/* Do the dies look the same?  */
+
+static int
+same_die_p (dw_die_ref die1, dw_die_ref die2, int *mark)
+{
+  dw_die_ref c1, c2;
+  dw_attr_ref a1, a2;
+
+  /* To avoid infinite recursion.  */
+  if (die1->die_mark)
+    return die1->die_mark == die2->die_mark;
+  die1->die_mark = die2->die_mark = ++(*mark);
+
+  if (die1->die_tag != die2->die_tag)
+    return 0;
+
+  for (a1 = die1->die_attr, a2 = die2->die_attr;
+       a1 && a2;
+       a1 = a1->dw_attr_next, a2 = a2->dw_attr_next)
+    if (!same_attr_p (a1, a2, mark))
+      return 0;
+  if (a1 || a2)
+    return 0;
+
+  for (c1 = die1->die_child, c2 = die2->die_child;
+       c1 && c2;
+       c1 = c1->die_sib, c2 = c2->die_sib)
+    if (!same_die_p (c1, c2, mark))
+      return 0;
+  if (c1 || c2)
+    return 0;
+
+  return 1;
+}
+
+/* Do the dies look the same?  Wrapper around same_die_p.  */
+
+static int
+same_die_p_wrap (dw_die_ref die1, dw_die_ref die2)
+{
+  int mark = 0;
+  int ret = same_die_p (die1, die2, &mark);
+
+  unmark_all_dies (die1);
+  unmark_all_dies (die2);
+
+  return ret;
+}
+
+/* The prefix to attach to symbols on DIEs in the current comdat debug
+   info section.  */
+static char *comdat_symbol_id;
+
+/* The index of the current symbol within the current comdat CU.  */
+static unsigned int comdat_symbol_number;
+
+/* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its
+   children, and set comdat_symbol_id accordingly.  */
+
+static void
+compute_section_prefix (dw_die_ref unit_die)
+{
+  const char *die_name = get_AT_string (unit_die, DW_AT_name);
+  const char *base = die_name ? lbasename (die_name) : "anonymous";
+  char *name = (char *) alloca (strlen (base) + 64);
+  char *p;
+  int i, mark;
+  unsigned char checksum[16];
+  struct md5_ctx ctx;
+
+  /* Compute the checksum of the DIE, then append part of it as hex digits to
+     the name filename of the unit.  */
+
+  md5_init_ctx (&ctx);
+  mark = 0;
+  die_checksum (unit_die, &ctx, &mark);
+  unmark_all_dies (unit_die);
+  md5_finish_ctx (&ctx, checksum);
+
+  sprintf (name, "%s.", base);
+  clean_symbol_name (name);
+
+  p = name + strlen (name);
+  for (i = 0; i < 4; i++)
+    {
+      sprintf (p, "%.2x", checksum[i]);
+      p += 2;
+    }
+
+  comdat_symbol_id = unit_die->die_symbol = xstrdup (name);
+  comdat_symbol_number = 0;
+}
+
+/* Returns nonzero if DIE represents a type, in the sense of TYPE_P.  */
 
 static int
-is_type_die (die)
-     dw_die_ref die;
+is_type_die (dw_die_ref die)
 {
   switch (die->die_tag)
     {
@@ -5588,6 +5716,7 @@ is_type_die (die)
     case DW_TAG_file_type:
     case DW_TAG_packed_type:
     case DW_TAG_volatile_type:
+    case DW_TAG_typedef:
       return 1;
     default:
       return 0;
@@ -5600,8 +5729,7 @@ is_type_die (die)
    compilations (functions).  */
 
 static int
-is_comdat_die (c)
-     dw_die_ref c;
+is_comdat_die (dw_die_ref c)
 {
   /* I think we want to leave base types and __vtbl_ptr_type in the main CU, as
      we do for stabs.  The advantage is a greater likelihood of sharing between
@@ -5628,8 +5756,7 @@ is_comdat_die (c)
    compilation unit.  */
 
 static int
-is_symbol_die (c)
-     dw_die_ref c;
+is_symbol_die (dw_die_ref c)
 {
   return (is_type_die (c)
          || (get_AT (c, DW_AT_declaration)
@@ -5637,11 +5764,9 @@ is_symbol_die (c)
 }
 
 static char *
-gen_internal_sym (prefix)
-     const char *prefix;
+gen_internal_sym (const char *prefix)
 {
   char buf[256];
-  static int label_num;
 
   ASM_GENERATE_INTERNAL_LABEL (buf, prefix, label_num++);
   return xstrdup (buf);
@@ -5650,8 +5775,7 @@ gen_internal_sym (prefix)
 /* Assign symbols to all worthy DIEs under DIE.  */
 
 static void
-assign_symbol_names (die)
-     dw_die_ref die;
+assign_symbol_names (dw_die_ref die)
 {
   dw_die_ref c;
 
@@ -5673,17 +5797,105 @@ assign_symbol_names (die)
     assign_symbol_names (c);
 }
 
+struct cu_hash_table_entry
+{
+  dw_die_ref cu;
+  unsigned min_comdat_num, max_comdat_num;
+  struct cu_hash_table_entry *next;
+};
+
+/* Routines to manipulate hash table of CUs.  */
+static hashval_t
+htab_cu_hash (const void *of)
+{
+  const struct cu_hash_table_entry *entry = of;
+
+  return htab_hash_string (entry->cu->die_symbol);
+}
+
+static int
+htab_cu_eq (const void *of1, const void *of2)
+{
+  const struct cu_hash_table_entry *entry1 = of1;
+  const struct die_struct *entry2 = of2;
+
+  return !strcmp (entry1->cu->die_symbol, entry2->die_symbol);
+}
+
+static void
+htab_cu_del (void *what)
+{
+  struct cu_hash_table_entry *next, *entry = what;
+
+  while (entry)
+    {
+      next = entry->next;
+      free (entry);
+      entry = next;
+    }
+}
+
+/* Check whether we have already seen this CU and set up SYM_NUM
+   accordingly.  */
+static int
+check_duplicate_cu (dw_die_ref cu, htab_t htable, unsigned int *sym_num)
+{
+  struct cu_hash_table_entry dummy;
+  struct cu_hash_table_entry **slot, *entry, *last = &dummy;
+
+  dummy.max_comdat_num = 0;
+
+  slot = (struct cu_hash_table_entry **)
+    htab_find_slot_with_hash (htable, cu, htab_hash_string (cu->die_symbol),
+       INSERT);
+  entry = *slot;
+
+  for (; entry; last = entry, entry = entry->next)
+    {
+      if (same_die_p_wrap (cu, entry->cu))
+       break;
+    }
+
+  if (entry)
+    {
+      *sym_num = entry->min_comdat_num;
+      return 1;
+    }
+
+  entry = xcalloc (1, sizeof (struct cu_hash_table_entry));
+  entry->cu = cu;
+  entry->min_comdat_num = *sym_num = last->max_comdat_num;
+  entry->next = *slot;
+  *slot = entry;
+
+  return 0;
+}
+
+/* Record SYM_NUM to record of CU in HTABLE.  */
+static void
+record_comdat_symbol_number (dw_die_ref cu, htab_t htable, unsigned int sym_num)
+{
+  struct cu_hash_table_entry **slot, *entry;
+
+  slot = (struct cu_hash_table_entry **)
+    htab_find_slot_with_hash (htable, cu, htab_hash_string (cu->die_symbol),
+       NO_INSERT);
+  entry = *slot;
+
+  entry->max_comdat_num = sym_num;
+}
+
 /* Traverse the DIE (which is always comp_unit_die), and set up
    additional compilation units for each of the include files we see
    bracketed by BINCL/EINCL.  */
 
 static void
-break_out_includes (die)
-     dw_die_ref die;
+break_out_includes (dw_die_ref die)
 {
   dw_die_ref *ptr;
   dw_die_ref unit = NULL;
-  limbo_die_node *node;
+  limbo_die_node *node, **pnode;
+  htab_t cu_hash_table;
 
   for (ptr = &(die->die_child); *ptr;)
     {
@@ -5724,11 +5936,27 @@ break_out_includes (die)
 #endif
 
   assign_symbol_names (die);
-  for (node = limbo_die_list; node; node = node->next)
+  cu_hash_table = htab_create (10, htab_cu_hash, htab_cu_eq, htab_cu_del);
+  for (node = limbo_die_list, pnode = &limbo_die_list;
+       node;
+       node = node->next)
     {
+      int is_dupl;
+
       compute_section_prefix (node->die);
+      is_dupl = check_duplicate_cu (node->die, cu_hash_table,
+                       &comdat_symbol_number);
       assign_symbol_names (node->die);
+      if (is_dupl)
+       *pnode = node->next;
+      else
+       {
+         pnode = &node->next;
+         record_comdat_symbol_number (node->die, cu_hash_table,
+               comdat_symbol_number);
+       }
     }
+  htab_delete (cu_hash_table);
 }
 
 /* Traverse the DIE and add a sibling attribute if it may have the
@@ -5736,8 +5964,7 @@ break_out_includes (die)
    avoid generating sibling attributes for DIE's without children.  */
 
 static void
-add_sibling_attributes (die)
-     dw_die_ref die;
+add_sibling_attributes (dw_die_ref die)
 {
   dw_die_ref c;
 
@@ -5753,8 +5980,7 @@ add_sibling_attributes (die)
 /* Output all location lists for the DIE and its children.  */
 
 static void
-output_location_lists (die)
-     dw_die_ref die;
+output_location_lists (dw_die_ref die)
 {
   dw_die_ref c;
   dw_attr_ref d_attr;
@@ -5774,8 +6000,7 @@ output_location_lists (die)
    die are visited recursively.  */
 
 static void
-build_abbrev_table (die)
-     dw_die_ref die;
+build_abbrev_table (dw_die_ref die)
 {
   unsigned long abbrev_id;
   unsigned int n_alloc;
@@ -5826,9 +6051,8 @@ build_abbrev_table (die)
       if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
        {
          n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
-         abbrev_die_table
-           = (dw_die_ref *) xrealloc (abbrev_die_table,
-                                      sizeof (dw_die_ref) * n_alloc);
+         abbrev_die_table = ggc_realloc (abbrev_die_table,
+                                         sizeof (dw_die_ref) * n_alloc);
 
          memset ((char *) &abbrev_die_table[abbrev_die_table_allocated], 0,
                 (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
@@ -5847,8 +6071,7 @@ build_abbrev_table (die)
 /* Return the power-of-two number of bytes necessary to represent VALUE.  */
 
 static int
-constant_size (value)
-     long unsigned value;
+constant_size (long unsigned int value)
 {
   int log;
 
@@ -5867,8 +6090,7 @@ constant_size (value)
    .debug_info section.  */
 
 static unsigned long
-size_of_die (die)
-     dw_die_ref die;
+size_of_die (dw_die_ref die)
 {
   unsigned long size = 0;
   dw_attr_ref a;
@@ -5915,7 +6137,10 @@ size_of_die (die)
          size += 1;
          break;
        case dw_val_class_die_ref:
-         size += DWARF_OFFSET_SIZE;
+         if (AT_ref_external (a))
+           size += DWARF2_ADDR_SIZE;
+         else
+           size += DWARF_OFFSET_SIZE;
          break;
        case dw_val_class_fde_ref:
          size += DWARF_OFFSET_SIZE;
@@ -5930,7 +6155,7 @@ size_of_die (die)
          if (AT_string_form (a) == DW_FORM_strp)
            size += DWARF_OFFSET_SIZE;
          else
-           size += HT_LEN (&a->dw_attr_val.v.val_str->id) + 1;
+           size += strlen (a->dw_attr_val.v.val_str->str) + 1;
          break;
        default:
          abort ();
@@ -5946,8 +6171,7 @@ size_of_die (die)
    die_offset field in each DIE.  */
 
 static void
-calc_die_sizes (die)
-     dw_die_ref die;
+calc_die_sizes (dw_die_ref die)
 {
   dw_die_ref c;
 
@@ -5968,11 +6192,13 @@ calc_die_sizes (die)
    and use that as the flag, but ran into ordering problems.  */
 
 static void
-mark_dies (die)
-     dw_die_ref die;
+mark_dies (dw_die_ref die)
 {
   dw_die_ref c;
 
+  if (die->die_mark)
+    abort ();
+
   die->die_mark = 1;
   for (c = die->die_child; c; c = c->die_sib)
     mark_dies (c);
@@ -5981,21 +6207,43 @@ mark_dies (die)
 /* Clear the marks for a die and its children.  */
 
 static void
-unmark_dies (die)
-     dw_die_ref die;
+unmark_dies (dw_die_ref die)
 {
   dw_die_ref c;
 
+  if (!die->die_mark)
+    abort ();
+
   die->die_mark = 0;
   for (c = die->die_child; c; c = c->die_sib)
     unmark_dies (c);
 }
 
+/* Clear the marks for a die, its children and referred dies.  */
+
+static void
+unmark_all_dies (dw_die_ref die)
+{
+  dw_die_ref c;
+  dw_attr_ref a;
+
+  if (!die->die_mark)
+    return;
+  die->die_mark = 0;
+
+  for (c = die->die_child; c; c = c->die_sib)
+    unmark_all_dies (c);
+
+  for (a = die->die_attr; a; a = a->dw_attr_next)
+    if (AT_class (a) == dw_val_class_die_ref)
+      unmark_all_dies (AT_ref (a));
+}
+
 /* Return the size of the .debug_pubnames table  generated for the
    compilation unit.  */
 
 static unsigned long
-size_of_pubnames ()
+size_of_pubnames (void)
 {
   unsigned long size;
   unsigned i;
@@ -6014,7 +6262,7 @@ size_of_pubnames ()
 /* Return the size of the information in the .debug_aranges section.  */
 
 static unsigned long
-size_of_aranges ()
+size_of_aranges (void)
 {
   unsigned long size;
 
@@ -6032,8 +6280,7 @@ size_of_aranges ()
 /* Select the encoding of an attribute value.  */
 
 static enum dwarf_form
-value_format (a)
-     dw_attr_ref a;
+value_format (dw_attr_ref a)
 {
   switch (a->dw_attr_val.val_class)
     {
@@ -6104,8 +6351,7 @@ value_format (a)
 /* Output the encoding of an attribute value.  */
 
 static void
-output_value_format (a)
-     dw_attr_ref a;
+output_value_format (dw_attr_ref a)
 {
   enum dwarf_form form = value_format (a);
 
@@ -6116,7 +6362,7 @@ output_value_format (a)
    table.  */
 
 static void
-output_abbrev_section ()
+output_abbrev_section (void)
 {
   unsigned long abbrev_id;
 
@@ -6154,8 +6400,7 @@ output_abbrev_section ()
 /* Output a symbol we can use to refer to this DIE from another CU.  */
 
 static inline void
-output_die_symbol (die)
-     dw_die_ref die;
+output_die_symbol (dw_die_ref die)
 {
   char *sym = die->die_symbol;
 
@@ -6166,7 +6411,7 @@ output_die_symbol (die)
     /* We make these global, not weak; if the target doesn't support
        .linkonce, it doesn't support combining the sections, so debugging
        will break.  */
-    ASM_GLOBALIZE_LABEL (asm_out_file, sym);
+    (*targetm.asm_out.globalize_label) (asm_out_file, sym);
 
   ASM_OUTPUT_LABEL (asm_out_file, sym);
 }
@@ -6176,15 +6421,10 @@ output_die_symbol (die)
    this location list node, which is done for the head of the list only.  */
 
 static inline dw_loc_list_ref
-new_loc_list (expr, begin, end, section, gensym)
-     dw_loc_descr_ref expr;
-     const char *begin;
-     const char *end;
-     const char *section;
-     unsigned gensym;
+new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
+             const char *section, unsigned int gensym)
 {
-  dw_loc_list_ref retlist
-    = (dw_loc_list_ref) xcalloc (1, sizeof (dw_loc_list_node));
+  dw_loc_list_ref retlist = ggc_alloc_cleared (sizeof (dw_loc_list_node));
 
   retlist->begin = begin;
   retlist->end = end;
@@ -6196,15 +6436,12 @@ new_loc_list (expr, begin, end, section, gensym)
   return retlist;
 }
 
-/* Add a location description expression to a location list */
+/* Add a location description expression to a location list */
 
 static inline void
-add_loc_descr_to_loc_list (list_head, descr, begin, end, section)
-     dw_loc_list_ref *list_head;
-     dw_loc_descr_ref descr;
-     const char *begin;
-     const char *end;
-     const char *section;
+add_loc_descr_to_loc_list (dw_loc_list_ref *list_head, dw_loc_descr_ref descr,
+                          const char *begin, const char *end,
+                          const char *section)
 {
   dw_loc_list_ref *d;
 
@@ -6212,15 +6449,14 @@ add_loc_descr_to_loc_list (list_head, descr, begin, end, section)
   for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
     ;
 
-  /* Add a new location list node to the list */
+  /* Add a new location list node to the list */
   *d = new_loc_list (descr, begin, end, section, 0);
 }
 
-/* Output the location list given to us */
+/* Output the location list given to us */
 
 static void
-output_loc_list (list_head)
-     dw_loc_list_ref list_head;
+output_loc_list (dw_loc_list_ref list_head)
 {
   dw_loc_list_ref curr = list_head;
 
@@ -6270,8 +6506,7 @@ output_loc_list (list_head)
    the definitions of each child DIE.  */
 
 static void
-output_die (die)
-     dw_die_ref die;
+output_die (dw_die_ref die)
 {
   dw_attr_ref a;
   dw_die_ref c;
@@ -6447,9 +6682,13 @@ output_die (die)
    .debug_info section, and precedes the DIE descriptions.  */
 
 static void
-output_compilation_unit_header ()
+output_compilation_unit_header (void)
 {
-  dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset - DWARF_OFFSET_SIZE,
+  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+    dw2_asm_output_data (4, 0xffffffff,
+      "Initial length escape value indicating 64-bit DWARF extension");
+  dw2_asm_output_data (DWARF_OFFSET_SIZE,
+                       next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
                       "Length of Compilation Unit Info");
   dw2_asm_output_data (2, DWARF_VERSION, "DWARF version number");
   dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label,
@@ -6460,10 +6699,14 @@ output_compilation_unit_header ()
 /* Output the compilation unit DIE and its children.  */
 
 static void
-output_comp_unit (die)
-     dw_die_ref die;
+output_comp_unit (dw_die_ref die, int output_if_empty)
 {
   const char *secname;
+  char *oldsym, *tmp;
+
+  /* Unless we are outputting main CU, we may throw away empty ones.  */
+  if (!output_if_empty && die->die_child == NULL)
+    return;
 
   /* Even if there are no children of this DIE, we must output the information
      about the compilation unit.  Otherwise, on an empty translation unit, we
@@ -6478,11 +6721,12 @@ output_comp_unit (die)
   next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
   calc_die_sizes (die);
 
-  if (die->die_symbol)
+  oldsym = die->die_symbol;
+  if (oldsym)
     {
-      char *tmp = (char *) alloca (strlen (die->die_symbol) + 24);
+      tmp = (char *) alloca (strlen (oldsym) + 24);
 
-      sprintf (tmp, ".gnu.linkonce.wi.%s", die->die_symbol);
+      sprintf (tmp, ".gnu.linkonce.wi.%s", oldsym);
       secname = tmp;
       die->die_symbol = NULL;
     }
@@ -6496,8 +6740,11 @@ output_comp_unit (die)
 
   /* Leave the marks on the main CU, so we can check them in
      output_pubnames.  */
-  if (die->die_symbol)
-    unmark_dies (die);
+  if (oldsym)
+    {
+      unmark_dies (die);
+      die->die_symbol = oldsym;
+    }
 }
 
 /* The DWARF2 pubname for a nested thingy looks like "A::f".  The
@@ -6505,9 +6752,7 @@ output_comp_unit (die)
    "A::f(int)".  Let's drop the argument list, and maybe the scope.  */
 
 static const char *
-dwarf2_name (decl, scope)
-     tree decl;
-     int scope;
+dwarf2_name (tree decl, int scope)
 {
   return (*lang_hooks.decl_printable_name) (decl, scope ? 1 : 0);
 }
@@ -6515,9 +6760,7 @@ dwarf2_name (decl, scope)
 /* Add a new entry to .debug_pubnames if appropriate.  */
 
 static void
-add_pubname (decl, die)
-     tree decl;
-     dw_die_ref die;
+add_pubname (tree decl, dw_die_ref die)
 {
   pubname_ref p;
 
@@ -6528,9 +6771,11 @@ add_pubname (decl, die)
     {
       pubname_table_allocated += PUBNAME_TABLE_INCREMENT;
       pubname_table
-       = (pubname_ref) xrealloc (pubname_table,
-                                 (pubname_table_allocated
-                                  * sizeof (pubname_entry)));
+       = (pubname_ref) ggc_realloc (pubname_table,
+                                    (pubname_table_allocated
+                                     * sizeof (pubname_entry)));
+      memset (pubname_table + pubname_table_in_use, 0,
+             PUBNAME_TABLE_INCREMENT * sizeof (pubname_entry));
     }
 
   p = &pubname_table[pubname_table_in_use++];
@@ -6543,11 +6788,14 @@ add_pubname (decl, die)
    visible procedures.  */
 
 static void
-output_pubnames ()
+output_pubnames (void)
 {
   unsigned i;
   unsigned long pubnames_length = size_of_pubnames ();
 
+  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+    dw2_asm_output_data (4, 0xffffffff,
+      "Initial length escape value indicating 64-bit DWARF extension");
   dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
                       "Length of Public Names Info");
   dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version");
@@ -6576,9 +6824,7 @@ output_pubnames ()
 /* Add a new entry to .debug_aranges if appropriate.  */
 
 static void
-add_arange (decl, die)
-     tree decl;
-     dw_die_ref die;
+add_arange (tree decl, dw_die_ref die)
 {
   if (! DECL_SECTION_NAME (decl))
     return;
@@ -6586,8 +6832,11 @@ add_arange (decl, die)
   if (arange_table_in_use == arange_table_allocated)
     {
       arange_table_allocated += ARANGE_TABLE_INCREMENT;
-      arange_table = (dw_die_ref *)
-       xrealloc (arange_table, arange_table_allocated * sizeof (dw_die_ref));
+      arange_table = ggc_realloc (arange_table,
+                                 (arange_table_allocated
+                                  * sizeof (dw_die_ref)));
+      memset (arange_table + arange_table_in_use, 0,
+             ARANGE_TABLE_INCREMENT * sizeof (dw_die_ref));
     }
 
   arange_table[arange_table_in_use++] = die;
@@ -6598,11 +6847,14 @@ add_arange (decl, die)
    text section generated for this compilation unit.  */
 
 static void
-output_aranges ()
+output_aranges (void)
 {
   unsigned i;
   unsigned long aranges_length = size_of_aranges ();
 
+  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+    dw2_asm_output_data (4, 0xffffffff,
+      "Initial length escape value indicating 64-bit DWARF extension");
   dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length,
                       "Length of Address Ranges Info");
   dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version");
@@ -6615,7 +6867,7 @@ output_aranges ()
   if (DWARF_ARANGES_PAD_SIZE)
     {
       /* Pad using a 2 byte words so that padding is correct for any
-         pointer size.  */
+        pointer size.  */
       dw2_asm_output_data (2, 0, "Pad to %d byte boundary",
                           2 * DWARF2_ADDR_SIZE);
       for (i = 2; i < (unsigned) DWARF_ARANGES_PAD_SIZE; i += 2)
@@ -6673,8 +6925,7 @@ output_aranges ()
    was placed.  */
 
 static unsigned int
-add_ranges (block)
-     tree block;
+add_ranges (tree block)
 {
   unsigned int in_use = ranges_table_in_use;
 
@@ -6682,8 +6933,10 @@ add_ranges (block)
     {
       ranges_table_allocated += RANGES_TABLE_INCREMENT;
       ranges_table = (dw_ranges_ref)
-       xrealloc (ranges_table, (ranges_table_allocated
-                                * sizeof (struct dw_ranges_struct)));
+       ggc_realloc (ranges_table, (ranges_table_allocated
+                                   * sizeof (struct dw_ranges_struct)));
+      memset (ranges_table + ranges_table_in_use, 0,
+             RANGES_TABLE_INCREMENT * sizeof (struct dw_ranges_struct));
     }
 
   ranges_table[in_use].block_num = (block ? BLOCK_NUMBER (block) : 0);
@@ -6693,7 +6946,7 @@ add_ranges (block)
 }
 
 static void
-output_ranges ()
+output_ranges (void)
 {
   unsigned i;
   static const char *const start_fmt = "Offset 0x%x";
@@ -6771,9 +7024,7 @@ struct dir_info
    the directories in the path.  */
 
 static int
-file_info_cmp (p1, p2)
-     const void *p1;
-     const void *p2;
+file_info_cmp (const void *p1, const void *p2)
 {
   const struct file_info *s1 = p1;
   const struct file_info *s2 = p2;
@@ -6812,31 +7063,39 @@ file_info_cmp (p1, p2)
    slowdowns with many input files.  */
 
 static void
-output_file_names ()
+output_file_names (void)
 {
   struct file_info *files;
   struct dir_info *dirs;
   int *saved;
   int *savehere;
   int *backmap;
-  int ndirs;
+  size_t ndirs;
   int idx_offset;
-  int i;
+  size_t i;
   int idx;
 
+  /* Handle the case where file_table is empty.  */
+  if (VARRAY_ACTIVE_SIZE (file_table) <= 1)
+    {
+      dw2_asm_output_data (1, 0, "End directory table");
+      dw2_asm_output_data (1, 0, "End file name table");
+      return;
+    }
+
   /* Allocate the various arrays we need.  */
-  files = (struct file_info *) alloca (file_table.in_use
+  files = (struct file_info *) alloca (VARRAY_ACTIVE_SIZE (file_table)
                                       * sizeof (struct file_info));
-  dirs = (struct dir_info *) alloca (file_table.in_use
+  dirs = (struct dir_info *) alloca (VARRAY_ACTIVE_SIZE (file_table)
                                     * sizeof (struct dir_info));
 
   /* Sort the file names.  */
-  for (i = 1; i < (int) file_table.in_use; i++)
+  for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++)
     {
       char *f;
 
       /* Skip all leading "./".  */
-      f = file_table.table[i];
+      f = VARRAY_CHAR_PTR (file_table, i);
       while (f[0] == '.' && f[1] == '/')
        f += 2;
 
@@ -6850,7 +7109,8 @@ output_file_names ()
       files[i].fname = f == NULL ? files[i].path : f + 1;
     }
 
-  qsort (files + 1, file_table.in_use - 1, sizeof (files[0]), file_info_cmp);
+  qsort (files + 1, VARRAY_ACTIVE_SIZE (file_table) - 1,
+        sizeof (files[0]), file_info_cmp);
 
   /* Find all the different directories used.  */
   dirs[0].path = files[1].path;
@@ -6862,7 +7122,7 @@ output_file_names ()
   files[1].dir_idx = 0;
   ndirs = 1;
 
-  for (i = 2; i < (int) file_table.in_use; i++)
+  for (i = 2; i < VARRAY_ACTIVE_SIZE (file_table); i++)
     if (files[i].fname - files[i].path == dirs[ndirs - 1].length
        && memcmp (dirs[ndirs - 1].path, files[i].path,
                   dirs[ndirs - 1].length) == 0)
@@ -6873,7 +7133,7 @@ output_file_names ()
       }
     else
       {
-       int j;
+       size_t j;
 
        /* This is a new directory.  */
        dirs[ndirs].path = files[i].path;
@@ -6908,7 +7168,7 @@ output_file_names ()
   memset (saved, '\0', ndirs * sizeof (saved[0]));
   for (i = 0; i < ndirs; i++)
     {
-      int j;
+      size_t j;
       int total;
 
       /* We can always save some space for the current directory.  But this
@@ -6926,10 +7186,10 @@ output_file_names ()
              int k;
 
              k = dirs[j].prefix;
-             while (k != -1 && k != i)
+             while (k != -1 && k != (int) i)
                k = dirs[k].prefix;
 
-             if (k == i)
+             if (k == (int) i)
                {
                  /* Yes it is.  We can possibly safe some memory but
                     writing the filenames in dirs[j] relative to
@@ -6960,8 +7220,8 @@ output_file_names ()
   /* We have to emit them in the order they appear in the file_table array
      since the index is used in the debug info generation.  To do this
      efficiently we generate a back-mapping of the indices first.  */
-  backmap = (int *) alloca (file_table.in_use * sizeof (int));
-  for (i = 1; i < (int) file_table.in_use; i++)
+  backmap = (int *) alloca (VARRAY_ACTIVE_SIZE (file_table) * sizeof (int));
+  for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++)
     {
       backmap[files[i].file_idx] = i;
 
@@ -6992,13 +7252,13 @@ output_file_names ()
     dirs[0].used = 0;
 
   /* Now write all the file names.  */
-  for (i = 1; i < (int) file_table.in_use; i++)
+  for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++)
     {
       int file_idx = backmap[i];
       int dir_idx = dirs[files[file_idx].dir_idx].dir_idx;
 
       dw2_asm_output_nstring (files[file_idx].path + dirs[dir_idx].length, -1,
-                             "File Entry: 0x%x", i);
+                             "File Entry: 0x%lx", (unsigned long) i);
 
       /* Include directory index.  */
       dw2_asm_output_data_uleb128 (dirs[dir_idx].used, NULL);
@@ -7018,7 +7278,7 @@ output_file_names ()
    information goes into the .debug_line section.  */
 
 static void
-output_line_info ()
+output_line_info (void)
 {
   char l1[20], l2[20], p1[20], p2[20];
   char line_label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -7037,6 +7297,9 @@ output_line_info ()
   ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, 0);
 
+  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+    dw2_asm_output_data (4, 0xffffffff,
+      "Initial length escape value indicating 64-bit DWARF extension");
   dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
                        "Length of Source Line Info");
   ASM_OUTPUT_LABEL (asm_out_file, l1);
@@ -7108,8 +7371,8 @@ output_line_info ()
         prologue.  */
 
       /* Don't emit anything for redundant notes.  Just updating the
-         address doesn't accomplish anything, because we already assume
-         that anything after the last address is this line.  */
+        address doesn't accomplish anything, because we already assume
+        that anything after the last address is this line.  */
       if (line_info->dw_line_num == current_line
          && line_info->dw_file_num == current_file)
        continue;
@@ -7135,7 +7398,7 @@ output_line_info ()
       else
        {
          /* This can handle any delta.  This takes
-             4+DWARF2_ADDR_SIZE bytes.  */
+            4+DWARF2_ADDR_SIZE bytes.  */
          dw2_asm_output_data (1, 0, "DW_LNE_set_address");
          dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL);
          dw2_asm_output_data (1, DW_LNE_set_address, NULL);
@@ -7151,7 +7414,8 @@ output_line_info ()
          current_file = line_info->dw_file_num;
          dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file");
          dw2_asm_output_data_uleb128 (current_file, "(\"%s\")",
-                                      file_table.table[current_file]);
+                                      VARRAY_CHAR_PTR (file_table,
+                                                       current_file));
        }
 
       /* Emit debug info for the current line number, choosing the encoding
@@ -7226,7 +7490,7 @@ output_line_info ()
        {
          function = line_info->function;
 
-         /* Set the address register to the first line in the function */
+         /* Set the address register to the first line in the function */
          dw2_asm_output_data (1, 0, "DW_LNE_set_address");
          dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL);
          dw2_asm_output_data (1, DW_LNE_set_address, NULL);
@@ -7259,7 +7523,8 @@ output_line_info ()
          current_file = line_info->dw_file_num;
          dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file");
          dw2_asm_output_data_uleb128 (current_file, "(\"%s\")",
-                                      file_table.table[current_file]);
+                                      VARRAY_CHAR_PTR (file_table,
+                                                       current_file));
        }
 
       /* Emit debug info for the current line number, choosing the encoding
@@ -7330,8 +7595,7 @@ output_line_info ()
    Dwarf base (fundamental) types.  */
 
 static dw_die_ref
-base_type_die (type)
-     tree type;
+base_type_die (tree type)
 {
   dw_die_ref base_type_result;
   const char *type_name;
@@ -7355,9 +7619,9 @@ base_type_die (type)
     {
     case INTEGER_TYPE:
       /* Carefully distinguish the C character types, without messing
-         up if the language is not C. Note that we check only for the names
-         that contain spaces; other names might occur by coincidence in other
-         languages.  */
+        up if the language is not C. Note that we check only for the names
+        that contain spaces; other names might occur by coincidence in other
+        languages.  */
       if (! (TYPE_PRECISION (type) == CHAR_TYPE_SIZE
             && (type == char_type_node
                 || ! strcmp (type_name, "signed char")
@@ -7424,8 +7688,7 @@ base_type_die (type)
    root type of the given type without the qualifiers.  */
 
 static tree
-root_type (type)
-     tree type;
+root_type (tree type)
 {
   if (TREE_CODE (type) == ERROR_MARK)
     return error_mark_node;
@@ -7444,12 +7707,11 @@ root_type (type)
     }
 }
 
-/* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the
+/* Given a pointer to an arbitrary ..._TYPE tree node, return nonzero if the
    given input type is a Dwarf "fundamental" type.  Otherwise return null.  */
 
 static inline int
-is_base_type (type)
-     tree type;
+is_base_type (tree type)
 {
   switch (TREE_CODE (type))
     {
@@ -7485,15 +7747,73 @@ is_base_type (type)
   return 0;
 }
 
+/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE
+   node, return the size in bits for the type if it is a constant, or else
+   return the alignment for the type if the type's size is not constant, or
+   else return BITS_PER_WORD if the type actually turns out to be an
+   ERROR_MARK node.  */
+
+static inline unsigned HOST_WIDE_INT
+simple_type_size_in_bits (tree type)
+{
+  if (TREE_CODE (type) == ERROR_MARK)
+    return BITS_PER_WORD;
+  else if (TYPE_SIZE (type) == NULL_TREE)
+    return 0;
+  else if (host_integerp (TYPE_SIZE (type), 1))
+    return tree_low_cst (TYPE_SIZE (type), 1);
+  else
+    return TYPE_ALIGN (type);
+}
+
+/* Return true if the debug information for the given type should be
+   emitted as a subrange type.  */
+
+static inline bool
+is_ada_subrange_type (tree type)
+{
+  /* We do this for INTEGER_TYPEs that have names, parent types, and when
+     we are compiling Ada code.  */
+  return (TREE_CODE (type) == INTEGER_TYPE
+         && TYPE_NAME (type) != 0 && TREE_TYPE (type) != 0
+         && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
+         && TREE_UNSIGNED (TREE_TYPE (type)) && is_ada ());
+}
+
+/*  Given a pointer to a tree node for a subrange type, return a pointer
+    to a DIE that describes the given type.  */
+
+static dw_die_ref
+subrange_type_die (tree type)
+{
+  dw_die_ref subtype_die;
+  dw_die_ref subrange_die;
+  tree name = TYPE_NAME (type);
+
+  subtype_die = base_type_die (TREE_TYPE (type));
+
+  if (TREE_CODE (name) == TYPE_DECL)
+    name = DECL_NAME (name);
+
+  subrange_die = new_die (DW_TAG_subrange_type, comp_unit_die, type);
+  add_name_attribute (subrange_die, IDENTIFIER_POINTER (name));
+  if (TYPE_MIN_VALUE (type) != NULL)
+    add_bound_info (subrange_die, DW_AT_lower_bound,
+                    TYPE_MIN_VALUE (type));
+  if (TYPE_MAX_VALUE (type) != NULL)
+    add_bound_info (subrange_die, DW_AT_upper_bound,
+                    TYPE_MAX_VALUE (type));
+  add_AT_die_ref (subrange_die, DW_AT_type, subtype_die);
+
+  return subrange_die;
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
    entry that chains various modifiers in front of the given type.  */
 
 static dw_die_ref
-modified_type_die (type, is_const_type, is_volatile_type, context_die)
-     tree type;
-     int is_const_type;
-     int is_volatile_type;
-     dw_die_ref context_die;
+modified_type_die (tree type, int is_const_type, int is_volatile_type,
+                  dw_die_ref context_die)
 {
   enum tree_code code = TREE_CODE (type);
   dw_die_ref mod_type_die = NULL;
@@ -7562,7 +7882,8 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
       else if (code == POINTER_TYPE)
        {
          mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type);
-         add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
+         add_AT_unsigned (mod_type_die, DW_AT_byte_size,
+                          simple_type_size_in_bits (type) / BITS_PER_UNIT);
 #if 0
          add_AT_unsigned (mod_type_die, DW_AT_address_class, 0);
 #endif
@@ -7571,12 +7892,15 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
       else if (code == REFERENCE_TYPE)
        {
          mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type);
-         add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
+         add_AT_unsigned (mod_type_die, DW_AT_byte_size,
+                          simple_type_size_in_bits (type) / BITS_PER_UNIT);
 #if 0
          add_AT_unsigned (mod_type_die, DW_AT_address_class, 0);
 #endif
          item_type = TREE_TYPE (type);
        }
+      else if (is_ada_subrange_type (type))
+        mod_type_die = subrange_type_die (type);
       else if (is_base_type (type))
        mod_type_die = base_type_die (type);
       else
@@ -7600,11 +7924,11 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
        }
 
       /* We want to equate the qualified type to the die below.  */
-      if (qualified_type)
-       type = qualified_type;
+      type = qualified_type;
     }
 
-  equate_type_number_to_die (type, mod_type_die);
+  if (type)
+    equate_type_number_to_die (type, mod_type_die);
   if (item_type)
     /* We must do this after the equate_type_number_to_die call, in case
        this is a recursive type.  This ensures that the modified_type_die
@@ -7625,8 +7949,7 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
    an enumerated type.  */
 
 static inline int
-type_is_enum (type)
-     tree type;
+type_is_enum (tree type)
 {
   return TREE_CODE (type) == ENUMERAL_TYPE;
 }
@@ -7634,8 +7957,7 @@ type_is_enum (type)
 /* Return the register number described by a given RTL node.  */
 
 static unsigned int
-reg_number (rtl)
-     rtx rtl;
+reg_number (rtx rtl)
 {
   unsigned regno = REGNO (rtl);
 
@@ -7646,32 +7968,94 @@ reg_number (rtl)
 }
 
 /* Return a location descriptor that designates a machine register or
-   zero if there is no such.  */
+   zero if there is none.  */
 
 static dw_loc_descr_ref
-reg_loc_descriptor (rtl)
-     rtx rtl;
+reg_loc_descriptor (rtx rtl)
 {
-  dw_loc_descr_ref loc_result = NULL;
   unsigned reg;
+  rtx regs;
 
   if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
     return 0;
 
   reg = reg_number (rtl);
-  if (reg <= 31)
-    loc_result = new_loc_descr (DW_OP_reg0 + reg, 0, 0);
+  regs = (*targetm.dwarf_register_span) (rtl);
+
+  if (HARD_REGNO_NREGS (reg, GET_MODE (rtl)) > 1
+      || regs)
+    return multiple_reg_loc_descriptor (rtl, regs);
   else
-    loc_result = new_loc_descr (DW_OP_regx, reg, 0);
+    return one_reg_loc_descriptor (reg);
+}
+
+/* Return a location descriptor that designates a machine register for
+   a given hard register number.  */
+
+static dw_loc_descr_ref
+one_reg_loc_descriptor (unsigned int regno)
+{
+  if (regno <= 31)
+    return new_loc_descr (DW_OP_reg0 + regno, 0, 0);
+  else
+    return new_loc_descr (DW_OP_regx, regno, 0);
+}
 
+/* Given an RTL of a register, return a location descriptor that
+   designates a value that spans more than one register.  */
+
+static dw_loc_descr_ref
+multiple_reg_loc_descriptor (rtx rtl, rtx regs)
+{
+  int nregs, size, i;
+  unsigned reg;
+  dw_loc_descr_ref loc_result = NULL;
+
+  reg = reg_number (rtl);
+  nregs = HARD_REGNO_NREGS (reg, GET_MODE (rtl));
+
+  /* Simple, contiguous registers.  */
+  if (regs == NULL_RTX)
+    {
+      size = GET_MODE_SIZE (GET_MODE (rtl)) / nregs;
+
+      loc_result = NULL;
+      while (nregs--)
+       {
+         dw_loc_descr_ref t;
+
+         t = one_reg_loc_descriptor (reg);
+         add_loc_descr (&loc_result, t);
+         add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0));
+         ++reg;
+       }
+      return loc_result;
+    }
+
+  /* Now onto stupid register sets in non contiguous locations.  */
+
+  if (GET_CODE (regs) != PARALLEL)
+    abort ();
+
+  size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
+  loc_result = NULL;
+
+  for (i = 0; i < XVECLEN (regs, 0); ++i)
+    {
+      dw_loc_descr_ref t;
+
+      t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i)));
+      add_loc_descr (&loc_result, t);
+      size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
+      add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0));
+    }
   return loc_result;
 }
 
 /* Return a location descriptor that designates a constant.  */
 
 static dw_loc_descr_ref
-int_loc_descriptor (i)
-     HOST_WIDE_INT i;
+int_loc_descriptor (HOST_WIDE_INT i)
 {
   enum dwarf_location_atom op;
 
@@ -7710,9 +8094,7 @@ int_loc_descriptor (i)
 /* Return a location descriptor that designates a base+offset location.  */
 
 static dw_loc_descr_ref
-based_loc_descr (reg, offset)
-     unsigned reg;
-     long int offset;
+based_loc_descr (unsigned int reg, long int offset)
 {
   dw_loc_descr_ref loc_result;
   /* For the "frame base", we use the frame pointer or stack pointer
@@ -7735,8 +8117,7 @@ based_loc_descr (reg, offset)
 /* Return true if this RTL expression describes a base+offset calculation.  */
 
 static inline int
-is_based_loc (rtl)
-     rtx rtl;
+is_based_loc (rtx rtl)
 {
   return (GET_CODE (rtl) == PLUS
          && ((GET_CODE (XEXP (rtl, 0)) == REG
@@ -7760,9 +8141,7 @@ is_based_loc (rtl)
    Return 0 if we can't represent the location.  */
 
 static dw_loc_descr_ref
-mem_loc_descriptor (rtl, mode)
-     rtx rtl;
-     enum machine_mode mode;
+mem_loc_descriptor (rtx rtl, enum machine_mode mode)
 {
   dw_loc_descr_ref mem_loc_result = NULL;
 
@@ -7771,9 +8150,7 @@ mem_loc_descriptor (rtl, mode)
      actually within the array.  That's *not* necessarily the same as the
      zeroth element of the array.  */
 
-#ifdef ASM_SIMPLIFY_DWARF_ADDR
-  rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
-#endif
+  rtl = (*targetm.delegitimize_address) (rtl);
 
   switch (GET_CODE (rtl))
     {
@@ -7787,28 +8164,28 @@ mem_loc_descriptor (rtl, mode)
 
     case SUBREG:
       /* The case of a subreg may arise when we have a local (register)
-         variable or a formal (register) parameter which doesn't quite fill
-         up an entire register.  For now, just assume that it is
-         legitimate to make the Dwarf info refer to the whole register which
-         contains the given subreg.  */
+        variable or a formal (register) parameter which doesn't quite fill
+        up an entire register.  For now, just assume that it is
+        legitimate to make the Dwarf info refer to the whole register which
+        contains the given subreg.  */
       rtl = SUBREG_REG (rtl);
 
       /* ... fall through ...  */
 
     case REG:
       /* Whenever a register number forms a part of the description of the
-         method for calculating the (dynamic) address of a memory resident
-         object, DWARF rules require the register number be referred to as
-         a "base register".  This distinction is not based in any way upon
-         what category of register the hardware believes the given register
-         belongs to.  This is strictly DWARF terminology we're dealing with
-         here. Note that in cases where the location of a memory-resident
-         data object could be expressed as: OP_ADD (OP_BASEREG (basereg),
-         OP_CONST (0)) the actual DWARF location descriptor that we generate
-         may just be OP_BASEREG (basereg).  This may look deceptively like
-         the object in question was allocated to a register (rather than in
-         memory) so DWARF consumers need to be aware of the subtle
-         distinction between OP_REG and OP_BASEREG.  */
+        method for calculating the (dynamic) address of a memory resident
+        object, DWARF rules require the register number be referred to as
+        a "base register".  This distinction is not based in any way upon
+        what category of register the hardware believes the given register
+        belongs to.  This is strictly DWARF terminology we're dealing with
+        here. Note that in cases where the location of a memory-resident
+        data object could be expressed as: OP_ADD (OP_BASEREG (basereg),
+        OP_CONST (0)) the actual DWARF location descriptor that we generate
+        may just be OP_BASEREG (basereg).  This may look deceptively like
+        the object in question was allocated to a register (rather than in
+        memory) so DWARF consumers need to be aware of the subtle
+        distinction between OP_REG and OP_BASEREG.  */
       if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
        mem_loc_result = based_loc_descr (reg_number (rtl), 0);
       break;
@@ -7819,10 +8196,15 @@ mem_loc_descriptor (rtl, mode)
        add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
       break;
 
+    case LO_SUM:
+        rtl = XEXP (rtl, 1);
+
+      /* ... fall through ...  */
+
     case LABEL_REF:
       /* Some ports can transform a symbol ref into a label ref, because
-        the symbol ref is too far away and has to be dumped into a constant
-        pool.  */
+        the symbol ref is too far away and has to be dumped into a constant
+        pool.  */
     case CONST:
     case SYMBOL_REF:
       /* Alternatively, the symbol in the constant pool might be referenced
@@ -7857,7 +8239,7 @@ mem_loc_descriptor (rtl, mode)
 
     case PRE_MODIFY:
       /* Extract the PLUS expression nested inside and fall into
-         PLUS code below.  */
+        PLUS code below.  */
       rtl = XEXP (rtl, 1);
       goto plus;
 
@@ -7937,8 +8319,7 @@ mem_loc_descriptor (rtl, mode)
    This is typically a complex variable.  */
 
 static dw_loc_descr_ref
-concat_loc_descriptor (x0, x1)
-     rtx x0, x1;
+concat_loc_descriptor (rtx x0, rtx x1)
 {
   dw_loc_descr_ref cc_loc_result = NULL;
   dw_loc_descr_ref x0_ref = loc_descriptor (x0);
@@ -7969,8 +8350,7 @@ concat_loc_descriptor (x0, x1)
    If we don't know how to describe it, return 0.  */
 
 static dw_loc_descr_ref
-loc_descriptor (rtl)
-     rtx rtl;
+loc_descriptor (rtx rtl)
 {
   dw_loc_descr_ref loc_result = NULL;
 
@@ -7978,10 +8358,10 @@ loc_descriptor (rtl)
     {
     case SUBREG:
       /* The case of a subreg may arise when we have a local (register)
-         variable or a formal (register) parameter which doesn't quite fill
-         up an entire register.  For now, just assume that it is
-         legitimate to make the Dwarf info refer to the whole register which
-         contains the given subreg.  */
+        variable or a formal (register) parameter which doesn't quite fill
+        up an entire register.  For now, just assume that it is
+        legitimate to make the Dwarf info refer to the whole register which
+        contains the given subreg.  */
       rtl = SUBREG_REG (rtl);
 
       /* ... fall through ...  */
@@ -8011,9 +8391,7 @@ loc_descriptor (rtl)
    descriptor, return 0.  */
 
 static dw_loc_descr_ref
-loc_descriptor_from_tree (loc, addressp)
-     tree loc;
-     int addressp;
+loc_descriptor_from_tree (tree loc, int addressp)
 {
   dw_loc_descr_ref ret, ret1;
   int indirect_p = 0;
@@ -8056,6 +8434,42 @@ loc_descriptor_from_tree (loc, addressp)
               : 0);
 
     case VAR_DECL:
+      if (DECL_THREAD_LOCAL (loc))
+       {
+         rtx rtl;
+
+#ifndef ASM_OUTPUT_DWARF_DTPREL
+         /* If this is not defined, we have no way to emit the data.  */
+         return 0;
+#endif
+
+         /* The way DW_OP_GNU_push_tls_address is specified, we can only
+            look up addresses of objects in the current module.  */
+         if (DECL_EXTERNAL (loc))
+           return 0;
+
+         rtl = rtl_for_decl_location (loc);
+         if (rtl == NULL_RTX)
+           return 0;
+
+         if (GET_CODE (rtl) != MEM)
+           return 0;
+         rtl = XEXP (rtl, 0);
+         if (! CONSTANT_P (rtl))
+           return 0;
+
+         ret = new_loc_descr (INTERNAL_DW_OP_tls_addr, 0, 0);
+         ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
+         ret->dw_loc_oprnd1.v.val_addr = rtl;
+
+         ret1 = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
+         add_loc_descr (&ret, ret1);
+
+         indirect_p = 1;
+         break;
+       }
+      /* FALLTHRU */
+
     case PARM_DECL:
       {
        rtx rtl = rtl_for_decl_location (loc);
@@ -8097,6 +8511,7 @@ loc_descriptor_from_tree (loc, addressp)
     case NON_LVALUE_EXPR:
     case VIEW_CONVERT_EXPR:
     case SAVE_EXPR:
+    case MODIFY_EXPR:
       return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp);
 
     case COMPONENT_REF:
@@ -8165,6 +8580,9 @@ loc_descriptor_from_tree (loc, addressp)
       op = DW_OP_or;
       goto do_binop;
 
+    case FLOOR_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case ROUND_DIV_EXPR:
     case TRUNC_DIV_EXPR:
       op = DW_OP_div;
       goto do_binop;
@@ -8173,6 +8591,9 @@ loc_descriptor_from_tree (loc, addressp)
       op = DW_OP_minus;
       goto do_binop;
 
+    case FLOOR_MOD_EXPR:
+    case CEIL_MOD_EXPR:
+    case ROUND_MOD_EXPR:
     case TRUNC_MOD_EXPR:
       op = DW_OP_mod;
       goto do_binop;
@@ -8315,6 +8736,14 @@ loc_descriptor_from_tree (loc, addressp)
       break;
 
     default:
+      /* Leave front-end specific codes as simply unknown.  This comes
+        up, for instance, with the C STMT_EXPR.  */
+      if ((unsigned int) TREE_CODE (loc)
+          >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
+       return 0;
+
+      /* Otherwise this is a generic code; we should just lists all of
+        these explicitly.  Aborting means we forgot one.  */
       abort ();
     }
 
@@ -8344,9 +8773,7 @@ loc_descriptor_from_tree (loc, addressp)
    which is not less than the value itself.  */
 
 static inline HOST_WIDE_INT
-ceiling (value, boundary)
-     HOST_WIDE_INT value;
-     unsigned int boundary;
+ceiling (HOST_WIDE_INT value, unsigned int boundary)
 {
   return (((value + boundary - 1) / boundary) * boundary);
 }
@@ -8357,8 +8784,7 @@ ceiling (value, boundary)
    ERROR_MARK node.  */
 
 static inline tree
-field_type (decl)
-     tree decl;
+field_type (tree decl)
 {
   tree type;
 
@@ -8377,40 +8803,17 @@ field_type (decl)
    be an ERROR_MARK node.  */
 
 static inline unsigned
-simple_type_align_in_bits (type)
-     tree type;
+simple_type_align_in_bits (tree type)
 {
   return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD;
 }
 
 static inline unsigned
-simple_decl_align_in_bits (decl)
-     tree decl;
+simple_decl_align_in_bits (tree decl)
 {
   return (TREE_CODE (decl) != ERROR_MARK) ? DECL_ALIGN (decl) : BITS_PER_WORD;
 }
 
-/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE
-   node, return the size in bits for the type if it is a constant, or else
-   return the alignment for the type if the type's size is not constant, or
-   else return BITS_PER_WORD if the type actually turns out to be an
-   ERROR_MARK node.  */
-
-static inline unsigned HOST_WIDE_INT
-simple_type_size_in_bits (type)
-     tree type;
-{
-
-  if (TREE_CODE (type) == ERROR_MARK)
-    return BITS_PER_WORD;
-  else if (TYPE_SIZE (type) == NULL_TREE)
-    return 0;
-  else if (host_integerp (TYPE_SIZE (type), 1))
-    return tree_low_cst (TYPE_SIZE (type), 1);
-  else
-    return TYPE_ALIGN (type);
-}
-
 /* Given a pointer to a FIELD_DECL, compute and return the byte offset of the
    lowest addressed byte of the "containing object" for the given FIELD_DECL,
    or return 0 if we are unable to determine what that offset is, either
@@ -8419,8 +8822,7 @@ simple_type_size_in_bits (type)
    just yet).  */
 
 static HOST_WIDE_INT
-field_byte_offset (decl)
-     tree decl;
+field_byte_offset (tree decl)
 {
   unsigned int type_align_in_bits;
   unsigned int decl_align_in_bits;
@@ -8538,14 +8940,10 @@ field_byte_offset (decl)
    whole parameters.  Note that the location attributes for struct fields are
    generated by the routine `data_member_location_attribute' below.  */
 
-static void
-add_AT_location_description (die, attr_kind, rtl)
-     dw_die_ref die;
-     enum dwarf_attribute attr_kind;
-     rtx rtl;
+static inline void
+add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind,
+                            dw_loc_descr_ref descr)
 {
-  dw_loc_descr_ref descr = loc_descriptor (rtl);
-
   if (descr != 0)
     add_AT_loc (die, attr_kind, descr);
 }
@@ -8570,9 +8968,7 @@ add_AT_location_description (die, attr_kind, rtl)
    function below.)  */
 
 static void
-add_data_member_location_attribute (die, decl)
-     dw_die_ref die;
-     tree decl;
+add_data_member_location_attribute (dw_die_ref die, tree decl)
 {
   long offset;
   dw_loc_descr_ref loc_descr = 0;
@@ -8648,16 +9044,14 @@ add_data_member_location_attribute (die, decl)
   add_AT_loc (die, DW_AT_data_member_location, loc_descr);
 }
 
-/* Attach an DW_AT_const_value attribute for a variable or a parameter which
+/* Attach a DW_AT_const_value attribute for a variable or a parameter which
    does not have a "location" either in memory or in a register.  These
    things can arise in GNU C when a constant is passed as an actual parameter
    to an inlined function.  They can also arise in C++ where declared
    constants do not necessarily get memory "homes".  */
 
 static void
-add_const_value_attribute (die, rtl)
-     dw_die_ref die;
-     rtx rtl;
+add_const_value_attribute (dw_die_ref die, rtx rtl)
 {
   switch (GET_CODE (rtl))
     {
@@ -8689,16 +9083,16 @@ add_const_value_attribute (die, rtl)
 
     case CONST_DOUBLE:
       /* Note that a CONST_DOUBLE rtx could represent either an integer or a
-         floating-point constant.  A CONST_DOUBLE is used whenever the
-         constant requires more than one word in order to be adequately
-         represented.  We output CONST_DOUBLEs as blocks.  */
+        floating-point constant.  A CONST_DOUBLE is used whenever the
+        constant requires more than one word in order to be adequately
+        represented.  We output CONST_DOUBLEs as blocks.  */
       {
        enum machine_mode mode = GET_MODE (rtl);
 
        if (GET_MODE_CLASS (mode) == MODE_FLOAT)
          {
            unsigned length = GET_MODE_SIZE (mode) / 4;
-           long *array = (long *) xmalloc (sizeof (long) * length);
+           long *array = (long *) ggc_alloc (sizeof (long) * length);
            REAL_VALUE_TYPE rv;
 
            REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
@@ -8748,16 +9142,16 @@ add_const_value_attribute (die, rtl)
 
     case PLUS:
       /* In cases where an inlined instance of an inline function is passed
-         the address of an `auto' variable (which is local to the caller) we
-         can get a situation where the DECL_RTL of the artificial local
-         variable (for the inlining) which acts as a stand-in for the
-         corresponding formal parameter (of the inline function) will look
-         like (plus:SI (reg:SI FRAME_PTR) (const_int ...)).  This is not
-         exactly a compile-time constant expression, but it isn't the address
-         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 nothing.  */
+        the address of an `auto' variable (which is local to the caller) we
+        can get a situation where the DECL_RTL of the artificial local
+        variable (for the inlining) which acts as a stand-in for the
+        corresponding formal parameter (of the inline function) will look
+        like (plus:SI (reg:SI FRAME_PTR) (const_int ...)).  This is not
+        exactly a compile-time constant expression, but it isn't the address
+        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 nothing.  */
       break;
 
     default:
@@ -8768,8 +9162,7 @@ add_const_value_attribute (die, rtl)
 }
 
 static rtx
-rtl_for_decl_location (decl)
-     tree decl;
+rtl_for_decl_location (tree decl)
 {
   rtx rtl;
 
@@ -8850,17 +9243,19 @@ rtl_for_decl_location (decl)
   rtl = DECL_RTL_IF_SET (decl);
 
   /* When generating abstract instances, ignore everything except
-     constants and symbols living in memory.  */
+     constants, symbols living in memory, and symbols living in
+     fixed registers.  */
   if (! reload_completed)
     {
       if (rtl
          && (CONSTANT_P (rtl)
              || (GET_CODE (rtl) == MEM
-                 && CONSTANT_P (XEXP (rtl, 0)))))
+                 && CONSTANT_P (XEXP (rtl, 0)))
+             || (GET_CODE (rtl) == REG
+                 && TREE_CODE (decl) == VAR_DECL
+                 && TREE_STATIC (decl))))
        {
-#ifdef ASM_SIMPLIFY_DWARF_ADDR
-         rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
-#endif
+         rtl = (*targetm.delegitimize_address) (rtl);
          return rtl;
        }
       rtl = NULL_RTX;
@@ -8966,14 +9361,19 @@ rtl_for_decl_location (decl)
        }
     }
 
-#ifdef ASM_SIMPLIFY_DWARF_ADDR
   if (rtl)
-    rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
-#endif
+    rtl = (*targetm.delegitimize_address) (rtl);
+
+  /* If we don't look past the constant pool, we risk emitting a
+     reference to a constant pool entry that isn't referenced from
+     code, and thus is not emitted.  */
+  if (rtl)
+    rtl = avoid_constant_pool_reference (rtl);
+
   return rtl;
 }
 
-/* Generate *either* an DW_AT_location attribute or else an DW_AT_const_value
+/* Generate *either* a DW_AT_location attribute or else a DW_AT_const_value
    data attribute for a variable or a parameter.  We generate the
    DW_AT_const_value attribute only in those cases where the given variable
    or parameter does not have a true "location" either in memory or in a
@@ -8985,11 +9385,10 @@ rtl_for_decl_location (decl)
    function call evaluates to a compile-time constant address.  */
 
 static void
-add_location_or_const_value_attribute (die, decl)
-     dw_die_ref die;
-     tree decl;
+add_location_or_const_value_attribute (dw_die_ref die, tree decl)
 {
   rtx rtl;
+  dw_loc_descr_ref descr;
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return;
@@ -9000,16 +9399,11 @@ add_location_or_const_value_attribute (die, decl)
   if (rtl == NULL_RTX)
     return;
 
-  /* If we don't look past the constant pool, we risk emitting a
-     reference to a constant pool entry that isn't referenced from
-     code, and thus is not emitted.  */
-  rtl = avoid_constant_pool_reference (rtl);
-
   switch (GET_CODE (rtl))
     {
     case ADDRESSOF:
-      /* The address of a variable that was optimized away; don't emit
-        anything.  */
+      /* The address of a variable that was optimized away;
+        don't emit anything.  */
       break;
 
     case CONST_INT:
@@ -9024,10 +9418,22 @@ add_location_or_const_value_attribute (die, decl)
       break;
 
     case MEM:
-    case REG:
-    case SUBREG:
-    case CONCAT:
-      add_AT_location_description (die, DW_AT_location, rtl);
+      if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+       {
+         /* Need loc_descriptor_from_tree since that's where we know
+            how to handle TLS variables.  Want the object's address
+            since the top-level DW_AT_location assumes such.  See
+            the confusion in loc_descriptor for reference.  */
+         descr = loc_descriptor_from_tree (decl, 1);
+       }
+      else
+       {
+       case REG:
+       case SUBREG:
+       case CONCAT:
+         descr = loc_descriptor (rtl);
+       }
+      add_AT_location_description (die, DW_AT_location, descr);
       break;
 
     default:
@@ -9040,9 +9446,7 @@ add_location_or_const_value_attribute (die, decl)
    we should tell the debugger about the constant value.  */
 
 static void
-tree_add_const_value_attribute (var_die, decl)
-     dw_die_ref var_die;
-     tree decl;
+tree_add_const_value_attribute (dw_die_ref var_die, tree decl)
 {
   tree init = DECL_INITIAL (decl);
   tree type = TREE_TYPE (decl);
@@ -9069,13 +9473,11 @@ tree_add_const_value_attribute (var_die, decl)
     }
 }
 
-/* Generate an DW_AT_name attribute given some string value to be included as
+/* Generate a DW_AT_name attribute given some string value to be included as
    the value of the attribute.  */
 
-static inline void
-add_name_attribute (die, name_string)
-     dw_die_ref die;
-     const char *name_string;
+static void
+add_name_attribute (dw_die_ref die, const char *name_string)
 {
   if (name_string != NULL && *name_string != 0)
     {
@@ -9086,14 +9488,21 @@ add_name_attribute (die, name_string)
     }
 }
 
+/* Generate a DW_AT_comp_dir attribute for DIE.  */
+
+static void
+add_comp_dir_attribute (dw_die_ref die)
+{
+  const char *wd = getpwd ();
+  if (wd != NULL)
+    add_AT_string (die, DW_AT_comp_dir, wd);
+}
+
 /* Given a tree node describing an array bound (either lower or upper) output
    a representation for that bound.  */
 
 static void
-add_bound_info (subrange_die, bound_attr, bound)
-     dw_die_ref subrange_die;
-     enum dwarf_attribute bound_attr;
-     tree bound;
+add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
 {
   switch (TREE_CODE (bound))
     {
@@ -9121,23 +9530,23 @@ add_bound_info (subrange_die, bound_attr, bound)
 
     case SAVE_EXPR:
       /* If optimization is turned on, the SAVE_EXPRs that describe how to
-         access the upper bound values may be bogus.  If they refer to a
-         register, they may only describe how to get at these values at the
-         points in the generated code right after they have just been
-         computed.  Worse yet, in the typical case, the upper bound values
-         will not even *be* computed in the optimized code (though the
-         number of elements will), so these SAVE_EXPRs are entirely
-         bogus. In order to compensate for this fact, we check here to see
-         if optimization is enabled, and if so, we don't add an attribute
-         for the (unknown and unknowable) upper bound.  This should not
-         cause too much trouble for existing (stupid?)  debuggers because
-         they have to deal with empty upper bounds location descriptions
-         anyway in order to be able to deal with incomplete array types.
-         Of course an intelligent debugger (GDB?)  should be able to
-         comprehend that a missing upper bound specification in an array
-         type used for a storage class `auto' local array variable
-         indicates that the upper bound is both unknown (at compile- time)
-         and unknowable (at run-time) due to optimization.
+        access the upper bound values may be bogus.  If they refer to a
+        register, they may only describe how to get at these values at the
+        points in the generated code right after they have just been
+        computed.  Worse yet, in the typical case, the upper bound values
+        will not even *be* computed in the optimized code (though the
+        number of elements will), so these SAVE_EXPRs are entirely
+        bogus. In order to compensate for this fact, we check here to see
+        if optimization is enabled, and if so, we don't add an attribute
+        for the (unknown and unknowable) upper bound.  This should not
+        cause too much trouble for existing (stupid?)  debuggers because
+        they have to deal with empty upper bounds location descriptions
+        anyway in order to be able to deal with incomplete array types.
+        Of course an intelligent debugger (GDB?)  should be able to
+        comprehend that a missing upper bound specification in an array
+        type used for a storage class `auto' local array variable
+        indicates that the upper bound is both unknown (at compile- time)
+        and unknowable (at run-time) due to optimization.
 
         We assume that a MEM rtx is safe because gcc wouldn't put the
         value there unless it was going to be used repeatedly in the
@@ -9161,7 +9570,8 @@ add_bound_info (subrange_die, bound_attr, bound)
 
          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, loc);
+         add_AT_location_description (decl_die, DW_AT_location,
+                                      loc_descriptor (loc));
          add_AT_die_ref (subrange_die, bound_attr, decl_die);
        }
 
@@ -9224,9 +9634,7 @@ add_bound_info (subrange_die, bound_attr, bound)
    includes information about the element type of type given array type.  */
 
 static void
-add_subscript_info (type_die, type)
-     dw_die_ref type_die;
-     tree type;
+add_subscript_info (dw_die_ref type_die, tree type)
 {
 #ifndef MIPS_DEBUGGING_INFO
   unsigned dimension_number;
@@ -9257,7 +9665,7 @@ add_subscript_info (type_die, type)
 
       /* Arrays come in three flavors: Unspecified bounds, fixed bounds,
         and (in GNU C only) variable bounds.  Handle all three forms
-         here.  */
+        here.  */
       subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
       if (domain)
        {
@@ -9284,7 +9692,7 @@ add_subscript_info (type_die, type)
          /* ??? 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
+            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.  */
 
@@ -9300,9 +9708,7 @@ add_subscript_info (type_die, type)
 }
 
 static void
-add_byte_size_attribute (die, tree_node)
-     dw_die_ref die;
-     tree tree_node;
+add_byte_size_attribute (dw_die_ref die, tree tree_node)
 {
   unsigned size;
 
@@ -9319,9 +9725,9 @@ add_byte_size_attribute (die, tree_node)
       break;
     case FIELD_DECL:
       /* For a data member of a struct or union, the DW_AT_byte_size is
-         generally given as the number of bytes normally allocated for an
-         object of the *declared* type of the member itself.  This is true
-         even for bit-fields.  */
+        generally given as the number of bytes normally allocated for an
+        object of the *declared* type of the member itself.  This is true
+        even for bit-fields.  */
       size = simple_type_size_in_bits (field_type (tree_node)) / BITS_PER_UNIT;
       break;
     default:
@@ -9352,9 +9758,7 @@ add_byte_size_attribute (die, tree_node)
    (See `byte_size_attribute' above).  */
 
 static inline void
-add_bit_offset_attribute (die, decl)
-     dw_die_ref die;
-     tree decl;
+add_bit_offset_attribute (dw_die_ref die, tree decl)
 {
   HOST_WIDE_INT object_offset_in_bytes = field_byte_offset (decl);
   tree type = DECL_BIT_FIELD_TYPE (decl);
@@ -9403,9 +9807,7 @@ add_bit_offset_attribute (die, decl)
    which specifies the length in bits of the given field.  */
 
 static inline void
-add_bit_size_attribute (die, decl)
-     dw_die_ref die;
-     tree decl;
+add_bit_size_attribute (dw_die_ref die, tree decl)
 {
   /* Must be a field and a bit field.  */
   if (TREE_CODE (decl) != FIELD_DECL
@@ -9420,9 +9822,7 @@ add_bit_size_attribute (die, decl)
    attribute, if arg types are given for the parameters of a function.  */
 
 static inline void
-add_prototyped_attribute (die, func_type)
-     dw_die_ref die;
-     tree func_type;
+add_prototyped_attribute (dw_die_ref die, tree func_type)
 {
   if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89
       && TYPE_ARG_TYPES (func_type) != NULL)
@@ -9434,9 +9834,7 @@ add_prototyped_attribute (die, func_type)
    equate table.  */
 
 static inline void
-add_abstract_origin_attribute (die, origin)
-     dw_die_ref die;
-     tree origin;
+add_abstract_origin_attribute (dw_die_ref die, tree origin)
 {
   dw_die_ref origin_die = NULL;
 
@@ -9446,7 +9844,7 @@ add_abstract_origin_attribute (die, origin)
         function, if we're in an exception handler or some such; make
         sure that the abstract function has been written out.
 
-         Doing this for nested functions is wrong, however; functions are
+        Doing this for nested functions is wrong, however; functions are
         distinct units, and our context might not even be inline.  */
       tree fn = origin;
 
@@ -9472,9 +9870,7 @@ add_abstract_origin_attribute (die, origin)
 /* We do not currently support the pure_virtual attribute.  */
 
 static inline void
-add_pure_or_virtual_attribute (die, func_decl)
-     dw_die_ref die;
-     tree func_decl;
+add_pure_or_virtual_attribute (dw_die_ref die, tree func_decl)
 {
   if (DECL_VINDEX (func_decl))
     {
@@ -9496,9 +9892,7 @@ add_pure_or_virtual_attribute (die, func_decl)
 /* Add source coordinate attributes for the given decl.  */
 
 static void
-add_src_coords_attributes (die, decl)
-     dw_die_ref die;
-     tree decl;
+add_src_coords_attributes (dw_die_ref die, tree decl)
 {
   unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl));
 
@@ -9506,13 +9900,11 @@ add_src_coords_attributes (die, decl)
   add_AT_unsigned (die, DW_AT_decl_line, DECL_SOURCE_LINE (decl));
 }
 
-/* Add an DW_AT_name attribute and source coordinate attribute for the
+/* Add a DW_AT_name attribute and source coordinate attribute for the
    given decl, but only if it actually has a name.  */
 
 static void
-add_name_and_src_coords_attributes (die, decl)
-     dw_die_ref die;
-     tree decl;
+add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
 {
   tree decl_name;
 
@@ -9546,8 +9938,7 @@ add_name_and_src_coords_attributes (die, decl)
 /* Push a new declaration scope.  */
 
 static void
-push_decl_scope (scope)
-     tree scope;
+push_decl_scope (tree scope)
 {
   VARRAY_PUSH_TREE (decl_scope_table, scope);
 }
@@ -9555,7 +9946,7 @@ push_decl_scope (scope)
 /* Pop a declaration scope.  */
 
 static inline void
-pop_decl_scope ()
+pop_decl_scope (void)
 {
   if (VARRAY_ACTIVE_SIZE (decl_scope_table) <= 0)
     abort ();
@@ -9570,9 +9961,7 @@ pop_decl_scope ()
    the current active scope.  */
 
 static dw_die_ref
-scope_die_for (t, context_die)
-     tree t;
-     dw_die_ref context_die;
+scope_die_for (tree t, dw_die_ref context_die)
 {
   dw_die_ref scope_die = NULL;
   tree containing_scope;
@@ -9626,8 +10015,7 @@ scope_die_for (t, context_die)
 /* Returns nonzero if CONTEXT_DIE is internal to a function.  */
 
 static inline int
-local_scope_p (context_die)
-     dw_die_ref context_die;
+local_scope_p (dw_die_ref context_die)
 {
   for (; context_die; context_die = context_die->die_parent)
     if (context_die->die_tag == DW_TAG_inlined_subroutine
@@ -9640,8 +10028,7 @@ local_scope_p (context_die)
 /* Returns nonzero if CONTEXT_DIE is a class.  */
 
 static inline int
-class_scope_p (context_die)
-     dw_die_ref context_die;
+class_scope_p (dw_die_ref context_die)
 {
   return (context_die
          && (context_die->die_tag == DW_TAG_structure_type
@@ -9650,15 +10037,11 @@ class_scope_p (context_die)
 
 /* Many forms of DIEs require a "type description" attribute.  This
    routine locates the proper "type descriptor" die for the type given
-   by 'type', and adds an DW_AT_type attribute below the given die.  */
+   by 'type', and adds a DW_AT_type attribute below the given die.  */
 
 static void
-add_type_attribute (object_die, type, decl_const, decl_volatile, context_die)
-     dw_die_ref object_die;
-     tree type;
-     int decl_const;
-     int decl_volatile;
-     dw_die_ref context_die;
+add_type_attribute (dw_die_ref object_die, tree type, int decl_const,
+                   int decl_volatile, dw_die_ref context_die)
 {
   enum tree_code code  = TREE_CODE (type);
   dw_die_ref type_die  = NULL;
@@ -9692,8 +10075,7 @@ add_type_attribute (object_die, type, decl_const, decl_volatile, context_die)
    was declared without a tag.  */
 
 static const char *
-type_tag (type)
-     tree type;
+type_tag (tree type)
 {
   const char *name = 0;
 
@@ -9706,8 +10088,8 @@ type_tag (type)
        t = TYPE_NAME (type);
 
       /* The g++ front end makes the TYPE_NAME of *each* tagged type point to
-         a TYPE_DECL node, regardless of whether or not a `typedef' was
-         involved.  */
+        a TYPE_DECL node, regardless of whether or not a `typedef' was
+        involved.  */
       else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
               && ! DECL_IGNORED_P (TYPE_NAME (type)))
        t = DECL_NAME (TYPE_NAME (type));
@@ -9724,8 +10106,7 @@ type_tag (type)
    for bit field types.  */
 
 static inline tree
-member_declared_type (member)
-     tree member;
+member_declared_type (tree member)
 {
   return (DECL_BIT_FIELD_TYPE (member)
          ? DECL_BIT_FIELD_TYPE (member) : TREE_TYPE (member));
@@ -9736,8 +10117,7 @@ member_declared_type (member)
 
 #if 0
 static const char *
-decl_start_label (decl)
-     tree decl;
+decl_start_label (tree decl)
 {
   rtx x;
   const char *fnname;
@@ -9760,9 +10140,7 @@ decl_start_label (decl)
    the declaration trees passed in from dwarf2out_decl().  */
 
 static void
-gen_array_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_array_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref scope_die = scope_die_for (type, context_die);
   dw_die_ref array_die;
@@ -9825,9 +10203,7 @@ gen_array_type_die (type, context_die)
 }
 
 static void
-gen_set_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_set_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref type_die
     = new_die (DW_TAG_set_type, scope_die_for (type, context_die), type);
@@ -9838,9 +10214,7 @@ gen_set_type_die (type, context_die)
 
 #if 0
 static void
-gen_entry_point_die (decl, context_die)
-     tree decl;
-     dw_die_ref context_die;
+gen_entry_point_die (tree decl, dw_die_ref context_die)
 {
   tree origin = decl_ultimate_origin (decl);
   dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die, decl);
@@ -9865,7 +10239,7 @@ gen_entry_point_die (decl, context_die)
    emit full debugging info for them.  */
 
 static void
-retry_incomplete_types ()
+retry_incomplete_types (void)
 {
   int i;
 
@@ -9876,9 +10250,7 @@ retry_incomplete_types ()
 /* Generate a DIE to represent an inlined instance of an enumeration type.  */
 
 static void
-gen_inlined_enumeration_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_inlined_enumeration_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die, type);
 
@@ -9890,9 +10262,7 @@ gen_inlined_enumeration_type_die (type, context_die)
 /* Generate a DIE to represent an inlined instance of a structure type.  */
 
 static void
-gen_inlined_structure_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_inlined_structure_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die, type);
 
@@ -9904,9 +10274,7 @@ gen_inlined_structure_type_die (type, context_die)
 /* Generate a DIE to represent an inlined instance of a union type.  */
 
 static void
-gen_inlined_union_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_inlined_union_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref type_die = new_die (DW_TAG_union_type, context_die, type);
 
@@ -9921,9 +10289,7 @@ gen_inlined_union_type_die (type, context_die)
    DIE.  */
 
 static void
-gen_enumeration_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_enumeration_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref type_die = lookup_type_die (type);
 
@@ -9993,9 +10359,7 @@ gen_enumeration_type_die (type, context_die)
    argument type of some subprogram type.  */
 
 static dw_die_ref
-gen_formal_parameter_die (node, context_die)
-     tree node;
-     dw_die_ref context_die;
+gen_formal_parameter_die (tree node, dw_die_ref context_die)
 {
   dw_die_ref parm_die
     = new_die (DW_TAG_formal_parameter, context_die, node);
@@ -10040,9 +10404,7 @@ gen_formal_parameter_die (node, context_die)
    at the end of an (ANSI prototyped) formal parameters list.  */
 
 static void
-gen_unspecified_parameters_die (decl_or_type, context_die)
-     tree decl_or_type;
-     dw_die_ref context_die;
+gen_unspecified_parameters_die (tree decl_or_type, dw_die_ref context_die)
 {
   new_die (DW_TAG_unspecified_parameters, context_die, decl_or_type);
 }
@@ -10053,9 +10415,7 @@ gen_unspecified_parameters_die (decl_or_type, context_die)
    those which appear as part of a function *definition*).  */
 
 static void
-gen_formal_types_die (function_or_method_type, context_die)
-     tree function_or_method_type;
-     dw_die_ref context_die;
+gen_formal_types_die (tree function_or_method_type, dw_die_ref context_die)
 {
   tree link;
   tree formal_type = NULL;
@@ -10114,9 +10474,7 @@ gen_formal_types_die (function_or_method_type, context_die)
    trick; we need to attach the member declaration by hand.  */
 
 static void
-gen_type_die_for_member (type, member, context_die)
-     tree type, member;
-     dw_die_ref context_die;
+gen_type_die_for_member (tree type, tree member, dw_die_ref context_die)
 {
   gen_type_die (type, context_die);
 
@@ -10142,8 +10500,7 @@ gen_type_die_for_member (type, member, context_die)
    may later generate inlined and/or out-of-line instances of.  */
 
 static void
-dwarf2out_abstract_function (decl)
-     tree decl;
+dwarf2out_abstract_function (tree decl)
 {
   dw_die_ref old_die;
   tree save_fn;
@@ -10184,9 +10541,7 @@ dwarf2out_abstract_function (decl)
    block-local).  */
 
 static void
-gen_subprogram_die (decl, context_die)
-     tree decl;
-     dw_die_ref context_die;
+gen_subprogram_die (tree decl, dw_die_ref context_die)
 {
   char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
   tree origin = decl_ultimate_origin (decl);
@@ -10340,10 +10695,10 @@ gen_subprogram_die (decl, context_die)
        equate_decl_number_to_die (decl, subr_die);
 
       ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL,
-                                  current_funcdef_number);
+                                  current_function_funcdef_no);
       add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id);
       ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
-                                  current_funcdef_number);
+                                  current_function_funcdef_no);
       add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id);
 
       add_pubname (decl, subr_die);
@@ -10355,8 +10710,8 @@ gen_subprogram_die (decl, context_die)
 #endif
 
       /* Define the "frame base" location for this routine.  We use the
-         frame pointer or stack pointer registers, since the RTL for local
-         variables is relative to one of them.  */
+        frame pointer or stack pointer registers, since the RTL for local
+        variables is relative to one of them.  */
       fp_reg
        = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx;
       add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg));
@@ -10366,7 +10721,7 @@ gen_subprogram_die (decl, context_die)
         is not part of the state saved/restored for inline functions.  */
       if (current_function_needs_context)
        add_AT_location_description (subr_die, DW_AT_static_link,
-                                    lookup_static_chain (decl));
+                            loc_descriptor (lookup_static_chain (decl)));
 #endif
     }
 
@@ -10389,12 +10744,12 @@ gen_subprogram_die (decl, context_die)
     gen_formal_types_die (decl, subr_die);
   else
     {
-      /* Generate DIEs to represent all known formal parameters */
+      /* Generate DIEs to represent all known formal parameters */
       tree arg_decls = DECL_ARGUMENTS (decl);
       tree parm;
 
       /* When generating DIEs, generate the unspecified_parameters DIE
-         instead if we come across the arg "__builtin_va_alist" */
+        instead if we come across the arg "__builtin_va_alist" */
       for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
        if (TREE_CODE (parm) == PARM_DECL)
          {
@@ -10407,11 +10762,11 @@ gen_subprogram_die (decl, context_die)
          }
 
       /* Decide whether we need an unspecified_parameters DIE at the end.
-         There are 2 more cases to do this for: 1) the ansi ... declaration -
-         this is detectable when the end of the arg list is not a
-         void_type_node 2) an unprototyped function declaration (not a
-         definition).  This just means that we have no info about the
-         parameters at all.  */
+        There are 2 more cases to do this for: 1) the ansi ... declaration -
+        this is detectable when the end of the arg list is not a
+        void_type_node 2) an unprototyped function declaration (not a
+        definition).  This just means that we have no info about the
+        parameters at all.  */
       fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
       if (fn_arg_types != NULL)
        {
@@ -10463,9 +10818,7 @@ gen_subprogram_die (decl, context_die)
 /* Generate a DIE to represent a declared data object.  */
 
 static void
-gen_variable_die (decl, context_die)
-     tree decl;
-     dw_die_ref context_die;
+gen_variable_die (tree decl, dw_die_ref context_die)
 {
   tree origin = decl_ultimate_origin (decl);
   dw_die_ref var_die = new_die (DW_TAG_variable, context_die, decl);
@@ -10540,9 +10893,7 @@ gen_variable_die (decl, context_die)
 /* Generate a DIE to represent a label identifier.  */
 
 static void
-gen_label_die (decl, context_die)
-     tree decl;
-     dw_die_ref context_die;
+gen_label_die (tree decl, dw_die_ref context_die)
 {
   tree origin = decl_ultimate_origin (decl);
   dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl);
@@ -10561,7 +10912,7 @@ gen_label_die (decl, context_die)
       insn = DECL_RTL (decl);
 
       /* Deleted labels are programmer specified labels which have been
-        eliminated because of various optimisations.  We still emit them
+        eliminated because of various optimizations.  We still emit them
         here so that it is possible to put breakpoints on them.  */
       if (GET_CODE (insn) == CODE_LABEL
          || ((GET_CODE (insn) == NOTE
@@ -10584,10 +10935,7 @@ gen_label_die (decl, context_die)
 /* Generate a DIE for a lexical block.  */
 
 static void
-gen_lexical_block_die (stmt, context_die, depth)
-     tree stmt;
-     dw_die_ref context_die;
-     int depth;
+gen_lexical_block_die (tree stmt, dw_die_ref context_die, int depth)
 {
   dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -10626,10 +10974,7 @@ gen_lexical_block_die (stmt, context_die, depth)
 /* Generate a DIE for an inlined subprogram.  */
 
 static void
-gen_inlined_subroutine_die (stmt, context_die, depth)
-     tree stmt;
-     dw_die_ref context_die;
-     int depth;
+gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die, int depth)
 {
   if (! BLOCK_ABSTRACT (stmt))
     {
@@ -10670,12 +11015,14 @@ gen_inlined_subroutine_die (stmt, context_die, depth)
 /* Generate a DIE for a field in a record, or structure.  */
 
 static void
-gen_field_die (decl, context_die)
-     tree decl;
-     dw_die_ref context_die;
+gen_field_die (tree decl, dw_die_ref context_die)
 {
-  dw_die_ref decl_die = new_die (DW_TAG_member, context_die, decl);
+  dw_die_ref decl_die;
+
+  if (TREE_TYPE (decl) == error_mark_node)
+    return;
 
+  decl_die = new_die (DW_TAG_member, context_die, decl);
   add_name_and_src_coords_attributes (decl_die, decl);
   add_type_attribute (decl_die, member_declared_type (decl),
                      TREE_READONLY (decl), TREE_THIS_VOLATILE (decl),
@@ -10707,9 +11054,7 @@ gen_field_die (decl, context_die)
    represent certain things in other languages (e.g. Pascal) someday.  */
 
 static void
-gen_pointer_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_pointer_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref ptr_die
     = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type);
@@ -10725,9 +11070,7 @@ gen_pointer_type_die (type, context_die)
    represent certain things in other languages (e.g. Pascal) someday.  */
 
 static void
-gen_reference_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_reference_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref ref_die
     = new_die (DW_TAG_reference_type, scope_die_for (type, context_die), type);
@@ -10741,9 +11084,7 @@ gen_reference_type_die (type, context_die)
 /* Generate a DIE for a pointer to a member type.  */
 
 static void
-gen_ptr_to_mbr_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref ptr_die
     = new_die (DW_TAG_ptr_to_member_type,
@@ -10758,20 +11099,22 @@ gen_ptr_to_mbr_type_die (type, context_die)
 /* Generate the DIE for the compilation unit.  */
 
 static dw_die_ref
-gen_compile_unit_die (filename)
-     const char *filename;
+gen_compile_unit_die (const char *filename)
 {
   dw_die_ref die;
   char producer[250];
-  const char *wd = getpwd ();
   const char *language_string = lang_hooks.name;
   int language;
 
   die = new_die (DW_TAG_compile_unit, NULL, NULL);
-  add_name_attribute (die, filename);
 
-  if (wd != NULL && filename[0] != DIR_SEPARATOR)
-    add_AT_string (die, DW_AT_comp_dir, wd);
+  if (filename)
+    {
+      add_name_attribute (die, filename);
+      /* Don't add cwd for <built-in>.  */
+      if (filename[0] != DIR_SEPARATOR && filename[0] != '<')
+       add_comp_dir_attribute (die);
+    }
 
   sprintf (producer, "%s %s", language_string, version_string);
 
@@ -10791,7 +11134,7 @@ gen_compile_unit_die (filename)
   if (strcmp (language_string, "GNU C++") == 0)
     language = DW_LANG_C_plus_plus;
   else if (strcmp (language_string, "GNU Ada") == 0)
-    language = DW_LANG_Ada83;
+    language = DW_LANG_Ada95;
   else if (strcmp (language_string, "GNU F77") == 0)
     language = DW_LANG_Fortran77;
   else if (strcmp (language_string, "GNU Pascal") == 0)
@@ -10808,9 +11151,7 @@ gen_compile_unit_die (filename)
 /* Generate a DIE for a string type.  */
 
 static void
-gen_string_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_string_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref type_die
     = new_die (DW_TAG_string_type, scope_die_for (type, context_die), type);
@@ -10828,9 +11169,7 @@ gen_string_type_die (type, context_die)
 /* Generate the DIE for a base class.  */
 
 static void
-gen_inheritance_die (binfo, context_die)
-     tree binfo;
-     dw_die_ref context_die;
+gen_inheritance_die (tree binfo, tree access, dw_die_ref context_die)
 {
   dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo);
 
@@ -10840,20 +11179,19 @@ gen_inheritance_die (binfo, context_die)
   if (TREE_VIA_VIRTUAL (binfo))
     add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
 
-  if (TREE_VIA_PUBLIC (binfo))
+  if (access == access_public_node)
     add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public);
-  else if (TREE_VIA_PROTECTED (binfo))
+  else if (access == access_protected_node)
     add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected);
 }
 
 /* Generate a DIE for a class member.  */
 
 static void
-gen_member_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_member_die (tree type, dw_die_ref context_die)
 {
   tree member;
+  tree binfo = TYPE_BINFO (type);
   dw_die_ref child;
 
   /* If this is not an incomplete type, output descriptions of each of its
@@ -10869,14 +11207,17 @@ gen_member_die (type, context_die)
      the TREE node representing the appropriate (containing) type.  */
 
   /* First output info about the base classes.  */
-  if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type))
+  if (binfo && BINFO_BASETYPES (binfo))
     {
-      tree bases = TYPE_BINFO_BASETYPES (type);
+      tree bases = BINFO_BASETYPES (binfo);
+      tree accesses = BINFO_BASEACCESSES (binfo);
       int n_bases = TREE_VEC_LENGTH (bases);
       int i;
 
       for (i = 0; i < n_bases; i++)
-       gen_inheritance_die (TREE_VEC_ELT (bases, i), context_die);
+       gen_inheritance_die (TREE_VEC_ELT (bases, i),
+                            (accesses ? TREE_VEC_ELT (accesses, i)
+                             : access_public_node), context_die);
     }
 
   /* Now output info about the data members and type members.  */
@@ -10914,9 +11255,7 @@ gen_member_die (type, context_die)
    member DIEs needed by later specification DIEs.  */
 
 static void
-gen_struct_or_union_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_struct_or_union_type_die (tree type, dw_die_ref context_die)
 {
   dw_die_ref type_die = lookup_type_die (type);
   dw_die_ref scope_die = 0;
@@ -10956,7 +11295,7 @@ gen_struct_or_union_type_die (type, context_die)
   if (complete)
     {
       /* Prevent infinite recursion in cases where the type of some member of
-         this type is expressed in terms of this type itself.  */
+        this type is expressed in terms of this type itself.  */
       TREE_ASM_WRITTEN (type) = 1;
       add_byte_size_attribute (type_die, type);
       if (TYPE_STUB_DECL (type) != NULL_TREE)
@@ -10995,9 +11334,7 @@ gen_struct_or_union_type_die (type, context_die)
 /* Generate a DIE for a subroutine _type_.  */
 
 static void
-gen_subroutine_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_subroutine_type_die (tree type, dw_die_ref context_die)
 {
   tree return_type = TREE_TYPE (type);
   dw_die_ref subr_die
@@ -11010,12 +11347,10 @@ gen_subroutine_type_die (type, context_die)
   gen_formal_types_die (type, subr_die);
 }
 
-/* Generate a DIE for a type definition */
+/* Generate a DIE for a type definition */
 
 static void
-gen_typedef_die (decl, context_die)
-     tree decl;
-     dw_die_ref context_die;
+gen_typedef_die (tree decl, dw_die_ref context_die)
 {
   dw_die_ref type_die;
   tree origin;
@@ -11056,29 +11391,19 @@ gen_typedef_die (decl, context_die)
 /* Generate a type description DIE.  */
 
 static void
-gen_type_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_type_die (tree type, dw_die_ref context_die)
 {
   int need_pop;
 
   if (type == NULL_TREE || type == error_mark_node)
     return;
 
-  /* 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.  (Vectors are special because the debugging info is in the
-     cloned type itself).  */
-  if (TREE_CODE (type) != VECTOR_TYPE)
-    type = type_main_variant (type);
-
-  if (TREE_ASM_WRITTEN (type))
-    return;
-
   if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
       && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
     {
+      if (TREE_ASM_WRITTEN (type))
+       return;
+
       /* Prevent broken recursion; we can't hand off to the same type.  */
       if (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) == type)
        abort ();
@@ -11088,6 +11413,17 @@ gen_type_die (type, context_die)
       return;
     }
 
+  /* 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.  (Vectors are special because the debugging info is in the
+     cloned type itself).  */
+  if (TREE_CODE (type) != VECTOR_TYPE)
+    type = type_main_variant (type);
+
+  if (TREE_ASM_WRITTEN (type))
+    return;
+
   switch (TREE_CODE (type))
     {
     case ERROR_MARK:
@@ -11103,7 +11439,7 @@ gen_type_die (type, context_die)
       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.  */
+        set of DIEs) to represent the "basis" type.  */
       gen_type_die (TREE_TYPE (type), context_die);
       break;
 
@@ -11116,7 +11452,7 @@ gen_type_die (type, context_die)
       gen_type_die (TREE_TYPE (type), context_die);
 
       /* Now output a DIE to represent this pointer-to-data-member type
-         itself.  */
+        itself.  */
       gen_ptr_to_mbr_type_die (type, context_die);
       break;
 
@@ -11161,11 +11497,11 @@ gen_type_die (type, context_die)
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
       /* If this is a nested type whose containing class hasn't been written
-         out yet, writing it out will cover this one, too.  This does not apply
-         to instantiations of member class templates; they need to be added to
-         the containing class as they are generated.  FIXME: This hurts the
-         idea of combining type decls from multiple TUs, since we can't predict
-         what set of template instantiations we'll get.  */
+        out yet, writing it out will cover this one, too.  This does not apply
+        to instantiations of member class templates; they need to be added to
+        the containing class as they are generated.  FIXME: This hurts the
+        idea of combining type decls from multiple TUs, since we can't predict
+        what set of template instantiations we'll get.  */
       if (TYPE_CONTEXT (type)
          && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
          && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
@@ -11219,9 +11555,7 @@ gen_type_die (type, context_die)
 /* Generate a DIE for a tagged type instantiation.  */
 
 static void
-gen_tagged_type_instantiation_die (type, context_die)
-     tree type;
-     dw_die_ref context_die;
+gen_tagged_type_instantiation_die (tree type, dw_die_ref context_die)
 {
   if (type == NULL_TREE || type == error_mark_node)
     return;
@@ -11263,10 +11597,7 @@ gen_tagged_type_instantiation_die (type, context_die)
    things which are local to the given block.  */
 
 static void
-gen_block_die (stmt, context_die, depth)
-     tree stmt;
-     dw_die_ref context_die;
-     int depth;
+gen_block_die (tree stmt, dw_die_ref context_die, int depth)
 {
   int must_output_die = 0;
   tree origin;
@@ -11308,12 +11639,12 @@ gen_block_die (stmt, context_die, depth)
   else
     {
       /* In the case where the current block represents an inlining of the
-         "body block" of an inline function, we must *NOT* output any DIE for
-         this block because we have already output a DIE to represent the whole
-         inlined function scope and the "body block" of any function doesn't
-         really represent a different scope according to ANSI C rules.  So we
-         check here to make sure that this block does not represent a "body
-         block inlining" before trying to set the MUST_OUTPUT_DIE flag.  */
+        "body block" of an inline function, we must *NOT* output any DIE for
+        this block because we have already output a DIE to represent the whole
+        inlined function scope and the "body block" of any function doesn't
+        really represent a different scope according to ANSI C rules.  So we
+        check here to make sure that this block does not represent a "body
+        block inlining" before trying to set the MUST_OUTPUT_DIE flag.  */
       if (! is_body_block (origin ? origin : stmt))
        {
          /* Determine if this block directly contains any "significant"
@@ -11358,10 +11689,7 @@ gen_block_die (stmt, context_die, depth)
    all of its sub-blocks.  */
 
 static void
-decls_for_scope (stmt, context_die, depth)
-     tree stmt;
-     dw_die_ref context_die;
-     int depth;
+decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
 {
   tree decl;
   tree subblocks;
@@ -11391,6 +11719,10 @@ decls_for_scope (stmt, context_die, depth)
        gen_decl_die (decl, context_die);
     }
 
+  /* If we're at -g1, we're not interested in subblocks.  */
+  if (debug_info_level <= DINFO_LEVEL_TERSE)
+    return;
+
   /* Output the DIEs to represent all sub-blocks (and the items declared
      therein) of this block.  */
   for (subblocks = BLOCK_SUBBLOCKS (stmt);
@@ -11402,8 +11734,7 @@ decls_for_scope (stmt, context_die, depth)
 /* Is this a typedef we can avoid emitting?  */
 
 static inline int
-is_redundant_typedef (decl)
-     tree decl;
+is_redundant_typedef (tree decl)
 {
   if (TYPE_DECL_IS_STUB (decl))
     return 1;
@@ -11422,9 +11753,7 @@ is_redundant_typedef (decl)
 /* Generate Dwarf debug information for a decl described by DECL.  */
 
 static void
-gen_decl_die (decl, context_die)
-     tree decl;
-     dw_die_ref context_die;
+gen_decl_die (tree decl, dw_die_ref context_die)
 {
   tree origin;
 
@@ -11438,7 +11767,7 @@ gen_decl_die (decl, context_die)
 
     case CONST_DECL:
       /* The individual enumerators of an enum type get output when we output
-         the Dwarf representation of the relevant enum type itself.  */
+        the Dwarf representation of the relevant enum type itself.  */
       break;
 
     case FUNCTION_DECL:
@@ -11488,16 +11817,16 @@ gen_decl_die (decl, context_die)
 
     case TYPE_DECL:
       /* If we are in terse mode, don't generate any DIEs to represent any
-         actual typedefs.  */
+        actual typedefs.  */
       if (debug_info_level <= DINFO_LEVEL_TERSE)
        break;
 
       /* In the special case of a TYPE_DECL node representing the declaration
-         of some type tag, if the given TYPE_DECL is marked as having been
-         instantiated from some other (original) TYPE_DECL node (e.g. one which
-         was generated within the original definition of an inline function) we
-         have to generate a special (abbreviated) DW_TAG_structure_type,
-         DW_TAG_union_type, or DW_TAG_enumeration_type DIE here.  */
+        of some type tag, if the given TYPE_DECL is marked as having been
+        instantiated from some other (original) TYPE_DECL node (e.g. one which
+        was generated within the original definition of an inline function) we
+        have to generate a special (abbreviated) DW_TAG_structure_type,
+        DW_TAG_union_type, or DW_TAG_enumeration_type DIE here.  */
       if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE)
        {
          gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die);
@@ -11518,12 +11847,12 @@ gen_decl_die (decl, context_die)
 
     case VAR_DECL:
       /* If we are in terse mode, don't generate any DIEs to represent any
-         variable declarations or definitions.  */
+        variable declarations or definitions.  */
       if (debug_info_level <= DINFO_LEVEL_TERSE)
        break;
 
       /* Output any DIEs that are needed to specify the type of this data
-         object.  */
+        object.  */
       gen_type_die (TREE_TYPE (decl), context_die);
 
       /* And its containing type.  */
@@ -11532,9 +11861,9 @@ gen_decl_die (decl, context_die)
        gen_type_die_for_member (origin, decl, context_die);
 
       /* Now output the DIE to represent the data object itself.  This gets
-         complicated because of the possibility that the VAR_DECL really
-         represents an inlined instance of a formal parameter for an inline
-         function.  */
+        complicated because of the possibility that the VAR_DECL really
+        represents an inlined instance of a formal parameter for an inline
+        function.  */
       origin = decl_ultimate_origin (decl);
       if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL)
        gen_formal_parameter_die (decl, context_die);
@@ -11563,25 +11892,17 @@ gen_decl_die (decl, context_die)
       break;
 
     default:
+      if ((int)TREE_CODE (decl) > NUM_TREE_CODES)
+       /* Probably some frontend-internal decl.  Assume we don't care.  */
+       break;
       abort ();
     }
 }
-
-static void
-mark_limbo_die_list (ptr)
-     void *ptr ATTRIBUTE_UNUSED;
-{
-  limbo_die_node *node;
-  for (node = limbo_die_list; node; node = node->next)
-    ggc_mark_tree (node->created_for);
-}
 \f
 /* Add Ada "use" clause information for SGI Workshop debugger.  */
 
 void
-dwarf2out_add_library_unit_info (filename, context_list)
-     const char *filename;
-     const char *context_list;
+dwarf2out_add_library_unit_info (const char *filename, const char *context_list)
 {
   unsigned int file_index;
 
@@ -11604,8 +11925,7 @@ dwarf2out_add_library_unit_info (filename, context_list)
    compilation proper has finished.  */
 
 static void
-dwarf2out_global_decl (decl)
-     tree decl;
+dwarf2out_global_decl (tree decl)
 {
   /* Output DWARF2 information for file-scope tentative data object
      declarations, file-scope (extern) function declarations (which had no
@@ -11618,8 +11938,7 @@ dwarf2out_global_decl (decl)
 /* Write the debugging output for DECL.  */
 
 void
-dwarf2out_decl (decl)
-     tree decl;
+dwarf2out_decl (tree decl)
 {
   dw_die_ref context_die = comp_unit_die;
 
@@ -11630,32 +11949,32 @@ dwarf2out_decl (decl)
 
     case FUNCTION_DECL:
       /* Ignore this FUNCTION_DECL if it refers to a builtin declaration of a
-         builtin function.  Explicit programmer-supplied declarations of
-         these same functions should NOT be ignored however.  */
+        builtin function.  Explicit programmer-supplied declarations of
+        these same functions should NOT be ignored however.  */
       if (DECL_EXTERNAL (decl) && DECL_BUILT_IN (decl))
        return;
 
       /* 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 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 functions,
-         it will have to hunt around and find the DWARF information associated
-         with the definition of the function.
+        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 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 functions,
+        it will have to hunt around and find the DWARF information associated
+        with the definition of the function.
 
         We can't just check DECL_EXTERNAL to find out which FUNCTION_DECL
-         nodes represent definitions and which ones represent mere
-         declarations.  We have to check DECL_INITIAL instead. That's because
-         the C front-end supports some weird semantics for "extern inline"
-         function definitions.  These can get inlined within the current
-         translation unit (an thus, we need to generate Dwarf info for their
-         abstract instances so that the Dwarf info for the concrete inlined
-         instances can have something to refer to) but the compiler never
-         generates any out-of-lines instances of such things (despite the fact
-         that they *are* definitions).
+        nodes represent definitions and which ones represent mere
+        declarations.  We have to check DECL_INITIAL instead. That's because
+        the C front-end supports some weird semantics for "extern inline"
+        function definitions.  These can get inlined within the current
+        translation unit (an thus, we need to generate Dwarf info for their
+        abstract instances so that the Dwarf info for the concrete inlined
+        instances can have something to refer to) but the compiler never
+        generates any out-of-lines instances of such things (despite the fact
+        that they *are* definitions).
 
         The important point is that the C front-end marks these "extern
         inline" functions as DECL_EXTERNAL, but we need to generate DWARF for
@@ -11668,24 +11987,26 @@ dwarf2out_decl (decl)
       /* If we're a nested function, initially use a parent of NULL; if we're
         a plain function, this will be fixed up in decls_for_scope.  If
         we're a method, it will be ignored, since we already have a DIE.  */
-      if (decl_function_context (decl))
+      if (decl_function_context (decl)
+         /* But if we're in terse mode, we don't care about scope.  */
+         && debug_info_level > DINFO_LEVEL_TERSE)
        context_die = NULL;
       break;
 
     case VAR_DECL:
       /* Ignore this VAR_DECL if it refers to a file-scope extern data object
-         declaration and if the declaration was never even referenced from
-         within this entire compilation unit.  We suppress these DIEs in
-         order to save space in the .debug section (by eliminating entries
-         which are probably useless).  Note that we must not suppress
-         block-local extern declarations (whether used or not) because that
-         would screw-up the debugger's name lookup mechanism and cause it to
-         miss things which really ought to be in scope at a given point.  */
+        declaration and if the declaration was never even referenced from
+        within this entire compilation unit.  We suppress these DIEs in
+        order to save space in the .debug section (by eliminating entries
+        which are probably useless).  Note that we must not suppress
+        block-local extern declarations (whether used or not) because that
+        would screw-up the debugger's name lookup mechanism and cause it to
+        miss things which really ought to be in scope at a given point.  */
       if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
        return;
 
       /* If we are in terse mode, don't generate any DIEs to represent any
-         variable declarations or definitions.  */
+        variable declarations or definitions.  */
       if (debug_info_level <= DINFO_LEVEL_TERSE)
        return;
       break;
@@ -11696,11 +12017,11 @@ dwarf2out_decl (decl)
        return;
 
       /* Don't bother trying to generate any DIEs to represent any of the
-         normal built-in types for the language we are compiling.  */
+        normal built-in types for the language we are compiling.  */
       if (DECL_SOURCE_LINE (decl) == 0)
        {
          /* OK, we need to generate one for `bool' so GDB knows what type
-             comparisons have.  */
+            comparisons have.  */
          if ((get_AT_unsigned (comp_unit_die, DW_AT_language)
               == DW_LANG_C_plus_plus)
              && TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE
@@ -11732,9 +12053,8 @@ dwarf2out_decl (decl)
    a lexical block.  */
 
 static void
-dwarf2out_begin_block (line, blocknum)
-     unsigned int line ATTRIBUTE_UNUSED;
-     unsigned int blocknum;
+dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED,
+                      unsigned int blocknum)
 {
   function_section (current_function_decl);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
@@ -11744,9 +12064,7 @@ dwarf2out_begin_block (line, blocknum)
    lexical block.  */
 
 static void
-dwarf2out_end_block (line, blocknum)
-     unsigned int line ATTRIBUTE_UNUSED;
-     unsigned int blocknum;
+dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum)
 {
   function_section (current_function_decl);
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
@@ -11760,8 +12078,7 @@ dwarf2out_end_block (line, blocknum)
    we may end up calling them anyway.  */
 
 static bool
-dwarf2out_ignore_block (block)
-     tree block;
+dwarf2out_ignore_block (tree block)
 {
   tree decl;
 
@@ -11785,61 +12102,70 @@ dwarf2out_ignore_block (block)
    all searches.  */
 
 static unsigned
-lookup_filename (file_name)
-     const char *file_name;
+lookup_filename (const char *file_name)
 {
-  unsigned i;
-
-  /* ??? Why isn't DECL_SOURCE_FILE left null instead.  */
-  if (strcmp (file_name, "<internal>") == 0
-      || strcmp (file_name, "<built-in>") == 0)
-    return 0;
+  size_t i, n;
+  char *save_file_name;
 
   /* Check to see if the file name that was searched on the previous
      call matches this file name.  If so, return the index.  */
-  if (file_table.last_lookup_index != 0)
-    if (0 == strcmp (file_name,
-                    file_table.table[file_table.last_lookup_index]))
-      return file_table.last_lookup_index;
+  if (file_table_last_lookup_index != 0)
+    {
+      const char *last
+       = VARRAY_CHAR_PTR (file_table, file_table_last_lookup_index);
+      if (strcmp (file_name, last) == 0)
+       return file_table_last_lookup_index;
+    }
 
   /* Didn't match the previous lookup, search the table */
-  for (i = 1; i < file_table.in_use; i++)
-    if (strcmp (file_name, file_table.table[i]) == 0)
+  n = VARRAY_ACTIVE_SIZE (file_table);
+  for (i = 1; i < n; i++)
+    if (strcmp (file_name, VARRAY_CHAR_PTR (file_table, i)) == 0)
       {
-       file_table.last_lookup_index = i;
+       file_table_last_lookup_index = i;
        return i;
       }
 
-  /* Prepare to add a new table entry by making sure there is enough space in
-     the table to do so.  If not, expand the current table.  */
-  if (i == file_table.allocated)
-    {
-      file_table.allocated = i + FILE_TABLE_INCREMENT;
-      file_table.table = (char **)
-       xrealloc (file_table.table, file_table.allocated * sizeof (char *));
-    }
-
   /* Add the new entry to the end of the filename table.  */
-  file_table.table[i] = xstrdup (file_name);
-  file_table.in_use = i + 1;
-  file_table.last_lookup_index = i;
-
-  if (DWARF2_ASM_LINE_DEBUG_INFO)
-    fprintf (asm_out_file, "\t.file %u \"%s\"\n", i, file_name);
+  file_table_last_lookup_index = n;
+  save_file_name = (char *) ggc_strdup (file_name);
+  VARRAY_PUSH_CHAR_PTR (file_table, save_file_name);
+  VARRAY_PUSH_UINT (file_table_emitted, 0);
 
   return i;
 }
 
+static int
+maybe_emit_file (int fileno)
+{
+  if (DWARF2_ASM_LINE_DEBUG_INFO && fileno > 0)
+    {
+      if (!VARRAY_UINT (file_table_emitted, fileno))
+       {
+         VARRAY_UINT (file_table_emitted, fileno) = ++emitcount;
+         fprintf (asm_out_file, "\t.file %u ",
+                  VARRAY_UINT (file_table_emitted, fileno));
+         output_quoted_string (asm_out_file,
+                               VARRAY_CHAR_PTR (file_table, fileno));
+         fputc ('\n', asm_out_file);
+       }
+      return VARRAY_UINT (file_table_emitted, fileno);
+    }
+  else
+    return fileno;
+}
+
 static void
-init_file_table ()
+init_file_table (void)
 {
   /* Allocate the initial hunk of the file_table.  */
-  file_table.table = (char **) xcalloc (FILE_TABLE_INCREMENT, sizeof (char *));
-  file_table.allocated = FILE_TABLE_INCREMENT;
+  VARRAY_CHAR_PTR_INIT (file_table, 64, "file_table");
+  VARRAY_UINT_INIT (file_table_emitted, 64, "file_table_emitted");
 
   /* Skip the first entry - file numbers begin at 1.  */
-  file_table.in_use = 1;
-  file_table.last_lookup_index = 0;
+  VARRAY_PUSH_CHAR_PTR (file_table, NULL);
+  VARRAY_PUSH_UINT (file_table_emitted, 0);
+  file_table_last_lookup_index = 0;
 }
 
 /* Output a label to mark the beginning of a source code line entry
@@ -11847,11 +12173,10 @@ init_file_table ()
    'line_info_table' for later output of the .debug_line section.  */
 
 static void
-dwarf2out_source_line (line, filename)
-     unsigned int line;
-     const char *filename;
+dwarf2out_source_line (unsigned int line, const char *filename)
 {
-  if (debug_info_level >= DINFO_LEVEL_NORMAL)
+  if (debug_info_level >= DINFO_LEVEL_NORMAL
+      && line != 0)
     {
       function_section (current_function_decl);
 
@@ -11864,6 +12189,8 @@ dwarf2out_source_line (line, filename)
        {
          unsigned file_num = lookup_filename (filename);
 
+         file_num = maybe_emit_file (file_num);
+
          /* Emit the .loc directive understood by GNU as.  */
          fprintf (asm_out_file, "\t.loc %d %d 0\n", file_num, line);
 
@@ -11877,7 +12204,7 @@ dwarf2out_source_line (line, filename)
       else if (DECL_SECTION_NAME (current_function_decl))
        {
          dw_separate_line_info_ref line_info;
-         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL,
+         (*targetm.asm_out.internal_label) (asm_out_file, SEPARATE_LINE_CODE_LABEL,
                                     separate_line_info_table_in_use);
 
          /* expand the line info table if necessary */
@@ -11887,9 +12214,14 @@ dwarf2out_source_line (line, filename)
              separate_line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
              separate_line_info_table
                = (dw_separate_line_info_ref)
-                 xrealloc (separate_line_info_table,
-                           separate_line_info_table_allocated
-                           * sizeof (dw_separate_line_info_entry));
+                 ggc_realloc (separate_line_info_table,
+                              separate_line_info_table_allocated
+                              * sizeof (dw_separate_line_info_entry));
+             memset ((separate_line_info_table
+                      + separate_line_info_table_in_use),
+                     0,
+                     (LINE_INFO_TABLE_INCREMENT
+                      * sizeof (dw_separate_line_info_entry)));
            }
 
          /* Add the new entry at the end of the line_info_table.  */
@@ -11897,13 +12229,13 @@ dwarf2out_source_line (line, filename)
            = &separate_line_info_table[separate_line_info_table_in_use++];
          line_info->dw_file_num = lookup_filename (filename);
          line_info->dw_line_num = line;
-         line_info->function = current_funcdef_number;
+         line_info->function = current_function_funcdef_no;
        }
       else
        {
          dw_line_info_ref line_info;
 
-         ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL,
+         (*targetm.asm_out.internal_label) (asm_out_file, LINE_CODE_LABEL,
                                     line_info_table_in_use);
 
          /* Expand the line info table if necessary.  */
@@ -11911,10 +12243,11 @@ dwarf2out_source_line (line, filename)
            {
              line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
              line_info_table
-               = (dw_line_info_ref)
-                 xrealloc (line_info_table,
-                           (line_info_table_allocated
-                            * sizeof (dw_line_info_entry)));
+               = ggc_realloc (line_info_table,
+                              (line_info_table_allocated
+                               * sizeof (dw_line_info_entry)));
+             memset (line_info_table + line_info_table_in_use, 0,
+                     LINE_INFO_TABLE_INCREMENT * sizeof (dw_line_info_entry));
            }
 
          /* Add the new entry at the end of the line_info_table.  */
@@ -11928,23 +12261,26 @@ dwarf2out_source_line (line, filename)
 /* Record the beginning of a new source file.  */
 
 static void
-dwarf2out_start_source_file (lineno, filename)
-     unsigned int lineno;
-     const char *filename;
+dwarf2out_start_source_file (unsigned int lineno, const char *filename)
 {
-  if (flag_eliminate_dwarf2_dups)
+  if (flag_eliminate_dwarf2_dups && !is_main_source)
     {
       /* Record the beginning of the file for break_out_includes.  */
-      dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL);
+      dw_die_ref bincl_die;
+
+      bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL);
       add_AT_string (bincl_die, DW_AT_name, filename);
     }
 
+  is_main_source = 0;
+
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
       named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
       dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file");
       dw2_asm_output_data_uleb128 (lineno, "Included from line number %d",
                                   lineno);
+      maybe_emit_file (lookup_filename (filename));
       dw2_asm_output_data_uleb128 (lookup_filename (filename),
                                   "Filename we just started");
     }
@@ -11953,8 +12289,7 @@ dwarf2out_start_source_file (lineno, filename)
 /* Record the end of a source file.  */
 
 static void
-dwarf2out_end_source_file (lineno)
-     unsigned int lineno ATTRIBUTE_UNUSED;
+dwarf2out_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
 {
   if (flag_eliminate_dwarf2_dups)
     /* Record the end of the file for break_out_includes.  */
@@ -11972,9 +12307,8 @@ dwarf2out_end_source_file (lineno)
    initial whitespace, #, whitespace, directive-name, whitespace part.  */
 
 static void
-dwarf2out_define (lineno, buffer)
-     unsigned lineno ATTRIBUTE_UNUSED;
-     const char *buffer ATTRIBUTE_UNUSED;
+dwarf2out_define (unsigned int lineno ATTRIBUTE_UNUSED,
+                 const char *buffer ATTRIBUTE_UNUSED)
 {
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
@@ -11990,9 +12324,8 @@ dwarf2out_define (lineno, buffer)
    initial whitespace, #, whitespace, directive-name, whitespace part.  */
 
 static void
-dwarf2out_undef (lineno, buffer)
-     unsigned lineno ATTRIBUTE_UNUSED;
-     const char *buffer ATTRIBUTE_UNUSED;
+dwarf2out_undef (unsigned int lineno ATTRIBUTE_UNUSED,
+                const char *buffer ATTRIBUTE_UNUSED)
 {
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
@@ -12006,41 +12339,29 @@ dwarf2out_undef (lineno, buffer)
 /* Set up for Dwarf output at the start of compilation.  */
 
 static void
-dwarf2out_init (main_input_filename)
-     const char *main_input_filename;
+dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
 {
   init_file_table ();
 
-  /* Remember the name of the primary input file.  */
-  primary_filename = main_input_filename;
-
-  /* Add it to the file table first, under the assumption that we'll
-     be emitting line number data for it first, which avoids having
-     to add an initial DW_LNS_set_file.  */
-  lookup_filename (main_input_filename);
-
   /* Allocate the initial hunk of the decl_die_table.  */
-  decl_die_table
-    = (dw_die_ref *) xcalloc (DECL_DIE_TABLE_INCREMENT, sizeof (dw_die_ref));
+  decl_die_table = ggc_alloc_cleared (DECL_DIE_TABLE_INCREMENT
+                                     * sizeof (dw_die_ref));
   decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT;
   decl_die_table_in_use = 0;
 
   /* Allocate the initial hunk of the decl_scope_table.  */
   VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");
-  ggc_add_tree_varray_root (&decl_scope_table, 1);
 
   /* Allocate the initial hunk of the abbrev_die_table.  */
-  abbrev_die_table
-    = (dw_die_ref *) xcalloc (ABBREV_DIE_TABLE_INCREMENT,
-                             sizeof (dw_die_ref));
+  abbrev_die_table = ggc_alloc_cleared (ABBREV_DIE_TABLE_INCREMENT
+                                       * sizeof (dw_die_ref));
   abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
   /* Zero-th entry is allocated, but unused */
   abbrev_die_table_in_use = 1;
 
   /* Allocate the initial hunk of the line_info_table.  */
-  line_info_table
-    = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
-                                 sizeof (dw_line_info_entry));
+  line_info_table = ggc_alloc_cleared (LINE_INFO_TABLE_INCREMENT
+                                      * sizeof (dw_line_info_entry));
   line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
 
   /* Zero-th entry is allocated, but unused */
@@ -12050,16 +12371,14 @@ dwarf2out_init (main_input_filename)
      value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE
      will (typically) be a relative pathname and that this pathname should be
      taken as being relative to the directory from which the compiler was
-     invoked when the given (base) source file was compiled.  */
-  comp_unit_die = gen_compile_unit_die (main_input_filename);
+     invoked when the given (base) source file was compiled.  We will fill
+     in this value in dwarf2out_finish.  */
+  comp_unit_die = gen_compile_unit_die (NULL);
+  is_main_source = 1;
 
   VARRAY_TREE_INIT (incomplete_types, 64, "incomplete_types");
-  ggc_add_tree_varray_root (&incomplete_types, 1);
 
   VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
-  ggc_add_rtx_varray_root (&used_rtx_varray, 1);
-
-  ggc_add_root (&limbo_die_list, 1, 1, mark_limbo_die_list);
 
   ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
@@ -12097,54 +12416,250 @@ dwarf2out_init (main_input_filename)
     }
 }
 
-/* Allocate a string in .debug_str hash table.  */
-
-static hashnode
-indirect_string_alloc (tab)
-     hash_table *tab ATTRIBUTE_UNUSED;
-{
-  struct indirect_string_node *node;
-
-  node = xmalloc (sizeof (struct indirect_string_node));
-  node->refcount = 0;
-  node->form = 0;
-  node->label = NULL;
-
-  return (hashnode) node;
-}
-
 /* A helper function for dwarf2out_finish called through
    ht_forall.  Emit one queued .debug_str string.  */
 
 static int
-output_indirect_string (pfile, h, v)
-     struct cpp_reader *pfile ATTRIBUTE_UNUSED;
-     hashnode h;
-     const PTR v ATTRIBUTE_UNUSED;
+output_indirect_string (void **h, void *v ATTRIBUTE_UNUSED)
 {
-  struct indirect_string_node *node = (struct indirect_string_node *) h;
+  struct indirect_string_node *node = (struct indirect_string_node *) *h;
 
   if (node->form == DW_FORM_strp)
     {
       named_section_flags (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS);
       ASM_OUTPUT_LABEL (asm_out_file, node->label);
-      assemble_string ((const char *) HT_STR (&node->id),
-                      HT_LEN (&node->id) + 1);
+      assemble_string (node->str, strlen (node->str) + 1);
     }
 
   return 1;
 }
 
+
+
+/* Clear the marks for a die and its children.
+   Be cool if the mark isn't set.  */
+
+static void
+prune_unmark_dies (dw_die_ref die)
+{
+  dw_die_ref c;
+  die->die_mark = 0;
+  for (c = die->die_child; c; c = c->die_sib)
+    prune_unmark_dies (c);
+}
+
+
+/* Given DIE that we're marking as used, find any other dies
+   it references as attributes and mark them as used.  */
+
+static void
+prune_unused_types_walk_attribs (dw_die_ref die)
+{
+  dw_attr_ref a;
+
+  for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
+    {
+      if (a->dw_attr_val.val_class == dw_val_class_die_ref)
+       {
+         /* A reference to another DIE.
+            Make sure that it will get emitted.  */
+         prune_unused_types_mark (a->dw_attr_val.v.val_die_ref.die, 1);
+       }
+      else if (a->dw_attr == DW_AT_decl_file)
+       {
+         /* A reference to a file.  Make sure the file name is emitted.  */
+         a->dw_attr_val.v.val_unsigned =
+           maybe_emit_file (a->dw_attr_val.v.val_unsigned);
+       }
+    }
+}
+
+
+/* Mark DIE as being used.  If DOKIDS is true, then walk down
+   to DIE's children.  */
+
+static void
+prune_unused_types_mark (dw_die_ref die, int dokids)
+{
+  dw_die_ref c;
+
+  if (die->die_mark == 0)
+    {
+      /* We haven't done this node yet.  Mark it as used.  */
+      die->die_mark = 1;
+
+      /* We also have to mark its parents as used.
+        (But we don't want to mark our parents' kids due to this.)  */
+      if (die->die_parent)
+       prune_unused_types_mark (die->die_parent, 0);
+
+      /* Mark any referenced nodes.  */
+      prune_unused_types_walk_attribs (die);
+    }
+
+  if (dokids && die->die_mark != 2)
+    {
+      /* We need to walk the children, but haven't done so yet.
+        Remember that we've walked the kids.  */
+      die->die_mark = 2;
+
+      /* Walk them.  */
+      for (c = die->die_child; c; c = c->die_sib)
+       {
+         /* If this is an array type, we need to make sure our
+            kids get marked, even if they're types.  */
+         if (die->die_tag == DW_TAG_array_type)
+           prune_unused_types_mark (c, 1);
+         else
+           prune_unused_types_walk (c);
+       }
+    }
+}
+
+
+/* Walk the tree DIE and mark types that we actually use.  */
+
+static void
+prune_unused_types_walk (dw_die_ref die)
+{
+  dw_die_ref c;
+
+  /* Don't do anything if this node is already marked.  */
+  if (die->die_mark)
+    return;
+
+  switch (die->die_tag) {
+  case DW_TAG_const_type:
+  case DW_TAG_packed_type:
+  case DW_TAG_pointer_type:
+  case DW_TAG_reference_type:
+  case DW_TAG_volatile_type:
+  case DW_TAG_typedef:
+  case DW_TAG_array_type:
+  case DW_TAG_structure_type:
+  case DW_TAG_union_type:
+  case DW_TAG_class_type:
+  case DW_TAG_friend:
+  case DW_TAG_variant_part:
+  case DW_TAG_enumeration_type:
+  case DW_TAG_subroutine_type:
+  case DW_TAG_string_type:
+  case DW_TAG_set_type:
+  case DW_TAG_subrange_type:
+  case DW_TAG_ptr_to_member_type:
+  case DW_TAG_file_type:
+    /* It's a type node --- don't mark it.  */
+    return;
+
+  default:
+    /* Mark everything else.  */
+    break;
+  }
+
+  die->die_mark = 1;
+
+  /* Now, mark any dies referenced from here.  */
+  prune_unused_types_walk_attribs (die);
+
+  /* Mark children.  */
+  for (c = die->die_child; c; c = c->die_sib)
+    prune_unused_types_walk (c);
+}
+
+
+/* Remove from the tree DIE any dies that aren't marked.  */
+
+static void
+prune_unused_types_prune (dw_die_ref die)
+{
+  dw_die_ref c, p, n;
+  if (!die->die_mark)
+    abort();
+
+  p = NULL;
+  for (c = die->die_child; c; c = n)
+    {
+      n = c->die_sib;
+      if (c->die_mark)
+       {
+         prune_unused_types_prune (c);
+         p = c;
+       }
+      else
+       {
+         if (p)
+           p->die_sib = n;
+         else
+           die->die_child = n;
+         free_die (c);
+       }
+    }
+}
+
+
+/* Remove dies representing declarations that we never use.  */
+
+static void
+prune_unused_types (void)
+{
+  unsigned int i;
+  limbo_die_node *node;
+
+  /* Clear all the marks.  */
+  prune_unmark_dies (comp_unit_die);
+  for (node = limbo_die_list; node; node = node->next)
+    prune_unmark_dies (node->die);
+
+  /* Set the mark on nodes that are actually used.  */
+  prune_unused_types_walk (comp_unit_die);
+  for (node = limbo_die_list; node; node = node->next)
+    prune_unused_types_walk (node->die);
+
+  /* Also set the mark on nodes referenced from the
+     pubname_table or arange_table.  */
+  for (i = 0; i < pubname_table_in_use; i++)
+    prune_unused_types_mark (pubname_table[i].die, 1);
+  for (i = 0; i < arange_table_in_use; i++)
+    prune_unused_types_mark (arange_table[i], 1);
+
+  /* Get rid of nodes that aren't marked.  */
+  prune_unused_types_prune (comp_unit_die);
+  for (node = limbo_die_list; node; node = node->next)
+    prune_unused_types_prune (node->die);
+
+  /* Leave the marks clear.  */
+  prune_unmark_dies (comp_unit_die);
+  for (node = limbo_die_list; node; node = node->next)
+    prune_unmark_dies (node->die);
+}
+
 /* Output stuff that dwarf requires at the end of every file,
    and generate the DWARF-2 debugging info.  */
 
 static void
-dwarf2out_finish (input_filename)
-     const char *input_filename ATTRIBUTE_UNUSED;
+dwarf2out_finish (const char *filename)
 {
   limbo_die_node *node, *next_node;
   dw_die_ref die = 0;
 
+  /* Add the name for the main input file now.  We delayed this from
+     dwarf2out_init to avoid complications with PCH.  */
+  add_name_attribute (comp_unit_die, filename);
+  if (filename[0] != DIR_SEPARATOR)
+    add_comp_dir_attribute (comp_unit_die);
+  else if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL)
+    {
+      size_t i;
+      for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++)
+       if (VARRAY_CHAR_PTR (file_table, i)[0] != DIR_SEPARATOR
+           /* Don't add cwd for <built-in>.  */
+           && VARRAY_CHAR_PTR (file_table, i)[0] != '<')
+         {
+           add_comp_dir_attribute (comp_unit_die);
+           break;
+         }
+    }
+
   /* Traverse the limbo die list, and add parent/child links.  The only
      dies without parents that should be here are concrete instances of
      inline functions, and the comp_unit_die.  We can ignore the comp_unit_die.
@@ -12196,8 +12711,6 @@ dwarf2out_finish (input_filename)
          else
            abort ();
        }
-
-      free (node);
     }
 
   limbo_die_list = NULL;
@@ -12210,6 +12723,9 @@ dwarf2out_finish (input_filename)
      we'll see the end of an include file before the beginning.  */
   reverse_all_dies (comp_unit_die);
 
+  if (flag_eliminate_unused_debug_types)
+    prune_unused_types ();
+
   /* Generate separate CUs for each of the include files we've seen.
      They will go into limbo_die_list.  */
   if (flag_eliminate_dwarf2_dups)
@@ -12223,7 +12739,7 @@ dwarf2out_finish (input_filename)
 
   /* Output a terminator label for the .text section.  */
   text_section ();
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0);
+  (*targetm.asm_out.internal_label) (asm_out_file, TEXT_END_LABEL, 0);
 
   /* Output the source line correspondence table.  We must do this
      even if there is no line information.  Otherwise, on an empty
@@ -12271,9 +12787,9 @@ dwarf2out_finish (input_filename)
   /* Output all of the compilation units.  We put the main one last so that
      the offsets are available to output_pubnames.  */
   for (node = limbo_die_list; node; node = node->next)
-    output_comp_unit (node->die);
+    output_comp_unit (node->die, 0);
 
-  output_comp_unit (comp_unit_die);
+  output_comp_unit (comp_unit_die, 0);
 
   /* Output the abbreviation table.  */
   named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG);
@@ -12307,11 +12823,19 @@ dwarf2out_finish (input_filename)
     {
       named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
       dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
+      dw2_asm_output_data (1, 0, "End compilation unit");
     }
 
   /* If we emitted any DW_FORM_strp form attribute, output the string
      table too.  */
   if (debug_str_hash)
-    ht_forall (debug_str_hash, output_indirect_string, NULL);
+    htab_traverse (debug_str_hash, output_indirect_string, NULL);
 }
-#endif /* DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO */
+#else
+
+/* This should never be used, but its address is needed for comparisons.  */
+const struct gcc_debug_hooks dwarf2_debug_hooks;
+
+#endif /* DWARF2_DEBUGGING_INFO */
+
+#include "gt-dwarf2out.h"