OSDN Git Service

* g++.dg/init/new1.C, g++.dg/template/alignof1.C,
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index f4c298a..c931420 100644 (file)
@@ -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"
@@ -61,6 +64,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #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 *));
@@ -102,13 +106,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)
@@ -122,17 +119,50 @@ void
 default_eh_frame_section ()
 {
 #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
 }
 
+/* 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;
+
 #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
 
 /* How to start an assembler comment.  */
@@ -193,6 +223,7 @@ typedef struct dw_fde_struct
   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;
 }
@@ -307,11 +338,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,35 +353,15 @@ 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.  */
@@ -417,16 +423,17 @@ expand_builtin_init_dwarf_reg_sizes (address)
   rtx addr = expand_expr (address, NULL_RTX, VOIDmode, 0);
   rtx mem = gen_rtx_MEM (BLKmode, addr);
 
-  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);
+       HOST_WIDE_INT size = GET_MODE_SIZE (reg_raw_mode[i]);
 
-      if (offset < 0)
-       continue;
+       if (offset < 0)
+         continue;
 
-      emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
-    }
+       emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
+      }
 }
 
 /* Convert a DWARF call frame info. operation to its string name */
@@ -950,6 +957,8 @@ stack_adjust_offset (pattern)
        return 0;
 
       offset = INTVAL (XEXP (src, 1));
+      if (code == PLUS)
+       offset = -offset;
     }
   else if (GET_CODE (dest) == MEM)
     {
@@ -957,30 +966,47 @@ stack_adjust_offset (pattern)
       src = XEXP (dest, 0);
       code = GET_CODE (src);
 
-      if ((code != PRE_DEC && code != PRE_INC && code != PRE_MODIFY)
-         || XEXP (src, 0) != stack_pointer_rtx)
-       return 0;
-
-      if (code == PRE_MODIFY)
+      switch (code)
        {
-         rtx val = XEXP (XEXP (src, 1), 1);
+       case PRE_MODIFY:
+       case POST_MODIFY:
+         if (XEXP (src, 0) == stack_pointer_rtx)
+           {
+             rtx val = XEXP (XEXP (src, 1), 1);
+             /* We handle only adjustments by constant amount.  */
+             if (GET_CODE (XEXP (src, 1)) != PLUS ||
+                 GET_CODE (val) != CONST_INT)
+               abort ();
+             offset = -INTVAL (val);
+             break;
+           }
+         return 0;
 
-         /* We handle only adjustments by constant amount.  */
-         if (GET_CODE (XEXP (src, 1)) != PLUS ||
-             GET_CODE (val) != CONST_INT)
-           abort ();
+       case PRE_DEC:
+       case POST_DEC:
+         if (XEXP (src, 0) == stack_pointer_rtx)
+           {
+             offset = GET_MODE_SIZE (GET_MODE (dest));
+             break;
+           }
+         return 0;
+
+       case PRE_INC:
+       case POST_INC:
+         if (XEXP (src, 0) == stack_pointer_rtx)
+           {
+             offset = -GET_MODE_SIZE (GET_MODE (dest));
+             break;
+           }
+         return 0;
 
-         offset = -INTVAL (val);
+       default:
+         return 0;
        }
-      else
-       offset = GET_MODE_SIZE (GET_MODE (dest));
     }
   else
     return 0;
 
-  if (code == PLUS || code == PRE_INC)
-    offset = -offset;
-
   return offset;
 }
 
@@ -1095,7 +1121,7 @@ flush_queued_reg_saves ()
 {
   struct queued_reg_save *q, *next;
 
-  for (q = queued_reg_saves; q ; q = next)
+  for (q = queued_reg_saves; q; q = next)
     {
       dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset);
       next = q->next;
@@ -1112,13 +1138,13 @@ clobbers_queued_reg_save (insn)
 {
   struct queued_reg_save *q;
 
-  for (q = queued_reg_saves; q ; q = q->next)
+  for (q = queued_reg_saves; q; q = q->next)
     if (modified_in_p (q->reg, insn))
       return true;
 
   return false;
 }
-  
+
 
 /* A temporary register holding an integral value used in adjusting SP
    or setting up the store_reg.  The "offset" field holds the integer
@@ -1154,7 +1180,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.
 
@@ -1169,7 +1195,7 @@ static dw_cfa_location cfa_temp;
               stores the value, which will be used to adjust the
               stack pointer.  cfa_temp is also used like cfa_store,
               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
               cfa.offset.  Rule 1 and 4 also set cfa_temp.reg and
@@ -1637,7 +1663,7 @@ dwarf2out_frame_debug (insn)
   if (! RTX_FRAME_RELATED_P (insn))
     {
       if (!ACCUMULATE_OUTGOING_ARGS)
-        dwarf2out_stack_adjust (insn);
+       dwarf2out_stack_adjust (insn);
 
       return;
     }
@@ -1795,6 +1821,10 @@ output_call_frame_info (for_eh)
   int per_encoding = DW_EH_PE_absptr;
   int lsda_encoding = DW_EH_PE_absptr;
 
+  /* Don't emit a CIE if there won't be any FDEs.  */
+  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 (for_eh)
@@ -1877,7 +1907,7 @@ output_call_frame_info (for_eh)
       if (p > augmentation + 1)
        {
          augmentation[0] = 'z';
-          *p = '\0';
+         *p = '\0';
        }
 
       /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
@@ -1933,7 +1963,7 @@ output_call_frame_info (for_eh)
     output_cfi (cfi, NULL, for_eh);
 
   /* Pad the CIE out to an address sized boundary.  */
-  ASM_OUTPUT_ALIGN (asm_out_file, 
+  ASM_OUTPUT_ALIGN (asm_out_file,
                    floor_log2 (for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE));
   ASM_OUTPUT_LABEL (asm_out_file, l2);
 
@@ -1943,10 +1973,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 (!flag_asynchronous_unwind_tables && for_eh
+         && (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,
@@ -1965,15 +1997,15 @@ output_call_frame_info (for_eh)
                   gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
                   "FDE initial location");
          dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
-                               fde->dw_fde_end, fde->dw_fde_begin, 
+                               fde->dw_fde_end, fde->dw_fde_begin,
                                "FDE address range");
        }
       else
        {
          dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
                               "FDE initial location");
-         dw2_asm_output_delta (DWARF2_ADDR_SIZE, 
-                               fde->dw_fde_end, fde->dw_fde_begin, 
+         dw2_asm_output_delta (DWARF2_ADDR_SIZE,
+                               fde->dw_fde_end, fde->dw_fde_begin,
                                "FDE address range");
        }
 
@@ -2026,15 +2058,13 @@ output_call_frame_info (for_eh)
        output_cfi (cfi, fde, for_eh);
 
       /* Pad the FDE out to an address sized boundary.  */
-      ASM_OUTPUT_ALIGN (asm_out_file, 
+      ASM_OUTPUT_ALIGN (asm_out_file,
                        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.  */
@@ -2071,12 +2101,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
@@ -2103,9 +2132,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;
 
@@ -2122,14 +2152,17 @@ dwarf2out_begin_prologue (line, file)
    been generated.  */
 
 void
-dwarf2out_end_epilogue ()
+dwarf2out_end_epilogue (line, file)
+     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);
@@ -2167,6 +2200,11 @@ dwarf2out_frame_finish ()
 /* 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;
@@ -2292,6 +2330,7 @@ dwarf_stack_op_name (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";
@@ -2581,6 +2620,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>";
     }
@@ -2638,6 +2687,7 @@ size_of_loc_descr (loc)
   switch (loc->dw_loc_opc)
     {
     case DW_OP_addr:
+    case INTERNAL_DW_OP_tls_addr:
       size += DWARF2_ADDR_SIZE;
       break;
     case DW_OP_const1u:
@@ -2723,6 +2773,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;
     }
@@ -2872,6 +2931,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;
@@ -3083,7 +3153,7 @@ static void dwarf2out_abstract_function PARAMS ((tree));
 
 /* The debug hooks structure.  */
 
-struct gcc_debug_hooks dwarf2_debug_hooks =
+const struct gcc_debug_hooks dwarf2_debug_hooks =
 {
   dwarf2out_init,
   dwarf2out_finish,
@@ -3096,7 +3166,7 @@ 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 */
@@ -3210,7 +3280,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
@@ -3234,14 +3304,9 @@ limbo_die_node;
 /* Information concerning the compilation unit's programming
    language, and compiler version.  */
 
-extern int flag_traditional;
-
 /* 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
-
 /* Fixed size portion of public names info.  */
 #define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
 
@@ -3288,6 +3353,10 @@ static unsigned long next_die_offset;
 /* Record the root of the DIE's built for the current compilation unit.  */
 static dw_die_ref comp_unit_die;
 
+/* We need special handling in dwarf2out_start_source_file if it is
+   first one.  */
+static int is_main_source;
+
 /* A list of DIEs with a NULL parent waiting to be relocated.  */
 static limbo_die_node *limbo_die_list = 0;
 
@@ -3307,10 +3376,6 @@ struct file_table
 /* 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;
-
 /* 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.  */
@@ -3326,13 +3391,6 @@ static unsigned decl_die_table_in_use;
    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.  */
@@ -3415,21 +3473,12 @@ static unsigned ranges_table_in_use;
 /* 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;
-
 /* Record whether the function being analyzed contains inlined functions.  */
 static int current_function_has_inlines;
 #if 0 && defined (MIPS_DEBUGGING_INFO)
 static int comp_unit_has_inlines;
 #endif
 
-/* 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;
-
 /* Forward declarations for functions defined in this file.  */
 
 static int is_pseudo_reg               PARAMS ((rtx));
@@ -3540,15 +3589,29 @@ 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 *));
+                                                struct md5_ctx *,
+                                                int *));
 static void die_checksum               PARAMS ((dw_die_ref,
-                                                struct md5_ctx *));
+                                                struct md5_ctx *,
+                                                int *));
+static int same_loc_p                  PARAMS ((dw_loc_descr_ref,
+                                                dw_loc_descr_ref, int *));
+static int same_dw_val_p               PARAMS ((dw_val_node *, dw_val_node *,
+                                                int *));
+static int same_attr_p                 PARAMS ((dw_attr_ref, dw_attr_ref, int *));
+static int same_die_p                  PARAMS ((dw_die_ref, dw_die_ref, int *));
+static int same_die_p_wrap             PARAMS ((dw_die_ref, dw_die_ref));
 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 hashval_t htab_cu_hash          PARAMS ((const void *));
+static int htab_cu_eq                  PARAMS ((const void *, const void *));
+static void htab_cu_del                        PARAMS ((void *));
+static int check_duplicate_cu          PARAMS ((dw_die_ref, htab_t, unsigned *));
+static void record_comdat_symbol_number        PARAMS ((dw_die_ref, htab_t, unsigned));
 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));
@@ -3557,6 +3620,7 @@ 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 void unmark_all_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));
@@ -3565,7 +3629,7 @@ 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 void output_comp_unit           PARAMS ((dw_die_ref, int));
 static const char *dwarf2_name         PARAMS ((tree, int));
 static void add_pubname                        PARAMS ((tree, dw_die_ref));
 static void output_pubnames            PARAMS ((void));
@@ -3596,7 +3660,8 @@ 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));
+                                                enum dwarf_attribute,
+                                                dw_loc_descr_ref));
 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));
@@ -3664,7 +3729,7 @@ 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, 
+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 *,
@@ -3759,24 +3824,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
@@ -3828,7 +3881,7 @@ 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)
@@ -4154,6 +4207,9 @@ dwarf_attr_name (attr)
       return "DW_AT_body_begin";
     case DW_AT_body_end:
       return "DW_AT_body_end";
+    case DW_AT_GNU_vector:
+      return "DW_AT_GNU_vector";
+
     case DW_AT_VMS_rtnbeg_pd_address:
       return "DW_AT_VMS_rtnbeg_pd_address";
 
@@ -4484,7 +4540,7 @@ add_AT_string (die, attr_kind, str)
 {
   dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
   struct indirect_string_node *node;
-  
+
   if (! debug_str_hash)
     {
       debug_str_hash = ht_create (10);
@@ -4895,7 +4951,7 @@ is_cxx ()
 {
   return (get_AT_unsigned (comp_unit_die, DW_AT_language)
          == DW_LANG_C_plus_plus);
-}  
+}
 
 static inline int
 is_fortran ()
@@ -5094,10 +5150,7 @@ static inline dw_die_ref
 lookup_type_die (type)
      tree type;
 {
-  if (TREE_CODE (type) == VECTOR_TYPE)
-    type = TYPE_DEBUG_REPRESENTATION_TYPE (type);
-
-  return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
+  return TYPE_SYMTAB_DIE (type);
 }
 
 /* Equate a DIE to a given type specifier.  */
@@ -5107,7 +5160,7 @@ equate_type_number_to_die (type, type_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.  */
@@ -5402,9 +5455,10 @@ loc_checksum (loc, ctx)
 /* Calculate the checksum of an attribute.  */
 
 static void
-attr_checksum (at, ctx)
+attr_checksum (at, ctx, mark)
      dw_attr_ref at;
      struct md5_ctx *ctx;
+     int *mark;
 {
   dw_loc_descr_ref loc;
   rtx r;
@@ -5462,9 +5516,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:
@@ -5479,25 +5532,195 @@ attr_checksum (at, ctx)
 /* Calculate the checksum of a DIE.  */
 
 static void
-die_checksum (die, ctx)
+die_checksum (die, ctx, mark)
      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
 
+/* Do the location expressions look same?  */
+static inline int
+same_loc_p (loc1, loc2, mark)
+     dw_loc_descr_ref loc1;
+     dw_loc_descr_ref loc2;
+     int *mark;
+{
+  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);
+}
+
+/* Do the values look the same?  */
+static int
+same_dw_val_p (v1, v2, mark)
+     dw_val_node *v1;
+     dw_val_node *v2;
+     int *mark;
+{
+  dw_loc_descr_ref loc1, loc2;
+  rtx r1, r2;
+  unsigned i;
+
+  if (v1->val_class != v2->val_class)
+    return 0;
+
+  switch (v1->val_class)
+    {
+    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((const char *) HT_STR (&v1->v.val_str->id),
+                    (const char *) HT_STR (&v2->v.val_str->id));
+
+    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));
+
+       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 (at1, at2, mark)
+     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 (die1, die2, mark)
+     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 (die1, die2)
+     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;
@@ -5512,10 +5735,11 @@ static void
 compute_section_prefix (unit_die)
      dw_die_ref unit_die;
 {
-  const char *base = lbasename (get_AT_string (unit_die, DW_AT_name));
+  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;
+  int i, mark;
   unsigned char checksum[16];
   struct md5_ctx ctx;
 
@@ -5523,7 +5747,9 @@ compute_section_prefix (unit_die)
      the name filename of the unit.  */
 
   md5_init_ctx (&ctx);
-  die_checksum (unit_die, &ctx);
+  mark = 0;
+  die_checksum (unit_die, &ctx, &mark);
+  unmark_all_dies (unit_die);
   md5_finish_ctx (&ctx, checksum);
 
   sprintf (name, "%s.", base);
@@ -5565,6 +5791,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;
@@ -5609,7 +5836,7 @@ is_symbol_die (c)
      dw_die_ref c;
 {
   return (is_type_die (c)
-         || (get_AT (c, DW_AT_declaration) 
+         || (get_AT (c, DW_AT_declaration)
              && !get_AT (c, DW_AT_specification)));
 }
 
@@ -5650,6 +5877,104 @@ 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 (of)
+     const void *of;
+{
+  const struct cu_hash_table_entry *entry = of;
+
+  return htab_hash_string (entry->cu->die_symbol);
+}
+
+static int
+htab_cu_eq (of1, of2)
+     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 (what)
+     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 (cu, htable, sym_num)
+     dw_die_ref cu;
+     htab_t htable;
+     unsigned *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 (cu, htable, sym_num)
+     dw_die_ref cu;
+     htab_t htable;
+     unsigned 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.  */
@@ -5660,9 +5985,10 @@ break_out_includes (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; )
+  for (ptr = &(die->die_child); *ptr;)
     {
       dw_die_ref c = *ptr;
 
@@ -5701,11 +6027,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
@@ -5744,6 +6086,7 @@ output_location_lists (die)
     output_location_lists (c);
 
 }
+
 /* The format of each DIE (and its attribute value pairs) is encoded in an
    abbreviation table.  This routine builds the abbreviation table and assigns
    a unique abbreviation id for each abbreviation entry.  The children of each
@@ -5949,6 +6292,9 @@ mark_dies (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);
@@ -5962,11 +6308,35 @@ unmark_dies (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 (die)
+     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.  */
 
@@ -6142,7 +6512,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);
 }
@@ -6166,7 +6536,7 @@ new_loc_list (expr, begin, end, section, gensym)
   retlist->end = end;
   retlist->expr = expr;
   retlist->section = section;
-  if (gensym) 
+  if (gensym)
     retlist->ll_symbol = gen_internal_sym ("LLST");
 
   return retlist;
@@ -6183,7 +6553,7 @@ add_loc_descr_to_loc_list (list_head, descr, begin, end, section)
      const char *section;
 {
   dw_loc_list_ref *d;
-  
+
   /* Find the end of the chain.  */
   for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
     ;
@@ -6214,7 +6584,7 @@ output_loc_list (list_head)
                             "Location list base address specifier base");
     }
 
-  for (curr = list_head; curr != NULL; curr=curr->dw_loc_next)
+  for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
     {
       unsigned long size;
 
@@ -6225,7 +6595,7 @@ output_loc_list (list_head)
                            "Location list end address (%s)",
                            list_head->ll_symbol);
       size = size_of_locs (curr->expr);
-      
+
       /* Output the block length for this list of location operations.  */
       if (size > 0xffff)
        abort ();
@@ -6314,7 +6684,7 @@ output_die (die)
 
            dw2_asm_output_data (1,
                                 2 * HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR,
-                                "%s", name);
+                                "%s", name);
 
            if (WORDS_BIG_ENDIAN)
              {
@@ -6339,7 +6709,7 @@ output_die (die)
            unsigned int i;
 
            dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4,
-                                "%s", name);
+                                "%s", name);
 
            for (i = 0; i < a->dw_attr_val.v.val_float.length; i++)
              dw2_asm_output_data (4, a->dw_attr_val.v.val_float.array[i],
@@ -6351,7 +6721,7 @@ output_die (die)
          dw2_asm_output_data (1, AT_flag (a), "%s", name);
          break;
 
-        case dw_val_class_loc_list:
+       case dw_val_class_loc_list:
          {
            char *sym = AT_loc_list (a)->ll_symbol;
 
@@ -6436,10 +6806,16 @@ output_compilation_unit_header ()
 /* Output the compilation unit DIE and its children.  */
 
 static void
-output_comp_unit (die)
+output_comp_unit (die, output_if_empty)
      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
@@ -6454,11 +6830,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;
     }
@@ -6472,20 +6849,23 @@ 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 output
-   of decl_printable_name for C++ looks like "A::f(int)".  Let's drop the
-   argument list, and maybe the scope.  */
+/* The DWARF2 pubname for a nested thingy looks like "A::f".  The
+   output of lang_hooks.decl_printable_name for C++ looks like
+   "A::f(int)".  Let's drop the argument list, and maybe the scope.  */
 
 static const char *
 dwarf2_name (decl, scope)
      tree decl;
      int scope;
 {
-  return (*decl_printable_name) (decl, scope ? 1 : 0);
+  return (*lang_hooks.decl_printable_name) (decl, scope ? 1 : 0);
 }
 
 /* Add a new entry to .debug_pubnames if appropriate.  */
@@ -6921,7 +7301,7 @@ output_file_names ()
       if (total > dirs[i].length + 1)
        {
          /* It's worthwhile adding.  */
-          for (j = i; j < ndirs; j++)
+         for (j = i; j < ndirs; j++)
            if (savehere[j] > 0)
              {
                /* Remember how much we saved for this directory so far.  */
@@ -7420,7 +7800,7 @@ 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
@@ -7461,6 +7841,27 @@ 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 (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 an arbitrary ..._TYPE tree node, return a debugging
    entry that chains various modifiers in front of the given type.  */
 
@@ -7482,10 +7883,10 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
 
       /* See if we already have the appropriately qualified variant of
         this type.  */
-      qualified_type 
+      qualified_type
        = get_qualified_type (type,
                              ((is_const_type ? TYPE_QUAL_CONST : 0)
-                              | (is_volatile_type 
+                              | (is_volatile_type
                                  ? TYPE_QUAL_VOLATILE : 0)));
 
       /* If we do, then we can just use its DIE, if it exists.  */
@@ -7497,7 +7898,7 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
        }
 
       /* Handle C typedef types.  */
-      if (qualified_type && TYPE_NAME (qualified_type) 
+      if (qualified_type && TYPE_NAME (qualified_type)
          && TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL
          && DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type)))
        {
@@ -7538,7 +7939,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
@@ -7547,7 +7949,8 @@ 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
@@ -7576,11 +7979,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
@@ -8032,6 +8435,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);
@@ -8124,7 +8563,7 @@ loc_descriptor_from_tree (loc, addressp)
        return 0;
       break;
 
-    case TRUTH_AND_EXPR: 
+    case TRUTH_AND_EXPR:
     case TRUTH_ANDIF_EXPR:
     case BIT_AND_EXPR:
       op = DW_OP_and;
@@ -8366,27 +8805,6 @@ simple_decl_align_in_bits (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
@@ -8514,14 +8932,12 @@ 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)
+static inline void
+add_AT_location_description (die, attr_kind, descr)
      dw_die_ref die;
      enum dwarf_attribute attr_kind;
-     rtx rtl;
+     dw_loc_descr_ref descr;
 {
-  dw_loc_descr_ref descr = loc_descriptor (rtl);
-
   if (descr != 0)
     add_AT_loc (die, attr_kind, descr);
 }
@@ -8645,7 +9061,7 @@ add_const_value_attribute (die, rtl)
         out, and the CONST_INT rtx is assigned VOIDmode.  */
       {
        HOST_WIDE_INT val = INTVAL (rtl);
-       
+
        /* ??? We really should be using HOST_WIDE_INT throughout.  */
        if (val < 0 && (long) val == val)
          add_AT_int (die, DW_AT_const_value, (long) val);
@@ -8674,7 +9090,7 @@ add_const_value_attribute (die, 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 *) xmalloc (sizeof (long) * length);
            REAL_VALUE_TYPE rv;
 
            REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
@@ -8833,7 +9249,12 @@ rtl_for_decl_location (decl)
          && (CONSTANT_P (rtl)
              || (GET_CODE (rtl) == MEM
                  && CONSTANT_P (XEXP (rtl, 0)))))
-       return rtl;
+       {
+#ifdef ASM_SIMPLIFY_DWARF_ADDR
+         rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
+#endif
+         return rtl;
+       }
       rtl = NULL_RTX;
     }
   else if (TREE_CODE (decl) == PARM_DECL)
@@ -8902,8 +9323,51 @@ rtl_for_decl_location (decl)
      and will have been substituted directly into all expressions that use it.
      C does not have such a concept, but C++ and other languages do.  */
   else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
-    rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
-                      EXPAND_INITIALIZER);
+    {
+      /* If a variable is initialized with a string constant without embedded
+        zeros, build CONST_STRING.  */
+      if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
+         && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+       {
+         tree arrtype = TREE_TYPE (decl);
+         tree enttype = TREE_TYPE (arrtype);
+         tree domain = TYPE_DOMAIN (arrtype);
+         tree init = DECL_INITIAL (decl);
+         enum machine_mode mode = TYPE_MODE (enttype);
+
+         if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1
+             && domain
+             && integer_zerop (TYPE_MIN_VALUE (domain))
+             && compare_tree_int (TYPE_MAX_VALUE (domain),
+                                  TREE_STRING_LENGTH (init) - 1) == 0
+             && ((size_t) TREE_STRING_LENGTH (init)
+                 == strlen (TREE_STRING_POINTER (init)) + 1))
+           rtl = gen_rtx_CONST_STRING (VOIDmode, TREE_STRING_POINTER (init));
+       }
+      /* If the initializer is something that we know will expand into an
+        immediate RTL constant, expand it now.  Expanding anything else
+        tends to produce unresolved symbols; see debug/5770 and c++/6381.  */
+      else if (TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST
+              || TREE_CODE (DECL_INITIAL (decl)) == REAL_CST)
+       {
+         rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
+                            EXPAND_INITIALIZER);
+         /* If expand_expr returns a MEM, it wasn't immediate.  */
+         if (rtl && GET_CODE (rtl) == MEM)
+           abort ();
+       }
+    }
+
+#ifdef ASM_SIMPLIFY_DWARF_ADDR
+  if (rtl)
+    rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
+#endif
+
+  /* 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;
 }
@@ -8925,6 +9389,7 @@ add_location_or_const_value_attribute (die, decl)
      tree decl;
 {
   rtx rtl;
+  dw_loc_descr_ref descr;
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return;
@@ -8935,16 +9400,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:
@@ -8959,12 +9419,24 @@ 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:
       abort ();
     }
@@ -9096,7 +9568,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);
        }
 
@@ -9711,6 +10184,16 @@ gen_array_type_die (type, context_die)
 #endif
 
   array_die = new_die (DW_TAG_array_type, scope_die, type);
+  add_name_attribute (array_die, type_tag (type));
+  equate_type_number_to_die (type, array_die);
+
+  if (TREE_CODE (type) == VECTOR_TYPE)
+    {
+      /* The frontend feeds us a representation for the vector as a struct
+        containing an array.  Pull out the array type.  */
+      type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
+      add_AT_flag (array_die, DW_AT_GNU_vector, 1);
+    }
 
 #if 0
   /* We default the array ordering.  SDB will probably do
@@ -9732,9 +10215,6 @@ gen_array_type_die (type, context_die)
 #endif
     add_subscript_info (array_die, type);
 
-  add_name_attribute (array_die, type_tag (type));
-  equate_type_number_to_die (type, array_die);
-
   /* Add representation of the type of the elements of this array type.  */
   element_type = TREE_TYPE (type);
 
@@ -9997,7 +10477,7 @@ gen_formal_types_die (function_or_method_type, context_die)
     }
   else
     arg = NULL_TREE;
-  
+
   first_parm_type = TYPE_ARG_TYPES (function_or_method_type);
 
   /* Make our first pass over the list of formal parameter types and output a
@@ -10081,7 +10561,7 @@ dwarf2out_abstract_function (decl)
   /* Make sure we have the actual abstract inline, not a clone.  */
   decl = DECL_ORIGIN (decl);
 
-  old_die = lookup_decl_die (decl);  
+  old_die = lookup_decl_die (decl);
   if (old_die && get_AT_unsigned (old_die, DW_AT_inline))
     /* We've already generated the abstract instance.  */
     return;
@@ -10095,7 +10575,7 @@ dwarf2out_abstract_function (decl)
        gen_type_die_for_member
          (context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
     }
+
   /* Pretend we've just finished compiling this function.  */
   save_fn = current_function_decl;
   current_function_decl = decl;
@@ -10268,10 +10748,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);
@@ -10294,7 +10774,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
     }
 
@@ -10414,7 +10894,7 @@ gen_variable_die (decl, context_die)
 
      ??? Duplicated blocks have been rewritten to use .debug_ranges.  */
   else if (old_die && TREE_STATIC (decl)
-          && get_AT_flag (old_die, DW_AT_declaration) == 1)
+          && get_AT_flag (old_die, DW_AT_declaration) == 1)
     {
       /* This is a definition of a C++ class level static.  */
       add_AT_die_ref (var_die, DW_AT_specification, old_die);
@@ -10726,8 +11206,6 @@ gen_compile_unit_die (filename)
     language = DW_LANG_Pascal83;
   else if (strcmp (language_string, "GNU Java") == 0)
     language = DW_LANG_Java;
-  else if (flag_traditional)
-    language = DW_LANG_C;
   else
     language = DW_LANG_C89;
 
@@ -11009,6 +11487,10 @@ gen_type_die (type, context_die)
   if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
       && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
     {
+      /* Prevent broken recursion; we can't hand off to the same type.  */
+      if (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) == type)
+       abort ();
+
       TREE_ASM_WRITTEN (type) = 1;
       gen_decl_die (TYPE_NAME (type), context_die);
       return;
@@ -11079,7 +11561,7 @@ gen_type_die (type, context_die)
       break;
 
     case VECTOR_TYPE:
-      gen_type_die (TYPE_DEBUG_REPRESENTATION_TYPE (type), context_die);
+      gen_array_type_die (type, context_die);
       break;
 
     case ENUMERAL_TYPE:
@@ -11498,7 +11980,7 @@ mark_limbo_die_list (ptr)
      void *ptr ATTRIBUTE_UNUSED;
 {
   limbo_die_node *node;
-  for (node = limbo_die_list; node ; node = node->next)
+  for (node = limbo_die_list; node; node = node->next)
     ggc_mark_tree (node->created_for);
 }
 \f
@@ -11751,7 +12233,11 @@ lookup_filename (file_name)
   file_table.last_lookup_index = i;
 
   if (DWARF2_ASM_LINE_DEBUG_INFO)
-    fprintf (asm_out_file, "\t.file %u \"%s\"\n", i, file_name);
+    {
+      fprintf (asm_out_file, "\t.file %u ", i);
+      output_quoted_string (asm_out_file, file_name);
+      fputc ('\n', asm_out_file);
+    }
 
   return i;
 }
@@ -11803,7 +12289,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 */
@@ -11823,13 +12309,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.  */
@@ -11858,13 +12344,17 @@ dwarf2out_start_source_file (lineno, filename)
      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);
@@ -11902,13 +12392,6 @@ dwarf2out_define (lineno, buffer)
      unsigned lineno ATTRIBUTE_UNUSED;
      const char *buffer ATTRIBUTE_UNUSED;
 {
-  static int initialized = 0;
-  if (!initialized)
-    {
-      dwarf2out_start_source_file (0, primary_filename);
-      initialized = 1;
-    }
-
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
     {
       named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
@@ -11944,12 +12427,9 @@ dwarf2out_init (main_input_filename)
 {
   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.  */
+  /* Add the name of the primary input file 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.  */
@@ -11960,7 +12440,6 @@ dwarf2out_init (main_input_filename)
 
   /* 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
@@ -11985,12 +12464,11 @@ dwarf2out_init (main_input_filename)
      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);
+  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);
 
@@ -12111,7 +12589,7 @@ dwarf2out_finish (input_filename)
            add_child_die (comp_unit_die, die);
          else if (node->created_for
                   && ((DECL_P (node->created_for)
-                       && (context = DECL_CONTEXT (node->created_for)))
+                       && (context = DECL_CONTEXT (node->created_for)))
                       || (TYPE_P (node->created_for)
                           && (context = TYPE_CONTEXT (node->created_for))))
                   && TREE_CODE (context) == FUNCTION_DECL)
@@ -12156,7 +12634,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
@@ -12204,9 +12682,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);
@@ -12237,9 +12715,10 @@ dwarf2out_finish (input_filename)
 
   /* Have to end the primary source file.  */
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
-    { 
+    {
       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
@@ -12247,4 +12726,11 @@ dwarf2out_finish (input_filename)
   if (debug_str_hash)
     ht_forall (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"