Track indirect calls for call site information in debug info
[gcc.git] / gcc / dwarf2out.c
index 55364a266327b0fb4de091c493861c019687c6a3..6af57b58864317dc7f47c355c74e0049b1de968f 100644 (file)
@@ -58,57 +58,33 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "target.h"
+#include "function.h"
 #include "rtl.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "input.h"
-#include "alias.h"
-#include "symtab.h"
-#include "inchash.h"
 #include "tree.h"
-#include "fold-const.h"
+#include "tm_p.h"
 #include "stringpool.h"
+#include "insn-config.h"
+#include "ira.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "fold-const.h"
 #include "stor-layout.h"
 #include "varasm.h"
-#include "hashtab.h"
-#include "hard-reg-set.h"
-#include "function.h"
-#include "emit-rtl.h"
-#include "hash-table.h"
 #include "version.h"
 #include "flags.h"
-#include "regs.h"
 #include "rtlhash.h"
-#include "insn-config.h"
 #include "reload.h"
 #include "output.h"
-#include "statistics.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "stmt.h"
 #include "expr.h"
-#include "except.h"
-#include "dwarf2.h"
 #include "dwarf2out.h"
 #include "dwarf2asm.h"
 #include "toplev.h"
 #include "md5.h"
-#include "tm_p.h"
-#include "diagnostic.h"
 #include "tree-pretty-print.h"
 #include "debug.h"
-#include "target.h"
 #include "common/common-target.h"
 #include "langhooks.h"
-#include "hash-map.h"
-#include "is-a.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
-#include "cgraph.h"
-#include "ira.h"
 #include "lra.h"
 #include "dumpfile.h"
 #include "opts.h"
@@ -121,6 +97,14 @@ static rtx_insn *last_var_location_insn;
 static rtx_insn *cached_next_real_insn;
 static void dwarf2out_decl (tree);
 
+#ifndef XCOFF_DEBUGGING_INFO
+#define XCOFF_DEBUGGING_INFO 0
+#endif
+
+#ifndef HAVE_XCOFF_DWARF_EXTRAS
+#define HAVE_XCOFF_DWARF_EXTRAS 0
+#endif
+
 #ifdef VMS_DEBUGGING_INFO
 int vms_file_stats_name (const char *, long long *, long *, char *, int *);
 
@@ -229,7 +213,7 @@ struct GTY((for_user)) indirect_string_node {
   unsigned int index;
 };
 
-struct indirect_string_hasher : ggc_hasher<indirect_string_node *>
+struct indirect_string_hasher : ggc_ptr_hash<indirect_string_node>
 {
   typedef const char *compare_type;
 
@@ -384,12 +368,14 @@ dump_struct_debug (tree type, enum debug_info_usage usage,
 #endif
 
 /* Get the number of HOST_WIDE_INTs needed to represent the precision
-   of the number.  */
+   of the number.  Some constants have a large uniform precision, so
+   we get the precision needed for the actual value of the number.  */
 
 static unsigned int
 get_full_len (const wide_int &op)
 {
-  return ((op.get_precision () + HOST_BITS_PER_WIDE_INT - 1)
+  int prec = wi::min_precision (op, UNSIGNED);
+  return ((prec + HOST_BITS_PER_WIDE_INT - 1)
          / HOST_BITS_PER_WIDE_INT);
 }
 
@@ -447,11 +433,8 @@ stripattributes (const char *s)
    for collect2 the first time around.  */
 
 static void
-switch_to_eh_frame_section (bool back)
+switch_to_eh_frame_section (bool back ATTRIBUTE_UNUSED)
 {
-  tree label;
-
-#ifdef EH_FRAME_SECTION_NAME
   if (eh_frame_section == 0)
     {
       int flags;
@@ -479,27 +462,29 @@ switch_to_eh_frame_section (bool back)
        }
       else
        flags = SECTION_WRITE;
+
+#ifdef EH_FRAME_SECTION_NAME
       eh_frame_section = get_section (EH_FRAME_SECTION_NAME, flags, NULL);
-    }
+#else
+      eh_frame_section = ((flags == SECTION_WRITE)
+                         ? data_section : readonly_data_section);
 #endif /* EH_FRAME_SECTION_NAME */
+    }
 
-  if (eh_frame_section)
-    switch_to_section (eh_frame_section);
-  else
-    {
-      /* We have no special eh_frame section.  Put the information in
-        the data section and emit special labels to guide collect2.  */
-      switch_to_section (data_section);
+  switch_to_section (eh_frame_section);
 
-      if (!back)
-       {
-         label = get_file_function_name ("F");
-         ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
-         targetm.asm_out.globalize_label (asm_out_file,
-                                          IDENTIFIER_POINTER (label));
-         ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
-       }
+#ifdef EH_FRAME_THROUGH_COLLECT2
+  /* We have no special eh_frame section.  Emit special labels to guide
+     collect2.  */
+  if (!back)
+    {
+      tree label = get_file_function_name ("F");
+      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
+      targetm.asm_out.globalize_label (asm_out_file,
+                                       IDENTIFIER_POINTER (label));
+      ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
     }
+#endif
 }
 
 /* Switch [BACK] to the eh or debug frame table section, depending on
@@ -608,11 +593,14 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
                                  for_eh + j);
   ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + j);
   ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + j);
-  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
-    dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
-                        " indicating 64-bit DWARF extension");
-  dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
-                       "FDE Length");
+  if (!XCOFF_DEBUGGING_INFO || for_eh)
+    {
+      if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
+       dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
+                            " indicating 64-bit DWARF extension");
+      dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
+                           "FDE Length");
+    }
   ASM_OUTPUT_LABEL (asm_out_file, l1);
 
   if (for_eh)
@@ -808,11 +796,14 @@ output_call_frame_info (int for_eh)
   /* Output the CIE.  */
   ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
   ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
-  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
-    dw2_asm_output_data (4, 0xffffffff,
-      "Initial length escape value indicating 64-bit DWARF extension");
-  dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
-                       "Length of Common Information Entry");
+  if (!XCOFF_DEBUGGING_INFO || for_eh)
+    {
+      if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
+       dw2_asm_output_data (4, 0xffffffff,
+         "Initial length escape value indicating 64-bit DWARF extension");
+      dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
+                           "Length of Common Information Entry");
+    }
   ASM_OUTPUT_LABEL (asm_out_file, l1);
 
   /* Now that the CIE pointer is PC-relative for EH,
@@ -1263,16 +1254,6 @@ struct GTY((for_user)) dwarf_file_data {
   int emitted_number;
 };
 
-typedef struct GTY(()) deferred_locations_struct
-{
-  tree variable;
-  dw_die_ref die;
-} deferred_locations;
-
-
-static GTY(()) vec<deferred_locations, va_gc> *deferred_locations_list;
-
-
 /* Describe an entry into the .debug_addr section.  */
 
 enum ate_kind {
@@ -1281,7 +1262,7 @@ enum ate_kind {
   ate_kind_label
 };
 
-typedef struct GTY((for_user)) addr_table_entry_struct {
+struct GTY((for_user)) addr_table_entry {
   enum ate_kind kind;
   unsigned int refcount;
   unsigned int index;
@@ -1291,8 +1272,7 @@ typedef struct GTY((for_user)) addr_table_entry_struct {
       char * GTY ((tag ("1"))) label;
     }
   GTY ((desc ("%1.kind"))) addr;
-}
-addr_table_entry;
+};
 
 /* Location lists are ranges + location descriptions for that range,
    so you can track variables that are in different places over
@@ -2443,6 +2423,7 @@ build_cfa_aligned_loc (dw_cfa_location *cfa,
 
 static void dwarf2out_init (const char *);
 static void dwarf2out_finish (const char *);
+static void dwarf2out_early_finish (void);
 static void dwarf2out_assembly_start (void);
 static void dwarf2out_define (unsigned int, const char *);
 static void dwarf2out_undef (unsigned int, const char *);
@@ -2452,7 +2433,8 @@ static void dwarf2out_function_decl (tree);
 static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
 static bool dwarf2out_ignore_block (const_tree);
-static void dwarf2out_global_decl (tree);
+static void dwarf2out_early_global_decl (tree);
+static void dwarf2out_late_global_decl (tree);
 static void dwarf2out_type_decl (tree, int);
 static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
 static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
@@ -2461,6 +2443,7 @@ static void dwarf2out_abstract_function (tree);
 static void dwarf2out_var_location (rtx_insn *);
 static void dwarf2out_begin_function (tree);
 static void dwarf2out_end_function (unsigned int);
+static void dwarf2out_register_main_translation_unit (tree unit);
 static void dwarf2out_set_name (tree, tree);
 
 /* The debug hooks structure.  */
@@ -2469,6 +2452,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
 {
   dwarf2out_init,
   dwarf2out_finish,
+  dwarf2out_early_finish,
   dwarf2out_assembly_start,
   dwarf2out_define,
   dwarf2out_undef,
@@ -2489,8 +2473,10 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   dwarf2out_end_epilogue,
   dwarf2out_begin_function,
   dwarf2out_end_function,      /* end_function */
+  dwarf2out_register_main_translation_unit,
   dwarf2out_function_decl,     /* function_decl */
-  dwarf2out_global_decl,
+  dwarf2out_early_global_decl,
+  dwarf2out_late_global_decl,
   dwarf2out_type_decl,         /* type_decl */
   dwarf2out_imported_module_or_decl,
   debug_nothing_tree,          /* deferred_inline_function */
@@ -2506,6 +2492,43 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   1,                            /* start_end_main_source_file */
   TYPE_SYMTAB_IS_DIE            /* tree_type_symtab_field */
 };
+
+const struct gcc_debug_hooks dwarf2_lineno_debug_hooks =
+{
+  dwarf2out_init,
+  debug_nothing_charstar,
+  debug_nothing_void,
+  debug_nothing_void,
+  debug_nothing_int_charstar,
+  debug_nothing_int_charstar,
+  debug_nothing_int_charstar,
+  debug_nothing_int,
+  debug_nothing_int_int,                /* begin_block */
+  debug_nothing_int_int,                /* end_block */
+  debug_true_const_tree,                /* ignore_block */
+  dwarf2out_source_line,        /* source_line */
+  debug_nothing_int_charstar,           /* begin_prologue */
+  debug_nothing_int_charstar,           /* end_prologue */
+  debug_nothing_int_charstar,           /* begin_epilogue */
+  debug_nothing_int_charstar,           /* end_epilogue */
+  debug_nothing_tree,                   /* begin_function */
+  debug_nothing_int,                    /* end_function */
+  debug_nothing_tree,                   /* register_main_translation_unit */
+  debug_nothing_tree,                   /* function_decl */
+  debug_nothing_tree,                   /* early_global_decl */
+  debug_nothing_tree,                   /* late_global_decl */
+  debug_nothing_tree_int,               /* type_decl */
+  debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
+  debug_nothing_tree,                   /* deferred_inline_function */
+  debug_nothing_tree,                   /* outlining_inline_function */
+  debug_nothing_rtx_code_label,                 /* label */
+  debug_nothing_int,                    /* handle_pch */
+  debug_nothing_rtx_insn,               /* var_location */
+  debug_nothing_void,                    /* switch_text_section */
+  debug_nothing_tree_tree,              /* set_name */
+  0,                                     /* start_end_main_source_file */
+  TYPE_SYMTAB_IS_ADDRESS                 /* tree_type_symtab_field */
+};
 \f
 /* NOTE: In the comments in this file, many references are made to
    "Debugging Information Entries".  This term is abbreviated as `DIE'
@@ -2531,14 +2554,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
 
 typedef long int dw_offset;
 
-/* Define typedefs here to avoid circular dependencies.  */
-
-typedef struct dw_attr_struct *dw_attr_ref;
-typedef struct dw_line_info_struct *dw_line_info_ref;
-typedef struct pubname_struct *pubname_ref;
-typedef struct dw_ranges_struct *dw_ranges_ref;
-typedef struct dw_ranges_by_label_struct *dw_ranges_by_label_ref;
-typedef struct comdat_type_struct *comdat_type_node_ref;
+struct comdat_type_node;
 
 /* The entries in the line_info table more-or-less mirror the opcodes
    that are used in the real dwarf line table.  Arrays of these entries
@@ -2577,7 +2593,7 @@ typedef struct GTY(()) dw_line_info_struct {
 } dw_line_info_entry;
 
 
-typedef struct GTY(()) dw_line_info_table_struct {
+struct GTY(()) dw_line_info_table {
   /* The label that marks the end of this section.  */
   const char *end_label;
 
@@ -2591,9 +2607,7 @@ typedef struct GTY(()) dw_line_info_table_struct {
   bool in_use;
 
   vec<dw_line_info_entry, va_gc> *entries;
-} dw_line_info_table;
-
-typedef dw_line_info_table *dw_line_info_table_p;
+};
 
 
 /* Each DIE attribute has a field specifying the attribute kind,
@@ -2615,7 +2629,7 @@ typedef struct GTY((chain_circular ("%h.die_sib"), for_user)) die_struct {
   union die_symbol_or_type_node
     {
       const char * GTY ((tag ("0"))) die_symbol;
-      comdat_type_node_ref GTY ((tag ("1"))) die_type_node;
+      comdat_type_node *GTY ((tag ("1"))) die_type_node;
     }
   GTY ((desc ("%0.comdat_type_p"))) die_id;
   vec<dw_attr_node, va_gc> *die_attr;
@@ -2635,6 +2649,14 @@ typedef struct GTY((chain_circular ("%h.die_sib"), for_user)) die_struct {
 }
 die_node;
 
+/* Set to TRUE while dwarf2out_early_global_decl is running.  */
+static bool early_dwarf;
+struct set_early_dwarf {
+  bool saved;
+  set_early_dwarf () : saved(early_dwarf) { early_dwarf = true; }
+  ~set_early_dwarf () { early_dwarf = saved; }
+};
+
 /* Evaluate 'expr' while 'c' is set to each child of DIE in order.  */
 #define FOR_EACH_CHILD(die, c, expr) do {      \
   c = die->die_child;                          \
@@ -2653,7 +2675,7 @@ typedef struct GTY(()) pubname_struct {
 pubname_entry;
 
 
-struct GTY(()) dw_ranges_struct {
+struct GTY(()) dw_ranges {
   /* If this is positive, it's a block number, otherwise it's a
      bitwise-negated index into dw_ranges_by_label.  */
   int num;
@@ -2669,25 +2691,28 @@ typedef struct GTY(()) macinfo_struct {
 macinfo_entry;
 
 
-struct GTY(()) dw_ranges_by_label_struct {
+struct GTY(()) dw_ranges_by_label {
   const char *begin;
   const char *end;
 };
 
 /* The comdat type node structure.  */
-typedef struct GTY(()) comdat_type_struct
+struct GTY(()) comdat_type_node
 {
   dw_die_ref root_die;
   dw_die_ref type_die;
   dw_die_ref skeleton_die;
   char signature[DWARF_TYPE_SIGNATURE_SIZE];
-  struct comdat_type_struct *next;
-}
-comdat_type_node;
+  comdat_type_node *next;
+};
 
-/* The limbo die list structure.  */
+/* A list of DIEs for which we can't determine ancestry (parent_die
+   field) just yet.  Later in dwarf2out_finish we will fill in the
+   missing bits.  */
 typedef struct GTY(()) limbo_die_struct {
   dw_die_ref die;
+  /* The tree for which this DIE was created.  We use this to
+     determine ancestry later.  */
   tree created_for;
   struct limbo_die_struct *next;
 }
@@ -2797,7 +2822,7 @@ static GTY(()) limbo_die_node *limbo_die_list;
    DW_AT_{,MIPS_}linkage_name once their DECL_ASSEMBLER_NAMEs are set.  */
 static GTY(()) limbo_die_node *deferred_asm_name;
 
-struct dwarf_file_hasher : ggc_hasher<dwarf_file_data *>
+struct dwarf_file_hasher : ggc_ptr_hash<dwarf_file_data>
 {
   typedef const char *compare_type;
 
@@ -2808,7 +2833,7 @@ struct dwarf_file_hasher : ggc_hasher<dwarf_file_data *>
 /* Filenames referenced by this compilation unit.  */
 static GTY(()) hash_table<dwarf_file_hasher> *file_table;
 
-struct decl_die_hasher : ggc_hasher<die_node *>
+struct decl_die_hasher : ggc_ptr_hash<die_node>
 {
   typedef tree compare_type;
 
@@ -2819,7 +2844,7 @@ struct decl_die_hasher : ggc_hasher<die_node *>
    The key is a DECL_UID() which is a unique number identifying each decl.  */
 static GTY (()) hash_table<decl_die_hasher> *decl_die_table;
 
-struct block_die_hasher : ggc_hasher<die_struct *>
+struct block_die_hasher : ggc_ptr_hash<die_struct>
 {
   static hashval_t hash (die_struct *);
   static bool equal (die_struct *, die_struct *);
@@ -2883,7 +2908,7 @@ struct GTY ((chain_next ("%h.next"))) call_arg_loc_node {
 };
 
 
-struct decl_loc_hasher : ggc_hasher<var_loc_list *>
+struct decl_loc_hasher : ggc_ptr_hash<var_loc_list>
 {
   typedef const_tree compare_type;
 
@@ -2913,7 +2938,7 @@ struct GTY ((for_user)) cached_dw_loc_list_def {
 };
 typedef struct cached_dw_loc_list_def cached_dw_loc_list;
 
-struct dw_loc_list_hasher : ggc_hasher<cached_dw_loc_list *>
+struct dw_loc_list_hasher : ggc_ptr_hash<cached_dw_loc_list>
 {
 
   typedef const_tree compare_type;
@@ -2934,7 +2959,7 @@ static GTY((length ("abbrev_die_table_allocated")))
 /* Number of elements currently allocated for abbrev_die_table.  */
 static GTY(()) unsigned abbrev_die_table_allocated;
 
-/* Number of elements in type_die_table currently in use.  */
+/* Number of elements in abbrev_die_table currently in use.  */
 static GTY(()) unsigned abbrev_die_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
@@ -2954,7 +2979,7 @@ static GTY(()) dw_line_info_table *text_section_line_info;
 static GTY(()) dw_line_info_table *cold_text_section_line_info;
 
 /* The set of all non-default tables of line number info.  */
-static GTY(()) vec<dw_line_info_table_p, va_gc> *separate_line_info;
+static GTY(()) vec<dw_line_info_table *, va_gc> *separate_line_info;
 
 /* A flag to tell pubnames/types export if there is an info section to
    refer to.  */
@@ -2975,11 +3000,12 @@ static GTY (()) vec<macinfo_entry, va_gc> *macinfo_table;
 /* True if .debug_macinfo or .debug_macros section is going to be
    emitted.  */
 #define have_macinfo \
-  (debug_info_level >= DINFO_LEVEL_VERBOSE \
+  ((!XCOFF_DEBUGGING_INFO || HAVE_XCOFF_DWARF_EXTRAS) \
+   && debug_info_level >= DINFO_LEVEL_VERBOSE \
    && !macinfo_table->is_empty ())
 
 /* Array of dies for which we should generate .debug_ranges info.  */
-static GTY ((length ("ranges_table_allocated"))) dw_ranges_ref ranges_table;
+static GTY ((length ("ranges_table_allocated"))) dw_ranges *ranges_table;
 
 /* Number of elements currently allocated for ranges_table.  */
 static GTY(()) unsigned ranges_table_allocated;
@@ -2989,7 +3015,7 @@ static GTY(()) unsigned ranges_table_in_use;
 
 /* Array of pairs of labels referenced in ranges_table.  */
 static GTY ((length ("ranges_by_label_allocated")))
-     dw_ranges_by_label_ref ranges_by_label;
+     dw_ranges_by_label *ranges_by_label;
 
 /* Number of elements currently allocated for ranges_by_label.  */
 static GTY(()) unsigned ranges_by_label_allocated;
@@ -3016,9 +3042,6 @@ static GTY(()) struct dwarf_file_data * last_emitted_file;
 /* Number of internal labels generated by gen_internal_sym().  */
 static GTY(()) int label_num;
 
-/* Cached result of previous call to lookup_filename.  */
-static GTY(()) struct dwarf_file_data * file_table_last_lookup;
-
 static GTY(()) vec<die_arg_entry, va_gc> *tmpl_value_parm_die_table;
 
 /* Instances of generic types for which we need to generate debug
@@ -3053,38 +3076,38 @@ static const char *dwarf_attr_name (unsigned);
 static const char *dwarf_form_name (unsigned);
 static tree decl_ultimate_origin (const_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 inline unsigned int AT_index (dw_attr_ref);
+static void add_dwarf_attr (dw_die_ref, dw_attr_node *);
+static inline enum dw_val_class AT_class (dw_attr_node *);
+static inline unsigned int AT_index (dw_attr_node *);
 static void add_AT_flag (dw_die_ref, enum dwarf_attribute, unsigned);
-static inline unsigned AT_flag (dw_attr_ref);
+static inline unsigned AT_flag (dw_attr_node *);
 static void add_AT_int (dw_die_ref, enum dwarf_attribute, HOST_WIDE_INT);
-static inline HOST_WIDE_INT AT_int (dw_attr_ref);
+static inline HOST_WIDE_INT AT_int (dw_attr_node *);
 static void add_AT_unsigned (dw_die_ref, enum dwarf_attribute, unsigned HOST_WIDE_INT);
-static inline unsigned HOST_WIDE_INT AT_unsigned (dw_attr_ref);
+static inline unsigned HOST_WIDE_INT AT_unsigned (dw_attr_node *);
 static void add_AT_double (dw_die_ref, enum dwarf_attribute,
                           HOST_WIDE_INT, unsigned HOST_WIDE_INT);
 static inline void add_AT_vec (dw_die_ref, enum dwarf_attribute, unsigned int,
                               unsigned int, unsigned char *);
 static void add_AT_data8 (dw_die_ref, enum dwarf_attribute, unsigned char *);
 static void add_AT_string (dw_die_ref, enum dwarf_attribute, const char *);
-static inline const char *AT_string (dw_attr_ref);
-static enum dwarf_form AT_string_form (dw_attr_ref);
+static inline const char *AT_string (dw_attr_node *);
+static enum dwarf_form AT_string_form (dw_attr_node *);
 static void add_AT_die_ref (dw_die_ref, enum dwarf_attribute, dw_die_ref);
 static void add_AT_specification (dw_die_ref, 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 inline dw_die_ref AT_ref (dw_attr_node *);
+static inline int AT_ref_external (dw_attr_node *);
+static inline void set_AT_ref_external (dw_attr_node *, 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 inline dw_loc_descr_ref AT_loc (dw_attr_node *);
 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 inline dw_loc_list_ref AT_loc_list (dw_attr_node *);
 static addr_table_entry *add_addr_table_entry (void *, enum ate_kind);
 static void remove_addr_table_entry (addr_table_entry *);
 static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx, bool);
-static inline rtx AT_addr (dw_attr_ref);
+static inline rtx AT_addr (dw_attr_node *);
 static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *);
 static void add_AT_lineptr (dw_die_ref, enum dwarf_attribute, const char *);
 static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *);
@@ -3092,8 +3115,8 @@ static void add_AT_offset (dw_die_ref, enum dwarf_attribute,
                           unsigned HOST_WIDE_INT);
 static void add_AT_range_list (dw_die_ref, enum dwarf_attribute,
                                unsigned long, bool);
-static inline const char *AT_lbl (dw_attr_ref);
-static dw_attr_ref get_AT (dw_die_ref, enum dwarf_attribute);
+static inline const char *AT_lbl (dw_attr_node *);
+static dw_attr_node *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);
@@ -3103,7 +3126,7 @@ static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
 static bool is_cxx (void);
 static bool is_fortran (void);
 static bool is_ada (void);
-static void remove_AT (dw_die_ref, enum dwarf_attribute);
+static bool remove_AT (dw_die_ref, enum dwarf_attribute);
 static void remove_child_TAG (dw_die_ref, enum dwarf_tag);
 static void add_child_die (dw_die_ref, dw_die_ref);
 static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
@@ -3120,12 +3143,12 @@ static void print_die (dw_die_ref, FILE *);
 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 attr_checksum (dw_attr_node *, struct md5_ctx *, int *);
 static void die_checksum (dw_die_ref, struct md5_ctx *, int *);
 static void checksum_sleb128 (HOST_WIDE_INT, struct md5_ctx *);
 static void checksum_uleb128 (unsigned HOST_WIDE_INT, struct md5_ctx *);
 static void loc_checksum_ordered (dw_loc_descr_ref, struct md5_ctx *);
-static void attr_checksum_ordered (enum dwarf_tag, dw_attr_ref,
+static void attr_checksum_ordered (enum dwarf_tag, dw_attr_node *,
                                   struct md5_ctx *, int *);
 struct checksum_attributes;
 static void collect_checksum_attributes (struct checksum_attributes *, dw_die_ref);
@@ -3134,7 +3157,7 @@ static void checksum_die_context (dw_die_ref, struct md5_ctx *);
 static void generate_type_signature (dw_die_ref, comdat_type_node *);
 static int same_loc_p (dw_loc_descr_ref, dw_loc_descr_ref, int *);
 static int same_dw_val_p (const dw_val_node *, const dw_val_node *, int *);
-static int same_attr_p (dw_attr_ref, dw_attr_ref, int *);
+static int same_attr_p (dw_attr_node *, dw_attr_node *, 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);
@@ -3170,8 +3193,8 @@ static void unmark_dies (dw_die_ref);
 static void unmark_all_dies (dw_die_ref);
 static unsigned long size_of_pubnames (vec<pubname_entry, va_gc> *);
 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 enum dwarf_form value_format (dw_attr_node *);
+static void output_value_format (dw_attr_node *);
 static void output_abbrev_section (void);
 static void output_die_abbrevs (unsigned long, dw_die_ref);
 static void output_die_symbol (dw_die_ref);
@@ -3185,7 +3208,7 @@ static void add_enumerator_pubname (const char *, dw_die_ref);
 static void add_pubname_string (const char *, dw_die_ref);
 static void add_pubtype (tree, dw_die_ref);
 static void output_pubnames (vec<pubname_entry, va_gc> *);
-static void output_aranges (unsigned long);
+static void output_aranges (void);
 static unsigned int add_ranges_num (int);
 static unsigned int add_ranges (const_tree);
 static void add_ranges_by_labels (dw_die_ref, const char *, const char *,
@@ -3236,8 +3259,7 @@ static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
 static void insert_wide_int (const wide_int &, unsigned char *, int);
 static void insert_float (const_rtx, unsigned char *);
 static rtx rtl_for_decl_location (tree);
-static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool,
-                                                  enum dwarf_attribute);
+static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool);
 static bool tree_add_const_value_attribute (dw_die_ref, tree);
 static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
@@ -3329,8 +3351,8 @@ 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 (struct dwarf_file_data *fd);
-static inline const char *AT_vms_delta1 (dw_attr_ref);
-static inline const char *AT_vms_delta2 (dw_attr_ref);
+static inline const char *AT_vms_delta1 (dw_attr_node *);
+static inline const char *AT_vms_delta2 (dw_attr_node *);
 static inline void add_AT_vms_delta (dw_die_ref, enum dwarf_attribute,
                                     const char *, const char *);
 static void append_entry_to_tmpl_value_parm_die_table (dw_die_ref, tree);
@@ -3772,7 +3794,7 @@ decl_class_context (tree decl)
 /* Add an attribute/value pair to a DIE.  */
 
 static inline void
-add_dwarf_attr (dw_die_ref die, dw_attr_ref attr)
+add_dwarf_attr (dw_die_ref die, dw_attr_node *attr)
 {
   /* Maybe this should be an assert?  */
   if (die == NULL)
@@ -3783,7 +3805,7 @@ add_dwarf_attr (dw_die_ref die, dw_attr_ref attr)
 }
 
 static inline enum dw_val_class
-AT_class (dw_attr_ref a)
+AT_class (dw_attr_node *a)
 {
   return a->dw_attr_val.val_class;
 }
@@ -3794,7 +3816,7 @@ AT_class (dw_attr_ref a)
    pruning.  */
 
 static inline unsigned int
-AT_index (dw_attr_ref a)
+AT_index (dw_attr_node *a)
 {
   if (AT_class (a) == dw_val_class_str)
     return a->dw_attr_val.v.val_str->index;
@@ -3818,7 +3840,7 @@ add_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int flag)
 }
 
 static inline unsigned
-AT_flag (dw_attr_ref a)
+AT_flag (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_flag);
   return a->dw_attr_val.v.val_flag;
@@ -3839,7 +3861,7 @@ add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, HOST_WIDE_INT int_va
 }
 
 static inline HOST_WIDE_INT
-AT_int (dw_attr_ref a)
+AT_int (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_const);
   return a->dw_attr_val.v.val_int;
@@ -3861,7 +3883,7 @@ add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind,
 }
 
 static inline unsigned HOST_WIDE_INT
-AT_unsigned (dw_attr_ref a)
+AT_unsigned (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_unsigned_const);
   return a->dw_attr_val.v.val_unsigned;
@@ -4036,7 +4058,7 @@ add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str)
 }
 
 static inline const char *
-AT_string (dw_attr_ref a)
+AT_string (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_str);
   return a->dw_attr_val.v.val_str->str;
@@ -4106,7 +4128,7 @@ find_string_form (struct indirect_string_node *node)
    output inline in DIE or out-of-line in .debug_str section.  */
 
 static enum dwarf_form
-AT_string_form (dw_attr_ref a)
+AT_string_form (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_str);
   return find_string_form (a->dw_attr_val.v.val_str);
@@ -4118,15 +4140,12 @@ static inline void
 add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_die)
 {
   dw_attr_node attr;
+  gcc_checking_assert (targ_die != NULL);
 
-#ifdef ENABLE_CHECKING
-  gcc_assert (targ_die != NULL);
-#else
   /* With LTO we can end up trying to reference something we didn't create
      a DIE for.  Avoid crashing later on a NULL referenced DIE.  */
   if (targ_die == NULL)
     return;
-#endif
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_die_ref;
@@ -4139,7 +4158,7 @@ add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_
 /* Change DIE reference REF to point to NEW_DIE instead.  */
 
 static inline void
-change_AT_die_ref (dw_attr_ref ref, dw_die_ref new_die)
+change_AT_die_ref (dw_attr_node *ref, dw_die_ref new_die)
 {
   gcc_assert (ref->dw_attr_val.val_class == dw_val_class_die_ref);
   ref->dw_attr_val.v.val_die_ref.die = new_die;
@@ -4158,14 +4177,14 @@ add_AT_specification (dw_die_ref die, dw_die_ref targ_die)
 }
 
 static inline dw_die_ref
-AT_ref (dw_attr_ref a)
+AT_ref (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_die_ref);
   return a->dw_attr_val.v.val_die_ref.die;
 }
 
 static inline int
-AT_ref_external (dw_attr_ref a)
+AT_ref_external (dw_attr_node *a)
 {
   if (a && AT_class (a) == dw_val_class_die_ref)
     return a->dw_attr_val.v.val_die_ref.external;
@@ -4174,7 +4193,7 @@ AT_ref_external (dw_attr_ref a)
 }
 
 static inline void
-set_AT_ref_external (dw_attr_ref a, int i)
+set_AT_ref_external (dw_attr_node *a, int i)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_die_ref);
   a->dw_attr_val.v.val_die_ref.external = i;
@@ -4209,7 +4228,7 @@ add_AT_loc (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_descr_ref loc
 }
 
 static inline dw_loc_descr_ref
-AT_loc (dw_attr_ref a)
+AT_loc (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_loc);
   return a->dw_attr_val.v.val_loc;
@@ -4220,6 +4239,9 @@ add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref
 {
   dw_attr_node attr;
 
+  if (XCOFF_DEBUGGING_INFO && !HAVE_XCOFF_DWARF_EXTRAS)
+    return;
+
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_loc_list;
   attr.dw_attr_val.val_entry = NULL;
@@ -4229,20 +4251,20 @@ add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref
 }
 
 static inline dw_loc_list_ref
-AT_loc_list (dw_attr_ref a)
+AT_loc_list (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_loc_list);
   return a->dw_attr_val.v.val_loc_list;
 }
 
 static inline dw_loc_list_ref *
-AT_loc_list_ptr (dw_attr_ref a)
+AT_loc_list_ptr (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_loc_list);
   return &a->dw_attr_val.v.val_loc_list;
 }
 
-struct addr_hasher : ggc_hasher<addr_table_entry *>
+struct addr_hasher : ggc_ptr_hash<addr_table_entry>
 {
   static hashval_t hash (addr_table_entry *);
   static bool equal (addr_table_entry *, addr_table_entry *);
@@ -4416,7 +4438,7 @@ add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr,
 /* Get the RTX from to an address DIE attribute.  */
 
 static inline rtx
-AT_addr (dw_attr_ref a)
+AT_addr (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_addr);
   return a->dw_attr_val.v.val_addr;
@@ -4440,7 +4462,7 @@ add_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind,
 /* Get the dwarf_file_data from a file DIE attribute.  */
 
 static inline struct dwarf_file_data *
-AT_file (dw_attr_ref a)
+AT_file (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_file);
   return a->dw_attr_val.v.val_file;
@@ -4558,7 +4580,7 @@ add_AT_range_list (dw_die_ref die, enum dwarf_attribute attr_kind,
 /* Return the start label of a delta attribute.  */
 
 static inline const char *
-AT_vms_delta1 (dw_attr_ref a)
+AT_vms_delta1 (dw_attr_node *a)
 {
   gcc_assert (a && (AT_class (a) == dw_val_class_vms_delta));
   return a->dw_attr_val.v.val_vms_delta.lbl1;
@@ -4567,14 +4589,14 @@ AT_vms_delta1 (dw_attr_ref a)
 /* Return the end label of a delta attribute.  */
 
 static inline const char *
-AT_vms_delta2 (dw_attr_ref a)
+AT_vms_delta2 (dw_attr_node *a)
 {
   gcc_assert (a && (AT_class (a) == dw_val_class_vms_delta));
   return a->dw_attr_val.v.val_vms_delta.lbl2;
 }
 
 static inline const char *
-AT_lbl (dw_attr_ref a)
+AT_lbl (dw_attr_node *a)
 {
   gcc_assert (a && (AT_class (a) == dw_val_class_lbl_id
                    || AT_class (a) == dw_val_class_lineptr
@@ -4585,10 +4607,10 @@ AT_lbl (dw_attr_ref a)
 
 /* Get the attribute of type attr_kind.  */
 
-static dw_attr_ref
+static dw_attr_node *
 get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
   dw_die_ref spec = NULL;
 
@@ -4632,7 +4654,7 @@ get_die_parent (dw_die_ref die)
 static inline const char *
 get_AT_low_pc (dw_die_ref die)
 {
-  dw_attr_ref a = get_AT (die, DW_AT_low_pc);
+  dw_attr_node *a = get_AT (die, DW_AT_low_pc);
 
   return a ? AT_lbl (a) : NULL;
 }
@@ -4644,7 +4666,7 @@ get_AT_low_pc (dw_die_ref die)
 static inline const char *
 get_AT_hi_pc (dw_die_ref die)
 {
-  dw_attr_ref a = get_AT (die, DW_AT_high_pc);
+  dw_attr_node *a = get_AT (die, DW_AT_high_pc);
 
   return a ? AT_lbl (a) : NULL;
 }
@@ -4655,7 +4677,7 @@ get_AT_hi_pc (dw_die_ref die)
 static inline const char *
 get_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_node *a = get_AT (die, attr_kind);
 
   return a ? AT_string (a) : NULL;
 }
@@ -4666,7 +4688,7 @@ get_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind)
 static inline int
 get_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_node *a = get_AT (die, attr_kind);
 
   return a ? AT_flag (a) : 0;
 }
@@ -4677,7 +4699,7 @@ get_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind)
 static inline unsigned
 get_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_node *a = get_AT (die, attr_kind);
 
   return a ? AT_unsigned (a) : 0;
 }
@@ -4685,7 +4707,7 @@ get_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind)
 static inline dw_die_ref
 get_AT_ref (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_node *a = get_AT (die, attr_kind);
 
   return a ? AT_ref (a) : NULL;
 }
@@ -4693,7 +4715,7 @@ get_AT_ref (dw_die_ref die, enum dwarf_attribute attr_kind)
 static inline struct dwarf_file_data *
 get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_node *a = get_AT (die, attr_kind);
 
   return a ? AT_file (a) : NULL;
 }
@@ -4743,16 +4765,17 @@ is_ada (void)
   return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
 }
 
-/* Remove the specified attribute if present.  */
+/* Remove the specified attribute if present.  Return TRUE if removal
+   was successful.  */
 
-static void
+static bool
 remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   if (! die)
-    return;
+    return false;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (a->dw_attr == attr_kind)
@@ -4764,8 +4787,9 @@ remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
        /* vec::ordered_remove should help reduce the number of abbrevs
           that are needed.  */
        die->die_attr->ordered_remove (ix);
-       return;
+       return true;
       }
+  return false;
 }
 
 /* Remove CHILD from its parent.  PREV must have the property that
@@ -4839,6 +4863,7 @@ remove_child_TAG (dw_die_ref die, enum dwarf_tag tag)
     while (c->die_tag == tag)
       {
        remove_child_with_prev (c, prev);
+       c->die_parent = NULL;
        /* Might have removed every child.  */
        if (c == c->die_sib)
          return;
@@ -4868,6 +4893,21 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
   die->die_child = child_die;
 }
 
+/* Unassociate CHILD from its parent, and make its parent be
+   NEW_PARENT.  */
+
+static void
+reparent_child (dw_die_ref child, dw_die_ref new_parent)
+{
+  for (dw_die_ref p = child->die_parent->die_child; ; p = p->die_sib)
+    if (p->die_sib == child)
+      {
+       remove_child_with_prev (child, p);
+       break;
+      }
+  add_child_die (new_parent, child);
+}
+
 /* Move CHILD, which must be a child of PARENT or the DIE for which PARENT
    is the specification, to the end of PARENT's list of children.
    This is done by removing and re-adding it.  */
@@ -4875,8 +4915,6 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
 static void
 splice_child_die (dw_die_ref parent, dw_die_ref child)
 {
-  dw_die_ref p;
-
   /* We want the declaration DIE from inside the class, not the
      specification DIE at toplevel.  */
   if (child->die_parent != parent)
@@ -4891,17 +4929,13 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
              || (child->die_parent
                  == get_AT_ref (parent, DW_AT_specification)));
 
-  for (p = child->die_parent->die_child; ; p = p->die_sib)
-    if (p->die_sib == child)
-      {
-       remove_child_with_prev (child, p);
-       break;
-      }
-
-  add_child_die (parent, child);
+  reparent_child (child, parent);
 }
 
-/* Return a pointer to a newly created DIE node.  */
+/* Create and return a new die with a parent of PARENT_DIE.  If
+   PARENT_DIE is NULL, the new DIE is placed in limbo and an
+   associated tree T must be supplied to determine parenthood
+   later.  */
 
 static inline dw_die_ref
 new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
@@ -4916,6 +4950,35 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
     {
       limbo_die_node *limbo_node;
 
+      /* No DIEs created after early dwarf should end up in limbo,
+        because the limbo list should not persist past LTO
+        streaming.  */
+      if (tag_value != DW_TAG_compile_unit
+         /* These are allowed because they're generated while
+            breaking out COMDAT units late.  */
+         && tag_value != DW_TAG_type_unit
+         && !early_dwarf
+         /* Allow nested functions to live in limbo because they will
+            only temporarily live there, as decls_for_scope will fix
+            them up.  */
+         && (TREE_CODE (t) != FUNCTION_DECL
+             || !decl_function_context (t))
+         /* Same as nested functions above but for types.  Types that
+            are local to a function will be fixed in
+            decls_for_scope.  */
+         && (!RECORD_OR_UNION_TYPE_P (t)
+             || !TYPE_CONTEXT (t)
+             || TREE_CODE (TYPE_CONTEXT (t)) != FUNCTION_DECL)
+         /* FIXME debug-early: Allow late limbo DIE creation for LTO,
+            especially in the ltrans stage, but once we implement LTO
+            dwarf streaming, we should remove this exception.  */
+         && !in_lto_p)
+       {
+         fprintf (stderr, "symbol ended up in limbo too late:");
+         debug_generic_stmt (t);
+         gcc_unreachable ();
+       }
+
       limbo_node = ggc_cleared_alloc<limbo_die_node> ();
       limbo_node->die = die;
       limbo_node->created_for = t;
@@ -5210,9 +5273,10 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
              && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))
        {
          HOST_WIDE_INT maxsize;
-         tree innerdecl;
-         innerdecl
-           = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize);
+         bool reverse;
+         tree innerdecl
+           = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize,
+                                      &reverse);
          if (!DECL_P (innerdecl)
              || DECL_IGNORED_P (innerdecl)
              || TREE_STATIC (innerdecl)
@@ -5519,7 +5583,7 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
 /* Likewise, for a DIE attribute.  */
 
 static void
-print_attribute (dw_attr_ref a, bool recurse, FILE *outfile)
+print_attribute (dw_attr_node *a, bool recurse, FILE *outfile)
 {
   print_dw_val (&a->dw_attr_val, recurse, outfile);
 }
@@ -5566,7 +5630,7 @@ print_loc_descr (dw_loc_descr_ref loc, FILE *outfile)
 static void
 print_die (dw_die_ref die, FILE *outfile)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   dw_die_ref c;
   unsigned ix;
 
@@ -5647,6 +5711,69 @@ debug_dwarf (void)
   print_indent = 0;
   print_die (comp_unit_die (), stderr);
 }
+
+/* Sanity checks on DIEs.  */
+
+static void
+check_die (dw_die_ref die)
+{
+  unsigned ix;
+  dw_attr_node *a;
+  bool inline_found = false;
+  int n_location = 0, n_low_pc = 0, n_high_pc = 0, n_artificial = 0;
+  int n_decl_line = 0, n_decl_file = 0;
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+    {
+      switch (a->dw_attr)
+       {
+       case DW_AT_inline:
+         if (a->dw_attr_val.v.val_unsigned)
+           inline_found = true;
+         break;
+       case DW_AT_location:
+         ++n_location;
+         break;
+       case DW_AT_low_pc:
+         ++n_low_pc;
+         break;
+       case DW_AT_high_pc:
+         ++n_high_pc;
+         break;
+       case DW_AT_artificial:
+         ++n_artificial;
+         break;
+       case DW_AT_decl_line:
+         ++n_decl_line;
+         break;
+       case DW_AT_decl_file:
+         ++n_decl_file;
+         break;
+       default:
+         break;
+       }
+    }
+  if (n_location > 1 || n_low_pc > 1 || n_high_pc > 1 || n_artificial > 1
+      || n_decl_line > 1 || n_decl_file > 1)
+    {
+      fprintf (stderr, "Duplicate attributes in DIE:\n");
+      debug_dwarf_die (die);
+      gcc_unreachable ();
+    }
+  if (inline_found)
+    {
+      /* A debugging information entry that is a member of an abstract
+        instance tree [that has DW_AT_inline] should not contain any
+        attributes which describe aspects of the subroutine which vary
+        between distinct inlined expansions or distinct out-of-line
+        expansions.  */
+      FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+       gcc_assert (a->dw_attr != DW_AT_low_pc
+                   && a->dw_attr != DW_AT_high_pc
+                   && a->dw_attr != DW_AT_location
+                   && a->dw_attr != DW_AT_frame_base
+                   && a->dw_attr != DW_AT_GNU_all_call_sites);
+    }
+}
 \f
 /* Start a new compilation unit DIE for an include file.  OLD_UNIT is the CU
    for the enclosing include file, if any.  BINCL_DIE is the DW_TAG_GNU_BINCL
@@ -5696,7 +5823,7 @@ loc_checksum (dw_loc_descr_ref loc, struct md5_ctx *ctx)
 /* Calculate the checksum of an attribute.  */
 
 static void
-attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark)
+attr_checksum (dw_attr_node *at, struct md5_ctx *ctx, int *mark)
 {
   dw_loc_descr_ref loc;
   rtx r;
@@ -5782,7 +5909,7 @@ static void
 die_checksum (dw_die_ref die, struct md5_ctx *ctx, int *mark)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   /* To avoid infinite recursion.  */
@@ -5916,7 +6043,7 @@ loc_checksum_ordered (dw_loc_descr_ref loc, struct md5_ctx *ctx)
 /* Calculate the checksum of an attribute.  */
 
 static void
-attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
+attr_checksum_ordered (enum dwarf_tag tag, dw_attr_node *at,
                       struct md5_ctx *ctx, int *mark)
 {
   dw_loc_descr_ref loc;
@@ -5939,7 +6066,7 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
          || (at->dw_attr == DW_AT_friend
              && tag == DW_TAG_friend))
        {
-         dw_attr_ref name_attr = get_AT (target_die, DW_AT_name);
+         dw_attr_node *name_attr = get_AT (target_die, DW_AT_name);
 
          if (name_attr != NULL)
            {
@@ -6071,53 +6198,53 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
 
 struct checksum_attributes
 {
-  dw_attr_ref at_name;
-  dw_attr_ref at_type;
-  dw_attr_ref at_friend;
-  dw_attr_ref at_accessibility;
-  dw_attr_ref at_address_class;
-  dw_attr_ref at_allocated;
-  dw_attr_ref at_artificial;
-  dw_attr_ref at_associated;
-  dw_attr_ref at_binary_scale;
-  dw_attr_ref at_bit_offset;
-  dw_attr_ref at_bit_size;
-  dw_attr_ref at_bit_stride;
-  dw_attr_ref at_byte_size;
-  dw_attr_ref at_byte_stride;
-  dw_attr_ref at_const_value;
-  dw_attr_ref at_containing_type;
-  dw_attr_ref at_count;
-  dw_attr_ref at_data_location;
-  dw_attr_ref at_data_member_location;
-  dw_attr_ref at_decimal_scale;
-  dw_attr_ref at_decimal_sign;
-  dw_attr_ref at_default_value;
-  dw_attr_ref at_digit_count;
-  dw_attr_ref at_discr;
-  dw_attr_ref at_discr_list;
-  dw_attr_ref at_discr_value;
-  dw_attr_ref at_encoding;
-  dw_attr_ref at_endianity;
-  dw_attr_ref at_explicit;
-  dw_attr_ref at_is_optional;
-  dw_attr_ref at_location;
-  dw_attr_ref at_lower_bound;
-  dw_attr_ref at_mutable;
-  dw_attr_ref at_ordering;
-  dw_attr_ref at_picture_string;
-  dw_attr_ref at_prototyped;
-  dw_attr_ref at_small;
-  dw_attr_ref at_segment;
-  dw_attr_ref at_string_length;
-  dw_attr_ref at_threads_scaled;
-  dw_attr_ref at_upper_bound;
-  dw_attr_ref at_use_location;
-  dw_attr_ref at_use_UTF8;
-  dw_attr_ref at_variable_parameter;
-  dw_attr_ref at_virtuality;
-  dw_attr_ref at_visibility;
-  dw_attr_ref at_vtable_elem_location;
+  dw_attr_node *at_name;
+  dw_attr_node *at_type;
+  dw_attr_node *at_friend;
+  dw_attr_node *at_accessibility;
+  dw_attr_node *at_address_class;
+  dw_attr_node *at_allocated;
+  dw_attr_node *at_artificial;
+  dw_attr_node *at_associated;
+  dw_attr_node *at_binary_scale;
+  dw_attr_node *at_bit_offset;
+  dw_attr_node *at_bit_size;
+  dw_attr_node *at_bit_stride;
+  dw_attr_node *at_byte_size;
+  dw_attr_node *at_byte_stride;
+  dw_attr_node *at_const_value;
+  dw_attr_node *at_containing_type;
+  dw_attr_node *at_count;
+  dw_attr_node *at_data_location;
+  dw_attr_node *at_data_member_location;
+  dw_attr_node *at_decimal_scale;
+  dw_attr_node *at_decimal_sign;
+  dw_attr_node *at_default_value;
+  dw_attr_node *at_digit_count;
+  dw_attr_node *at_discr;
+  dw_attr_node *at_discr_list;
+  dw_attr_node *at_discr_value;
+  dw_attr_node *at_encoding;
+  dw_attr_node *at_endianity;
+  dw_attr_node *at_explicit;
+  dw_attr_node *at_is_optional;
+  dw_attr_node *at_location;
+  dw_attr_node *at_lower_bound;
+  dw_attr_node *at_mutable;
+  dw_attr_node *at_ordering;
+  dw_attr_node *at_picture_string;
+  dw_attr_node *at_prototyped;
+  dw_attr_node *at_small;
+  dw_attr_node *at_segment;
+  dw_attr_node *at_string_length;
+  dw_attr_node *at_threads_scaled;
+  dw_attr_node *at_upper_bound;
+  dw_attr_node *at_use_location;
+  dw_attr_node *at_use_UTF8;
+  dw_attr_node *at_variable_parameter;
+  dw_attr_node *at_virtuality;
+  dw_attr_node *at_visibility;
+  dw_attr_node *at_vtable_elem_location;
 };
 
 /* Collect the attributes that we will want to use for the checksum.  */
@@ -6125,7 +6252,7 @@ struct checksum_attributes
 static void
 collect_checksum_attributes (struct checksum_attributes *attrs, dw_die_ref die)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -6349,7 +6476,7 @@ die_checksum_ordered (dw_die_ref die, struct md5_ctx *ctx, int *mark)
   /* Checksum the child DIEs.  */
   c = die->die_child;
   if (c) do {
-    dw_attr_ref name_attr;
+    dw_attr_node *name_attr;
 
     c = c->die_sib;
     name_attr = get_AT (c, DW_AT_name);
@@ -6552,7 +6679,7 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
 /* Do the attributes look the same?  */
 
 static int
-same_attr_p (dw_attr_ref at1, dw_attr_ref at2, int *mark)
+same_attr_p (dw_attr_node *at1, dw_attr_node *at2, int *mark)
 {
   if (at1->dw_attr != at2->dw_attr)
     return 0;
@@ -6571,7 +6698,7 @@ static int
 same_die_p (dw_die_ref die1, dw_die_ref die2, int *mark)
 {
   dw_die_ref c1, c2;
-  dw_attr_ref a1;
+  dw_attr_node *a1;
   unsigned ix;
 
   /* To avoid infinite recursion.  */
@@ -6855,9 +6982,8 @@ struct cu_hash_table_entry
 
 /* Helpers to manipulate hash table of CUs.  */
 
-struct cu_hash_table_entry_hasher
+struct cu_hash_table_entry_hasher : pointer_hash <cu_hash_table_entry>
 {
-  typedef cu_hash_table_entry *value_type;
   typedef die_struct *compare_type;
   static inline hashval_t hash (const cu_hash_table_entry *);
   static inline bool equal (const cu_hash_table_entry *, const die_struct *);
@@ -7012,7 +7138,7 @@ break_out_includes (dw_die_ref die)
 static int
 is_declaration_die (dw_die_ref die)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -7095,7 +7221,7 @@ static dw_die_ref
 clone_die (dw_die_ref die)
 {
   dw_die_ref clone;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   clone = ggc_cleared_alloc<die_node> ();
@@ -7127,7 +7253,7 @@ clone_as_declaration (dw_die_ref die)
 {
   dw_die_ref clone;
   dw_die_ref decl;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   /* If the DIE is already a declaration, just clone it.  */
@@ -7192,9 +7318,8 @@ struct decl_table_entry
 
 /* Hashtable helpers.  */
 
-struct decl_table_entry_hasher : typed_free_remove <decl_table_entry>
+struct decl_table_entry_hasher : free_ptr_hash <decl_table_entry>
 {
-  typedef decl_table_entry *value_type;
   typedef die_struct *compare_type;
   static inline hashval_t hash (const decl_table_entry *);
   static inline bool equal (const decl_table_entry *, const die_struct *);
@@ -7288,7 +7413,7 @@ copy_declaration_context (dw_die_ref unit, dw_die_ref die)
     {
       unsigned ix;
       dw_die_ref c;
-      dw_attr_ref a;
+      dw_attr_node *a;
 
       /* The original DIE will be changed to a declaration, and must
          be moved to be a child of the original declaration DIE.  */
@@ -7495,7 +7620,7 @@ break_out_comdat_types (dw_die_ref die)
     if (should_move_die_to_comdat (c))
       {
         dw_die_ref replacement;
-       comdat_type_node_ref type_node;
+       comdat_type_node *type_node;
 
         /* Break out nested types into their own type units.  */
         break_out_comdat_types (c);
@@ -7580,7 +7705,7 @@ static void
 copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type *decl_table)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -7705,7 +7830,7 @@ static void
 output_location_lists (dw_die_ref die)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -7734,10 +7859,8 @@ struct external_ref
 
 /* Hashtable helpers.  */
 
-struct external_ref_hasher : typed_free_remove <external_ref>
+struct external_ref_hasher : free_ptr_hash <external_ref>
 {
-  typedef external_ref *value_type;
-  typedef external_ref *compare_type;
   static inline hashval_t hash (const external_ref *);
   static inline bool equal (const external_ref *, const external_ref *);
 };
@@ -7757,7 +7880,7 @@ external_ref_hasher::hash (const external_ref *r)
     {
       /* We have a type signature; use a subset of the bits as the hash.
         The 8-byte signature is at least as large as hashval_t.  */
-      comdat_type_node_ref type_node = die->die_id.die_type_node;
+      comdat_type_node *type_node = die->die_id.die_type_node;
       memcpy (&h, type_node->signature, sizeof (h));
     }
   return h;
@@ -7799,7 +7922,7 @@ static void
 optimize_external_refs_1 (dw_die_ref die, external_ref_hash_type *map)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
   struct external_ref *ref_p;
 
@@ -7887,7 +8010,7 @@ build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
   unsigned long abbrev_id;
   unsigned int n_alloc;
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   /* Scan the DIE references, and replace any that refer to
@@ -7911,7 +8034,7 @@ build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
   for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
     {
       dw_die_ref abbrev = abbrev_die_table[abbrev_id];
-      dw_attr_ref die_a, abbrev_a;
+      dw_attr_node *die_a, *abbrev_a;
       unsigned ix;
       bool ok = true;
 
@@ -7983,7 +8106,7 @@ static unsigned long
 size_of_die (dw_die_ref die)
 {
   unsigned long size = 0;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
   enum dwarf_form form;
 
@@ -8222,7 +8345,7 @@ static void
 unmark_all_dies (dw_die_ref die)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   if (!die->die_mark)
@@ -8276,7 +8399,7 @@ size_of_pubnames (vec<pubname_entry, va_gc> *names)
 {
   unsigned long size;
   unsigned i;
-  pubname_ref p;
+  pubname_entry *p;
   int space_for_flags = (debug_generate_pub_sections == 2) ? 1 : 0;
 
   size = DWARF_PUBNAMES_HEADER_SIZE;
@@ -8326,7 +8449,7 @@ size_of_aranges (void)
 /* Select the encoding of an attribute value.  */
 
 static enum dwarf_form
-value_format (dw_attr_ref a)
+value_format (dw_attr_node *a)
 {
   switch (AT_class (a))
     {
@@ -8517,7 +8640,7 @@ value_format (dw_attr_ref a)
 /* Output the encoding of an attribute value.  */
 
 static void
-output_value_format (dw_attr_ref a)
+output_value_format (dw_attr_node *a)
 {
   enum dwarf_form form = value_format (a);
 
@@ -8530,7 +8653,7 @@ static void
 output_die_abbrevs (unsigned long abbrev_id, dw_die_ref abbrev)
 {
   unsigned ix;
-  dw_attr_ref a_attr;
+  dw_attr_node *a_attr;
 
   dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)");
   dw2_asm_output_data_uleb128 (abbrev->die_tag, "(TAG: %s)",
@@ -8705,7 +8828,7 @@ output_loc_list (dw_loc_list_ref list_head)
    indirect reference.  */
 
 static void
-output_range_list_offset (dw_attr_ref a)
+output_range_list_offset (dw_attr_node *a)
 {
   const char *name = dwarf_attr_name (a->dw_attr);
 
@@ -8725,7 +8848,7 @@ output_range_list_offset (dw_attr_ref a)
 /* Output the offset into the debug_loc section.  */
 
 static void
-output_loc_list_offset (dw_attr_ref a)
+output_loc_list_offset (dw_attr_node *a)
 {
   char *sym = AT_loc_list (a)->ll_symbol;
 
@@ -8741,7 +8864,7 @@ output_loc_list_offset (dw_attr_ref a)
 /* Output an attribute's index or value appropriately.  */
 
 static void
-output_attr_index_or_value (dw_attr_ref a)
+output_attr_index_or_value (dw_attr_node *a)
 {
   const char *name = dwarf_attr_name (a->dw_attr);
 
@@ -8784,7 +8907,7 @@ output_signature (const char *sig, const char *name)
 static void
 output_die (dw_die_ref die)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   dw_die_ref c;
   unsigned long size;
   unsigned ix;
@@ -8890,14 +9013,14 @@ output_die (dw_die_ref die)
                {
                  dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
                                       "%s", name);
-                 name = NULL;
+                 name = "";
                }
            else
              for (i = 0; i < len; ++i)
                {
                  dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
                                       "%s", name);
-                 name = NULL;
+                 name = "";
                }
          }
          break;
@@ -8951,7 +9074,7 @@ output_die (dw_die_ref die)
            {
              if (AT_ref (a)->comdat_type_p)
                {
-                 comdat_type_node_ref type_node =
+                 comdat_type_node *type_node =
                    AT_ref (a)->die_id.die_type_node;
 
                  gcc_assert (type_node);
@@ -9079,12 +9202,16 @@ output_compilation_unit_header (void)
      DWARFv5 draft DIE tags in DWARFv4 format.  */
   int ver = dwarf_version < 5 ? dwarf_version : 4;
 
-  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");
+  if (!XCOFF_DEBUGGING_INFO)
+    {
+      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, ver, "DWARF version number");
   dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label,
                         debug_abbrev_section,
@@ -9512,12 +9639,16 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
 {
   unsigned i;
   unsigned long pubnames_length = size_of_pubnames (names);
-  pubname_ref pub;
+  pubname_entry *pub;
 
-  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, "Pub Info Length");
+  if (!XCOFF_DEBUGGING_INFO)
+    {
+      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,
+                          "Pub Info Length");
+    }
 
   /* Version number for pubnames/pubtypes is independent of dwarf version.  */
   dw2_asm_output_data (2, 2, "DWARF Version");
@@ -9549,7 +9680,7 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
             the skeleton DIE (if there is one).  */
          if (pub->die->comdat_type_p && names == pubtype_table)
            {
-             comdat_type_node_ref type_node = pub->die->die_id.die_type_node;
+             comdat_type_node *type_node = pub->die->die_id.die_type_node;
 
              if (type_node != NULL)
                die_offset = (type_node->skeleton_die != NULL
@@ -9587,15 +9718,20 @@ output_pubtables (void)
    text section generated for this compilation unit.  */
 
 static void
-output_aranges (unsigned long aranges_length)
+output_aranges (void)
 {
   unsigned i;
+  unsigned long aranges_length = size_of_aranges ();
+  
+  if (!XCOFF_DEBUGGING_INFO)
+    {
+      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");
+    }
 
-  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");
   /* Version number for aranges is still 2, even up to DWARF5.  */
   dw2_asm_output_data (2, 2, "DWARF Version");
   if (dwarf_split_debug_info)
@@ -9681,10 +9817,10 @@ add_ranges_num (int num)
   if (in_use == ranges_table_allocated)
     {
       ranges_table_allocated += RANGES_TABLE_INCREMENT;
-      ranges_table = GGC_RESIZEVEC (struct dw_ranges_struct, ranges_table,
+      ranges_table = GGC_RESIZEVEC (dw_ranges, ranges_table,
                                    ranges_table_allocated);
       memset (ranges_table + ranges_table_in_use, 0,
-             RANGES_TABLE_INCREMENT * sizeof (struct dw_ranges_struct));
+             RANGES_TABLE_INCREMENT * sizeof (dw_ranges));
     }
 
   ranges_table[in_use].num = num;
@@ -9717,12 +9853,10 @@ add_ranges_by_labels (dw_die_ref die, const char *begin, const char *end,
   if (in_use == ranges_by_label_allocated)
     {
       ranges_by_label_allocated += RANGES_TABLE_INCREMENT;
-      ranges_by_label = GGC_RESIZEVEC (struct dw_ranges_by_label_struct,
-                                      ranges_by_label,
+      ranges_by_label = GGC_RESIZEVEC (dw_ranges_by_label, ranges_by_label,
                                       ranges_by_label_allocated);
       memset (ranges_by_label + ranges_by_label_in_use, 0,
-             RANGES_TABLE_INCREMENT
-             * sizeof (struct dw_ranges_by_label_struct));
+             RANGES_TABLE_INCREMENT * sizeof (dw_ranges_by_label));
     }
 
   ranges_by_label[in_use].begin = begin;
@@ -10281,11 +10415,15 @@ output_line_info (bool prologue_only)
   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");
+  if (!XCOFF_DEBUGGING_INFO)
+    {
+      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);
 
   dw2_asm_output_data (2, ver, "DWARF Version");
@@ -10761,29 +10899,39 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
            mod_type_die = d;
          }
     }
-  else if (code == POINTER_TYPE)
-    {
-      mod_type_die = new_die (DW_TAG_pointer_type, mod_scope, type);
-      add_AT_unsigned (mod_type_die, DW_AT_byte_size,
-                      simple_type_size_in_bits (type) / BITS_PER_UNIT);
-      item_type = TREE_TYPE (type);
-      if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type)))
-       add_AT_unsigned (mod_type_die, DW_AT_address_class,
-                        TYPE_ADDR_SPACE (item_type));
-    }
-  else if (code == REFERENCE_TYPE)
+  else if (code == POINTER_TYPE || code == REFERENCE_TYPE)
     {
-      if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
-       mod_type_die = new_die (DW_TAG_rvalue_reference_type, mod_scope,
-                               type);
-      else
-       mod_type_die = new_die (DW_TAG_reference_type, mod_scope, type);
+      dwarf_tag tag = DW_TAG_pointer_type;
+      if (code == REFERENCE_TYPE)
+       {
+         if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
+           tag = DW_TAG_rvalue_reference_type;
+         else
+           tag = DW_TAG_reference_type;
+       }
+      mod_type_die = new_die (tag, mod_scope, type);
+
       add_AT_unsigned (mod_type_die, DW_AT_byte_size,
                       simple_type_size_in_bits (type) / BITS_PER_UNIT);
       item_type = TREE_TYPE (type);
-      if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type)))
-       add_AT_unsigned (mod_type_die, DW_AT_address_class,
-                        TYPE_ADDR_SPACE (item_type));
+
+      addr_space_t as = TYPE_ADDR_SPACE (item_type);
+      if (!ADDR_SPACE_GENERIC_P (as))
+       {
+         int action = targetm.addr_space.debug (as);
+         if (action >= 0)
+           {
+             /* Positive values indicate an address_class.  */
+             add_AT_unsigned (mod_type_die, DW_AT_address_class, action);
+           }
+         else
+           {
+             /* Negative values indicate an (inverted) segment base reg.  */
+             dw_loc_descr_ref d
+               = one_reg_loc_descriptor (~action, VAR_INIT_STATUS_INITIALIZED);
+             add_AT_loc (mod_type_die, DW_AT_segment, d);
+           }
+       }
     }
   else if (code == INTEGER_TYPE
           && TREE_TYPE (type) != NULL_TREE
@@ -11612,14 +11760,14 @@ const_ok_for_output_1 (rtx rtl)
     {
       /* If delegitimize_address couldn't do anything with the UNSPEC, assume
         we can't express it in the debug info.  */
-#ifdef ENABLE_CHECKING
       /* Don't complain about TLS UNSPECs, those are just too hard to
         delegitimize.  Note this could be a non-decl SYMBOL_REF such as
         one in a constant pool entry, so testing SYMBOL_REF_TLS_MODEL
         rather than DECL_THREAD_LOCAL_P is not just an optimization.  */
-      if (XVECLEN (rtl, 0) == 0
-         || GET_CODE (XVECEXP (rtl, 0, 0)) != SYMBOL_REF
-         || SYMBOL_REF_TLS_MODEL (XVECEXP (rtl, 0, 0)) == TLS_MODEL_NONE)
+      if (flag_checking
+         && (XVECLEN (rtl, 0) == 0
+             || GET_CODE (XVECEXP (rtl, 0, 0)) != SYMBOL_REF
+             || SYMBOL_REF_TLS_MODEL (XVECEXP (rtl, 0, 0)) == TLS_MODEL_NONE))
        inform (current_function_decl
                ? DECL_SOURCE_LOCATION (current_function_decl)
                : UNKNOWN_LOCATION,
@@ -11631,7 +11779,6 @@ const_ok_for_output_1 (rtx rtl)
 #else
                "non-delegitimized UNSPEC %d found in variable location",
                XINT (rtl, 1));
-#endif
 #endif
       expansion_failed (NULL_TREE, rtl,
                        "UNSPEC hasn't been delegitimized.\n");
@@ -13419,12 +13566,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       goto symref;
 
     default:
-#ifdef ENABLE_CHECKING
-      print_rtl (stderr, rtl);
-      gcc_unreachable ();
-#else
+      if (flag_checking)
+       {
+         print_rtl (stderr, rtl);
+         gcc_unreachable ();
+       }
       break;
-#endif
     }
 
   if (mem_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
@@ -14327,12 +14474,12 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev,
   tree obj, offset;
   HOST_WIDE_INT bitsize, bitpos, bytepos;
   machine_mode mode;
-  int unsignedp, volatilep = 0;
+  int unsignedp, reversep, volatilep = 0;
   dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
 
   obj = get_inner_reference (TREE_OPERAND (loc, 0),
                             &bitsize, &bitpos, &offset, &mode,
-                            &unsignedp, &volatilep, false);
+                            &unsignedp, &reversep, &volatilep, false);
   STRIP_NOPS (obj);
   if (bitpos % BITS_PER_UNIT)
     {
@@ -14661,10 +14808,10 @@ loc_list_from_tree (tree loc, int want_address,
        tree obj, offset;
        HOST_WIDE_INT bitsize, bitpos, bytepos;
        machine_mode mode;
-       int unsignedp, volatilep = 0;
+       int unsignedp, reversep, volatilep = 0;
 
        obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
-                                  &unsignedp, &volatilep, false);
+                                  &unsignedp, &reversep, &volatilep, false);
 
        gcc_assert (obj != loc);
 
@@ -14947,15 +15094,14 @@ loc_list_from_tree (tree loc, int want_address,
          return 0;
        }
 
-#ifdef ENABLE_CHECKING
       /* Otherwise this is a generic code; we should just lists all of
         these explicitly.  We forgot one.  */
-      gcc_unreachable ();
-#else
+      if (flag_checking)
+       gcc_unreachable ();
+
       /* In a release build, we want to degrade gracefully: better to
         generate incomplete debugging information than to crash.  */
       return NULL;
-#endif
     }
 
   if (!ret && !list_ret)
@@ -15424,12 +15570,10 @@ insert_wide_int (const wide_int &val, unsigned char *dest, int elt_size)
 static void
 insert_float (const_rtx rtl, unsigned char *array)
 {
-  REAL_VALUE_TYPE rv;
   long val[4];
   int i;
 
-  REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
-  real_to_target (val, &rv, GET_MODE (rtl));
+  real_to_target (val, CONST_DOUBLE_REAL_VALUE (rtl), GET_MODE (rtl));
 
   /* real_to_target puts 32-bit pieces in each long.  Pack them.  */
   for (i = 0; i < GET_MODE_SIZE (GET_MODE (rtl)) / 4; i++)
@@ -15462,8 +15606,13 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
       return true;
 
     case CONST_WIDE_INT:
-      add_AT_wide (die, DW_AT_const_value,
-                  std::make_pair (rtl, GET_MODE (rtl)));
+      {
+       wide_int w1 = std::make_pair (rtl, MAX_MODE_INT);
+       unsigned int prec = MIN (wi::min_precision (w1, UNSIGNED),
+                                (unsigned int)CONST_WIDE_INT_NUNITS (rtl) * HOST_BITS_PER_WIDE_INT);
+       wide_int w = wi::zext (w1, prec);
+       add_AT_wide (die, DW_AT_const_value, w);
+      }
       return true;
 
     case CONST_DOUBLE:
@@ -15964,7 +16113,7 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
   machine_mode mode;
   HOST_WIDE_INT bitsize, bitpos;
   tree offset;
-  int unsignedp, volatilep = 0;
+  int unsignedp, reversep, volatilep = 0;
 
   /* If the decl isn't a VAR_DECL, or if it isn't static, or if
      it does not have a value (the offset into the common area), or if it
@@ -15980,8 +16129,8 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
   if (TREE_CODE (val_expr) != COMPONENT_REF)
     return NULL_TREE;
 
-  cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset,
-                             &mode, &unsignedp, &volatilep, true);
+  cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset, &mode,
+                             &unsignedp, &reversep, &volatilep, true);
 
   if (cvar == NULL_TREE
       || TREE_CODE (cvar) != VAR_DECL
@@ -16019,17 +16168,23 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
    since we will need to refer to them each time the function is inlined.  */
 
 static bool
-add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
-                                      enum dwarf_attribute attr)
+add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p)
 {
   rtx rtl;
   dw_loc_list_ref list;
   var_loc_list *loc_list;
   cached_dw_loc_list *cache;
 
+  if (early_dwarf)
+    return false;
+
   if (TREE_CODE (decl) == ERROR_MARK)
     return false;
 
+  if (get_AT (die, DW_AT_location)
+      || get_AT (die, DW_AT_const_value))
+    return true;
+
   gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
              || TREE_CODE (decl) == RESULT_DECL);
 
@@ -16093,7 +16248,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
     }
   if (list)
     {
-      add_AT_location_description (die, attr, list);
+      add_AT_location_description (die, DW_AT_location, list);
       return true;
     }
   /* None of that worked, so it must not really have a location;
@@ -16101,17 +16256,6 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
   return tree_add_const_value_attribute_for_decl (die, decl);
 }
 
-/* Add VARIABLE and DIE into deferred locations list.  */
-
-static void
-defer_location (tree variable, dw_die_ref die)
-{
-  deferred_locations entry;
-  entry.variable = variable;
-  entry.die = die;
-  vec_safe_push (deferred_locations_list, entry);
-}
-
 /* Helper function for tree_add_const_value_attribute.  Natively encode
    initializer INIT into an array.  Return true if successful.  */
 
@@ -16793,14 +16937,17 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
 /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
    possibly nested array subscripts in a flat sequence if COLLAPSE_P is true.
    Note that the block of subscript information for an array type also
-   includes information about the element type of the given array type.  */
+   includes information about the element type of the given array type.
+
+   This function reuses previously set type and bound information if
+   available.  */
 
 static void
 add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
 {
   unsigned dimension_number;
   tree lower, upper;
-  dw_die_ref subrange_die;
+  dw_die_ref child = type_die->die_child;
 
   for (dimension_number = 0;
        TREE_CODE (type) == ARRAY_TYPE && (dimension_number == 0 || collapse_p);
@@ -16814,7 +16961,37 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
       /* Arrays come in three flavors: Unspecified bounds, fixed bounds,
         and (in GNU C only) variable bounds.  Handle all three forms
         here.  */
-      subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
+
+      /* Find and reuse a previously generated DW_TAG_subrange_type if
+        available.
+
+         For multi-dimensional arrays, as we iterate through the
+         various dimensions in the enclosing for loop above, we also
+         iterate through the DIE children and pick at each
+         DW_TAG_subrange_type previously generated (if available).
+         Each child DW_TAG_subrange_type DIE describes the range of
+         the current dimension.  At this point we should have as many
+         DW_TAG_subrange_type's as we have dimensions in the
+         array.  */
+      dw_die_ref subrange_die = NULL;
+      if (child)
+       while (1)
+         {
+           child = child->die_sib;
+           if (child->die_tag == DW_TAG_subrange_type)
+             subrange_die = child;
+           if (child == type_die->die_child)
+             {
+               /* If we wrapped around, stop looking next time.  */
+               child = NULL;
+               break;
+             }
+           if (child->die_tag == DW_TAG_subrange_type)
+             break;
+         }
+      if (!subrange_die)
+       subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
+
       if (domain)
        {
          /* We have an array type with specified bounds.  */
@@ -16822,7 +16999,8 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
          upper = TYPE_MAX_VALUE (domain);
 
          /* Define the index type.  */
-         if (TREE_TYPE (domain))
+         if (TREE_TYPE (domain)
+             && !get_AT (subrange_die, DW_AT_type))
            {
              /* ??? This is probably an Ada unnamed subrange type.  Ignore the
                 TREE_TYPE field.  We can't emit debug info for this
@@ -16844,8 +17022,9 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
             to produce useful results, go ahead and output the lower
             bound solo, and hope the debugger can cope.  */
 
-         add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
-         if (upper)
+         if (!get_AT (subrange_die, DW_AT_lower_bound))
+           add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
+         if (upper && !get_AT (subrange_die, DW_AT_upper_bound))
            add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL);
        }
 
@@ -17472,6 +17651,25 @@ decl_start_label (tree decl)
 }
 #endif
 \f
+/* For variable-length arrays that have been previously generated, but
+   may be incomplete due to missing subscript info, fill the subscript
+   info.  Return TRUE if this is one of those cases.  */
+static bool
+fill_variable_array_bounds (tree type)
+{
+  if (TREE_ASM_WRITTEN (type)
+      && TREE_CODE (type) == ARRAY_TYPE
+      && variably_modified_type_p (type, NULL))
+    {
+      dw_die_ref array_die = lookup_type_die (type);
+      if (!array_die)
+       return false;
+      add_subscript_info (array_die, type, !is_ada ());
+      return true;
+    }
+  return false;
+}
+
 /* These routines generate the internal representation of the DIE's for
    the compilation unit.  Debugging information is collected by walking
    the declaration trees passed in from dwarf2out_decl().  */
@@ -17479,7 +17677,6 @@ decl_start_label (tree decl)
 static void
 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;
 
   /* GNU compilers represent multidimensional array types as sequences of one
@@ -17493,6 +17690,11 @@ gen_array_type_die (tree type, dw_die_ref context_die)
      flexibilty wrt arrays of variable size.  */
 
   bool collapse_nested_arrays = !is_ada ();
+
+  if (fill_variable_array_bounds (type))
+    return;
+
+  dw_die_ref scope_die = scope_die_for (type, context_die);
   tree element_type;
 
   /* Emit DW_TAG_string_type for Fortran character types (with kind 1 only, as
@@ -17848,8 +18050,67 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
 {
   tree node_or_origin = node ? node : origin;
   tree ultimate_origin;
-  dw_die_ref parm_die
-    = new_die (DW_TAG_formal_parameter, context_die, node);
+  dw_die_ref parm_die = NULL;
+  
+  if (TREE_CODE_CLASS (TREE_CODE (node_or_origin)) == tcc_declaration)
+    {
+      parm_die = lookup_decl_die (node);
+
+      /* If the contexts differ, we may not be talking about the same
+        thing.  */
+      if (parm_die && parm_die->die_parent != context_die)
+       {
+         if (!DECL_ABSTRACT_P (node))
+           {
+             /* This can happen when creating an inlined instance, in
+                which case we need to create a new DIE that will get
+                annotated with DW_AT_abstract_origin.  */
+             parm_die = NULL;
+           }
+         else
+           {
+             /* FIXME: Reuse DIE even with a differing context.
+
+                This can happen when calling
+                dwarf2out_abstract_function to build debug info for
+                the abstract instance of a function for which we have
+                already generated a DIE in
+                dwarf2out_early_global_decl.
+
+                Once we remove dwarf2out_abstract_function, we should
+                have a call to gcc_unreachable here.  */
+           }
+       }
+
+      if (parm_die && parm_die->die_parent == NULL)
+       {
+         /* Check that parm_die already has the right attributes that
+            we would have added below.  If any attributes are
+            missing, fall through to add them.  */
+         if (! DECL_ABSTRACT_P (node_or_origin)
+             && !get_AT (parm_die, DW_AT_location)
+             && !get_AT (parm_die, DW_AT_const_value))
+           /* We are missing  location info, and are about to add it.  */
+           ;
+         else
+           {
+             add_child_die (context_die, parm_die);
+             return parm_die;
+           }
+       }
+    }
+
+  /* If we have a previously generated DIE, use it, unless this is an
+     concrete instance (origin != NULL), in which case we need a new
+     DIE with a corresponding DW_AT_abstract_origin.  */
+  bool reusing_die;
+  if (parm_die && origin == NULL)
+    reusing_die = true;
+  else
+    {
+      parm_die = new_die (DW_TAG_formal_parameter, context_die, node);
+      reusing_die = false;
+    }
 
   switch (TREE_CODE_CLASS (TREE_CODE (node_or_origin)))
     {
@@ -17857,6 +18118,10 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
       ultimate_origin = decl_ultimate_origin (node_or_origin);
       if (node || ultimate_origin)
        origin = ultimate_origin;
+
+      if (reusing_die)
+       goto add_location;
+
       if (origin != NULL)
        add_abstract_origin_attribute (parm_die, origin);
       else if (emit_name_p)
@@ -17878,12 +18143,12 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
        }
       if (origin == NULL && DECL_ARTIFICIAL (node))
        add_AT_flag (parm_die, DW_AT_artificial, 1);
-
+    add_location:
       if (node && node != origin)
         equate_decl_number_to_die (node, parm_die);
       if (! DECL_ABSTRACT_P (node_or_origin))
        add_location_or_const_value_attribute (parm_die, node_or_origin,
-                                              node == NULL, DW_AT_location);
+                                              node == NULL);
 
       break;
 
@@ -18207,7 +18472,16 @@ set_decl_abstract_flags (tree decl, vec<tree> &abstract_vec)
 }
 
 /* Generate the DWARF2 info for the "abstract" instance of a function which we
-   may later generate inlined and/or out-of-line instances of.  */
+   may later generate inlined and/or out-of-line instances of.
+
+   FIXME: In the early-dwarf world, this function, and most of the
+          DECL_ABSTRACT code should be obsoleted.  The early DIE _is_
+          the abstract instance.  All we would need to do is annotate
+          the early DIE with the appropriate DW_AT_inline in late
+          dwarf (perhaps in gen_inlined_subroutine_die).
+
+         However, we can't do this yet, because LTO streaming of DIEs
+         has not been implemented yet.  */
 
 static void
 dwarf2out_abstract_function (tree decl)
@@ -18389,34 +18663,103 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 {
   tree origin = decl_ultimate_origin (decl);
   dw_die_ref subr_die;
-  tree outer_scope;
   dw_die_ref old_die = lookup_decl_die (decl);
-  int declaration = (current_function_decl != decl
-                    || class_or_namespace_scope_p (context_die));
 
-  premark_used_types (DECL_STRUCT_FUNCTION (decl));
+  /* This function gets called multiple times for different stages of
+     the debug process.  For example, for func() in this code:
 
-  /* It is possible to have both DECL_ABSTRACT_P and DECLARATION be true if we
-     started to generate the abstract instance of an inline, decided to output
-     its containing class, and proceeded to emit the declaration of the inline
-     from the member list for the class.  If so, DECLARATION takes priority;
-     we'll get back to the abstract instance when done with the class.  */
+       namespace S
+       {
+         void func() { ... }
+       }
 
-  /* The class-scope declaration DIE must be the primary DIE.  */
-  if (origin && declaration && class_or_namespace_scope_p (context_die))
-    {
-      origin = NULL;
-      gcc_assert (!old_die);
-    }
+     ...we get called 4 times.  Twice in early debug and twice in
+     late debug:
 
-  /* Now that the C++ front end lazily declares artificial member fns, we
-     might need to retrofit the declaration into its class.  */
-  if (!declaration && !origin && !old_die
-      && DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))
-      && !class_or_namespace_scope_p (context_die)
+     Early debug
+     -----------
+
+       1. Once while generating func() within the namespace.  This is
+          the declaration.  The declaration bit below is set, as the
+          context is the namespace.
+
+         A new DIE will be generated with DW_AT_declaration set.
+
+       2. Once for func() itself.  This is the specification.  The
+          declaration bit below is clear as the context is the CU.
+
+         We will use the cached DIE from (1) to create a new DIE with
+         DW_AT_specification pointing to the declaration in (1).
+
+     Late debug via rest_of_handle_final()
+     -------------------------------------
+
+       3. Once generating func() within the namespace.  This is also the
+          declaration, as in (1), but this time we will early exit below
+          as we have a cached DIE and a declaration needs no additional
+          annotations (no locations), as the source declaration line
+          info is enough.
+
+       4. Once for func() itself.  As in (2), this is the specification,
+          but this time we will re-use the cached DIE, and just annotate
+          it with the location information that should now be available.
+
+     For something without namespaces, but with abstract instances, we
+     are also called a multiple times:
+
+        class Base
+       {
+       public:
+         Base ();        // constructor declaration (1)
+       };
+
+       Base::Base () { } // constructor specification (2)
+
+    Early debug
+    -----------
+
+       1. Once for the Base() constructor by virtue of it being a
+          member of the Base class.  This is done via
+          rest_of_type_compilation.
+
+         This is a declaration, so a new DIE will be created with
+         DW_AT_declaration.
+
+       2. Once for the Base() constructor definition, but this time
+          while generating the abstract instance of the base
+          constructor (__base_ctor) which is being generated via early
+          debug of reachable functions.
+
+         Even though we have a cached version of the declaration (1),
+         we will create a DW_AT_specification of the declaration DIE
+         in (1).
+
+       3. Once for the __base_ctor itself, but this time, we generate
+          an DW_AT_abstract_origin version of the DW_AT_specification in
+         (2).
+
+    Late debug via rest_of_handle_final
+    -----------------------------------
+
+       4. One final time for the __base_ctor (which will have a cached
+          DIE with DW_AT_abstract_origin created in (3).  This time,
+          we will just annotate the location information now
+          available.
+  */
+  int declaration = (current_function_decl != decl
+                    || class_or_namespace_scope_p (context_die));
+
+  premark_used_types (DECL_STRUCT_FUNCTION (decl));
+
+  /* Now that the C++ front end lazily declares artificial member fns, we
+     might need to retrofit the declaration into its class.  */
+  if (!declaration && !origin && !old_die
+      && DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))
+      && !class_or_namespace_scope_p (context_die)
       && debug_info_level > DINFO_LEVEL_TERSE)
     old_die = force_decl_die (decl);
 
+  /* An inlined instance, tag a new DIE with DW_AT_abstract_origin.  */
   if (origin != NULL)
     {
       gcc_assert (!declaration || local_scope_p (context_die));
@@ -18426,19 +18769,32 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (old_die && old_die->die_parent == NULL)
        add_child_die (context_die, old_die);
 
-      subr_die = new_die (DW_TAG_subprogram, context_die, decl);
-      add_abstract_origin_attribute (subr_die, origin);
-      /*  This is where the actual code for a cloned function is.
-         Let's emit linkage name attribute for it.  This helps
-         debuggers to e.g, set breakpoints into
-         constructors/destructors when the user asks "break
-         K::K".  */
-      add_linkage_name (subr_die, decl);
+      if (old_die && get_AT_ref (old_die, DW_AT_abstract_origin))
+       {
+         /* If we have a DW_AT_abstract_origin we have a working
+            cached version.  */
+         subr_die = old_die;
+       }
+      else
+       {
+         subr_die = new_die (DW_TAG_subprogram, context_die, decl);
+         add_abstract_origin_attribute (subr_die, origin);
+         /*  This is where the actual code for a cloned function is.
+             Let's emit linkage name attribute for it.  This helps
+             debuggers to e.g, set breakpoints into
+             constructors/destructors when the user asks "break
+             K::K".  */
+         add_linkage_name (subr_die, decl);
+       }
     }
+  /* A cached copy, possibly from early dwarf generation.  Reuse as
+     much as possible.  */
   else if (old_die)
     {
-      expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
-      struct dwarf_file_data * file_index = lookup_filename (s.file);
+      /* A declaration that has been previously dumped needs no
+        additional information.  */
+      if (declaration)
+       return;
 
       if (!get_AT_flag (old_die, DW_AT_declaration)
          /* We can have a normal definition following an inline one in the
@@ -18448,7 +18804,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        {
          /* Detect and ignore this case, where we are trying to output
             something we have already output.  */
-         return;
+         if (get_AT (old_die, DW_AT_low_pc)
+             || get_AT (old_die, DW_AT_ranges))
+           return;
+
+         /* If we have no location information, this must be a
+            partially generated DIE from early dwarf generation.
+            Fall through and generate it.  */
        }
 
       /* If the definition comes from the same place as the declaration,
@@ -18458,23 +18820,44 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
         instances of inlines, since the spec requires the out-of-line copy
         to have the same parent.  For local class methods, this doesn't
         apply; we just use the old DIE.  */
-      if ((is_cu_die (old_die->die_parent) || context_die == NULL)
-         && (DECL_ARTIFICIAL (decl)
-             || (get_AT_file (old_die, DW_AT_decl_file) == file_index
-                 && (get_AT_unsigned (old_die, DW_AT_decl_line)
-                     == (unsigned) s.line))))
+      expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
+      struct dwarf_file_data * file_index = lookup_filename (s.file);
+      if ((is_cu_die (old_die->die_parent)
+          /* This condition fixes the inconsistency/ICE with the
+             following Fortran test (or some derivative thereof) while
+             building libgfortran:
+
+                module some_m
+                contains
+                   logical function funky (FLAG)
+                     funky = .true.
+                  end function
+                end module
+          */
+          || (old_die->die_parent
+              && old_die->die_parent->die_tag == DW_TAG_module)
+          || context_die == NULL)
+          && (DECL_ARTIFICIAL (decl)
+              || (get_AT_file (old_die, DW_AT_decl_file) == file_index
+                  && (get_AT_unsigned (old_die, DW_AT_decl_line)
+                      == (unsigned) s.line))))
        {
          subr_die = old_die;
 
-         /* Clear out the declaration attribute and the formal parameters.
-            Do not remove all children, because it is possible that this
-            declaration die was forced using force_decl_die(). In such
-            cases die that forced declaration die (e.g. TAG_imported_module)
-            is one of the children that we do not want to remove.  */
-         remove_AT (subr_die, DW_AT_declaration);
-         remove_AT (subr_die, DW_AT_object_pointer);
-         remove_child_TAG (subr_die, DW_TAG_formal_parameter);
+         /* Clear out the declaration attribute, but leave the
+            parameters so they can be augmented with location
+            information later.  Unless this was a declaration, in
+            which case, wipe out the nameless parameters and recreate
+            them further down.  */
+         if (remove_AT (subr_die, DW_AT_declaration))
+           {
+
+             remove_AT (subr_die, DW_AT_object_pointer);
+             remove_child_TAG (subr_die, DW_TAG_formal_parameter);
+           }
        }
+      /* Make a specification pointing to the previously built
+        declaration.  */
       else
        {
          subr_die = new_die (DW_TAG_subprogram, context_die, decl);
@@ -18496,6 +18879,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
            }
        }
     }
+  /* Create a fresh DIE for anything else.  */
   else
     {
       subr_die = new_die (DW_TAG_subprogram, context_die, decl);
@@ -18522,6 +18906,11 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       add_accessibility_attribute (subr_die, decl);
     }
 
+  /* Unless we have an existing non-declaration DIE, equate the new
+     DIE.  */
+  if (!old_die || is_declaration_die (old_die))
+    equate_decl_number_to_die (decl, subr_die);
+
   if (declaration)
     {
       if (!old_die || !get_AT (old_die, DW_AT_inline))
@@ -18539,17 +18928,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
          if (lang_hooks.decls.function_decl_deleted_p (decl)
              && (! dwarf_strict))
            add_AT_flag (subr_die, DW_AT_GNU_deleted, 1);
-
-         /* The first time we see a member function, it is in the context of
-            the class to which it belongs.  We make sure of this by emitting
-            the class first.  The next time is the definition, which is
-            handled above.  The two may come from the same source text.
-
-            Note that force_decl_die() forces function declaration die. It is
-            later reused to represent definition.  */
-         equate_decl_number_to_die (decl, subr_die);
        }
     }
+  /* Tag abstract instances with DW_AT_inline.  */
   else if (DECL_ABSTRACT_P (decl))
     {
       if (DECL_DECLARED_INLINE_P (decl))
@@ -18570,18 +18951,15 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (DECL_DECLARED_INLINE_P (decl)
          && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
        add_AT_flag (subr_die, DW_AT_artificial, 1);
-
-      equate_decl_number_to_die (decl, subr_die);
     }
-  else if (!DECL_EXTERNAL (decl))
+  /* For non DECL_EXTERNALs, if range information is available, fill
+     the DIE with it.  */
+  else if (!DECL_EXTERNAL (decl) && !early_dwarf)
     {
       HOST_WIDE_INT cfa_fb_offset;
-      struct function *fun = DECL_STRUCT_FUNCTION (decl);
 
-      if (!old_die || !get_AT (old_die, DW_AT_inline))
-       equate_decl_number_to_die (decl, subr_die);
+      struct function *fun = DECL_STRUCT_FUNCTION (decl);
 
-      gcc_checking_assert (fun);
       if (!flag_reorder_blocks_and_partition)
        {
          dw_fde_ref fde = fun->fde;
@@ -18735,12 +19113,27 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
 
       if (fun->static_chain_decl)
-       add_AT_location_description (subr_die, DW_AT_static_link,
-                loc_list_from_tree (fun->static_chain_decl, 2, NULL));
+       {
+         /* DWARF requires here a location expression that computes the
+            address of the enclosing subprogram's frame base.  The machinery
+            in tree-nested.c is supposed to store this specific address in the
+            last field of the FRAME record.  */
+         const tree frame_type
+           = TREE_TYPE (TREE_TYPE (fun->static_chain_decl));
+         const tree fb_decl = tree_last (TYPE_FIELDS (frame_type));
+
+         tree fb_expr
+           = build1 (INDIRECT_REF, frame_type, fun->static_chain_decl);
+         fb_expr = build3 (COMPONENT_REF, TREE_TYPE (fb_decl),
+                           fb_expr, fb_decl, NULL_TREE);
+
+         add_AT_location_description (subr_die, DW_AT_static_link,
+                                      loc_list_from_tree (fb_expr, 0, NULL));
+       }
     }
 
   /* Generate child dies for template paramaters.  */
-  if (debug_info_level > DINFO_LEVEL_TERSE)
+  if (early_dwarf && debug_info_level > DINFO_LEVEL_TERSE)
     gen_generic_params_dies (decl);
 
   /* Now output descriptions of the arguments for this function. This gets
@@ -18764,7 +19157,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
     {
       /* Generate DIEs to represent all known formal parameters.  */
       tree parm = DECL_ARGUMENTS (decl);
-      tree generic_decl = lang_hooks.decls.get_generic_function_decl (decl);
+      tree generic_decl = early_dwarf
+       ? lang_hooks.decls.get_generic_function_decl (decl) : NULL;
       tree generic_decl_parm = generic_decl
                                ? DECL_ARGUMENTS (generic_decl)
                                : NULL;
@@ -18829,11 +19223,14 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        gen_unspecified_parameters_die (decl, subr_die);
     }
 
+  if (subr_die != old_die)
+    /* Add the calling convention attribute if requested.  */
+    add_calling_convention_attribute (subr_die, decl);
+
   /* Output Dwarf info for all of the stuff within the body of the function
-     (if it has one - it may be just a declaration).  */
-  outer_scope = DECL_INITIAL (decl);
+     (if it has one - it may be just a declaration).
 
-  /* OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent
+     OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent
      a function.  This BLOCK actually represents the outermost binding contour
      for the function, i.e. the contour in which the function's formal
      parameters and labels get declared. Curiously, it appears that the front
@@ -18847,6 +19244,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
      a BLOCK node representing the function's outermost pair of curly braces,
      and any blocks used for the base and member initializers of a C++
      constructor function.  */
+  tree outer_scope = DECL_INITIAL (decl);
   if (! declaration && outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
     {
       int call_site_note_count = 0;
@@ -18856,6 +19254,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (DECL_NAME (DECL_RESULT (decl)))
        gen_decl_die (DECL_RESULT (decl), NULL, subr_die);
 
+      /* The first time through decls_for_scope we will generate the
+        DIEs for the locals.  The second time, we fill in the
+        location info.  */
       decls_for_scope (outer_scope, subr_die);
 
       if (call_arg_locations && !dwarf_strict)
@@ -18867,7 +19268,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
              rtx tloc = NULL_RTX, tlocc = NULL_RTX;
              rtx arg, next_arg;
 
-             for (arg = NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note);
+             for (arg = (ca_loc->call_arg_loc_note != NULL_RTX
+                         ? NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note)
+                         : NULL_RTX);
                   arg; arg = next_arg)
                {
                  dw_loc_descr_ref reg, val;
@@ -18890,18 +19293,23 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                    }
                  if (mode == VOIDmode || mode == BLKmode)
                    continue;
-                 if (XEXP (XEXP (arg, 0), 0) == pc_rtx)
-                   {
-                     gcc_assert (ca_loc->symbol_ref == NULL_RTX);
-                     tloc = XEXP (XEXP (arg, 0), 1);
-                     continue;
-                   }
-                 else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER
-                          && XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx)
+                 /* Get dynamic information about call target only if we
+                    have no static information: we cannot generate both
+                    DW_AT_abstract_origin and DW_AT_GNU_call_site_target
+                    attributes.  */
+                 if (ca_loc->symbol_ref == NULL_RTX)
                    {
-                     gcc_assert (ca_loc->symbol_ref == NULL_RTX);
-                     tlocc = XEXP (XEXP (arg, 0), 1);
-                     continue;
+                     if (XEXP (XEXP (arg, 0), 0) == pc_rtx)
+                       {
+                         tloc = XEXP (XEXP (arg, 0), 1);
+                         continue;
+                       }
+                     else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER
+                              && XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx)
+                       {
+                         tlocc = XEXP (XEXP (arg, 0), 1);
+                         continue;
+                       }
                    }
                  reg = NULL;
                  if (REG_P (XEXP (XEXP (arg, 0), 0)))
@@ -19007,10 +19415,6 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       call_site_count = -1;
       tail_call_site_count = -1;
     }
-
-  if (subr_die != old_die)
-    /* Add the calling convention attribute if requested.  */
-    add_calling_convention_attribute (subr_die, decl);
 }
 
 /* Returns a hash value for X (which really is a die_struct).  */
@@ -19030,6 +19434,33 @@ block_die_hasher::equal (die_struct *x, die_struct *y)
   return x->decl_id == y->decl_id && x->die_parent == y->die_parent;
 }
 
+/* Return TRUE if DECL, which may have been previously generated as
+   OLD_DIE, is a candidate for a DW_AT_specification.  DECLARATION is
+   true if decl (or its origin) is either an extern declaration or a
+   class/namespace scoped declaration.
+
+   The declare_in_namespace support causes us to get two DIEs for one
+   variable, both of which are declarations.  We want to avoid
+   considering one to be a specification, so we must test for
+   DECLARATION and DW_AT_declaration.  */
+static inline bool
+decl_will_get_specification_p (dw_die_ref old_die, tree decl, bool declaration)
+{
+  return (old_die && TREE_STATIC (decl) && !declaration
+         && get_AT_flag (old_die, DW_AT_declaration) == 1);
+}
+
+/* Return true if DECL is a local static.  */
+
+static inline bool
+local_function_static (tree decl)
+{
+  gcc_assert (TREE_CODE (decl) == VAR_DECL);
+  return TREE_STATIC (decl)
+    && DECL_CONTEXT (decl)
+    && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL;
+}
+
 /* Generate a DIE to represent a declared data object.
    Either DECL or ORIGIN must be non-null.  */
 
@@ -19042,7 +19473,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   tree ultimate_origin;
   dw_die_ref var_die;
   dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL;
-  dw_die_ref origin_die;
+  dw_die_ref origin_die = NULL;
   bool declaration = (DECL_EXTERNAL (decl_or_origin)
                      || class_or_namespace_scope_p (context_die));
   bool specialization_p = false;
@@ -19157,12 +19588,38 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
       return;
     }
 
-  /* If the compiler emitted a definition for the DECL declaration
-     and if we already emitted a DIE for it, don't emit a second
-     DIE for it again. Allow re-declarations of DECLs that are
-     inside functions, though.  */
-  if (old_die && declaration && !local_scope_p (context_die))
-    return;
+  if (old_die)
+    {
+      if (declaration)
+       {
+         /* A declaration that has been previously dumped, needs no
+            further annotations, since it doesn't need location on
+            the second pass.  */
+         return;
+       }
+      else if (decl_will_get_specification_p (old_die, decl, declaration)
+              && !get_AT (old_die, DW_AT_specification))
+       {
+         /* Fall-thru so we can make a new variable die along with a
+            DW_AT_specification.  */
+       }
+      else if (origin && old_die->die_parent != context_die)
+       {
+         /* If we will be creating an inlined instance, we need a
+            new DIE that will get annotated with
+            DW_AT_abstract_origin.  Clear things so we can get a
+            new DIE.  */
+         gcc_assert (!DECL_ABSTRACT_P (decl));
+         old_die = NULL;
+       }
+      else
+       {
+         /* If a DIE was dumped early, it still needs location info.
+            Skip to where we fill the location bits.  */
+         var_die = old_die;
+         goto gen_variable_die_location;
+       }
+    }
 
   /* For static data members, the declaration in the class is supposed
      to have DW_TAG_member tag; the specification should still be
@@ -19172,7 +19629,6 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   else
     var_die = new_die (DW_TAG_variable, context_die, decl);
 
-  origin_die = NULL;
   if (origin != NULL)
     origin_die = add_abstract_origin_attribute (var_die, origin);
 
@@ -19183,14 +19639,8 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
      copy decls and set the DECL_ABSTRACT_P flag on them instead of
      sharing them.
 
-     ??? Duplicated blocks have been rewritten to use .debug_ranges.
-
-     ??? The declare_in_namespace support causes us to get two DIEs for one
-     variable, both of which are declarations.  We want to avoid considering
-     one to be a specification, so we must test that this DIE is not a
-     declaration.  */
-  else if (old_die && TREE_STATIC (decl) && ! declaration
-          && get_AT_flag (old_die, DW_AT_declaration) == 1)
+     ??? Duplicated blocks have been rewritten to use .debug_ranges.  */
+  else if (decl_will_get_specification_p (old_die, decl, declaration))
     {
       /* This is a definition of a C++ class level static.  */
       add_AT_specification (var_die, old_die);
@@ -19244,9 +19694,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   if (declaration)
     add_AT_flag (var_die, DW_AT_declaration, 1);
 
-  if (decl && (DECL_ABSTRACT_P (decl) || declaration || old_die == NULL))
+  if (decl && (DECL_ABSTRACT_P (decl)
+              || !old_die || is_declaration_die (old_die)))
     equate_decl_number_to_die (decl, var_die);
 
+ gen_variable_die_location:
   if (! declaration
       && (! DECL_ABSTRACT_P (decl_or_origin)
          /* Local static vars are shared between all clones/inlines,
@@ -19259,13 +19711,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
         to add it again.  */
       && (origin_die == NULL || get_AT (origin_die, DW_AT_location) == NULL))
     {
-      if (TREE_CODE (decl_or_origin) == VAR_DECL && TREE_STATIC (decl_or_origin)
-          && !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl_or_origin)))
-       defer_location (decl_or_origin, var_die);
+      if (early_dwarf)
+       add_pubname (decl_or_origin, var_die);
       else
-        add_location_or_const_value_attribute (var_die, decl_or_origin,
-                                              decl == NULL, DW_AT_location);
-      add_pubname (decl_or_origin, var_die);
+       add_location_or_const_value_attribute (var_die, decl_or_origin,
+                                              decl == NULL);
     }
   else
     tree_add_const_value_attribute_for_decl (var_die, decl_or_origin);
@@ -19279,7 +19729,12 @@ gen_const_die (tree decl, dw_die_ref context_die)
   dw_die_ref const_die;
   tree type = TREE_TYPE (decl);
 
+  const_die = lookup_decl_die (decl);
+  if (const_die)
+    return;
+
   const_die = new_die (DW_TAG_constant, context_die, decl);
+  equate_decl_number_to_die (decl, const_die);
   add_name_and_src_coords_attributes (const_die, decl);
   add_type_attribute (const_die, type, TYPE_QUAL_CONST, context_die);
   if (TREE_PUBLIC (decl))
@@ -19295,14 +19750,20 @@ static void
 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);
+  dw_die_ref lbl_die = lookup_decl_die (decl);
   rtx insn;
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  if (origin != NULL)
-    add_abstract_origin_attribute (lbl_die, origin);
-  else
-    add_name_and_src_coords_attributes (lbl_die, decl);
+  if (!lbl_die)
+    {
+      lbl_die = new_die (DW_TAG_label, context_die, decl);
+      equate_decl_number_to_die (decl, lbl_die);
+
+      if (origin != NULL)
+       add_abstract_origin_attribute (lbl_die, origin);
+      else
+       add_name_and_src_coords_attributes (lbl_die, decl);
+    }
 
   if (DECL_ABSTRACT_P (decl))
     equate_decl_number_to_die (decl, lbl_die);
@@ -19369,7 +19830,7 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
     {
       tree chain, superblock = NULL_TREE;
       dw_die_ref pdie;
-      dw_attr_ref attr = NULL;
+      dw_attr_node *attr = NULL;
 
       if (inlined_function_outer_scope_p (stmt))
        {
@@ -19387,7 +19848,7 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
           BLOCK_SAME_RANGE (chain);
           chain = BLOCK_SUPERCONTEXT (chain))
        {
-         dw_attr_ref new_attr;
+         dw_attr_node *new_attr;
 
          pdie = pdie->die_parent;
          if (pdie == NULL)
@@ -19456,13 +19917,55 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
 static void
 gen_lexical_block_die (tree stmt, dw_die_ref context_die)
 {
-  dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+  dw_die_ref old_die = BLOCK_DIE (stmt);
+  dw_die_ref stmt_die = NULL;
+  if (!old_die)
+    {
+      stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+      BLOCK_DIE (stmt) = stmt_die;
+    }
 
-  if (call_arg_locations)
-    BLOCK_DIE (stmt) = stmt_die;
+  if (BLOCK_ABSTRACT (stmt))
+    {
+      if (old_die)
+       {
+         /* This must have been generated early and it won't even
+            need location information since it's a DW_AT_inline
+            function.  */
+         if (flag_checking)
+           for (dw_die_ref c = context_die; c; c = c->die_parent)
+             if (c->die_tag == DW_TAG_inlined_subroutine
+                 || c->die_tag == DW_TAG_subprogram)
+               {
+                 gcc_assert (get_AT (c, DW_AT_inline));
+                 break;
+               }
+         return;
+       }
+    }
+  else if (BLOCK_ABSTRACT_ORIGIN (stmt))
+    {
+      /* If this is an inlined instance, create a new lexical die for
+        anything below to attach DW_AT_abstract_origin to.  */
+      if (old_die)
+       {
+         stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+         BLOCK_DIE (stmt) = stmt_die;
+         old_die = NULL;
+       }
+    }
+
+  if (old_die)
+    stmt_die = old_die;
 
-  if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
-    add_high_low_attributes (stmt, stmt_die);
+  /* A non abstract block whose blocks have already been reordered
+     should have the instruction range for this block.  If so, set the
+     high/low attributes.  */
+  if (!early_dwarf && !BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
+    {
+      gcc_assert (stmt_die);
+      add_high_low_attributes (stmt, stmt_die);
+    }
 
   decls_for_scope (stmt, stmt_die);
 }
@@ -19480,6 +19983,10 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die)
 
   decl = block_ultimate_origin (stmt);
 
+  /* Make sure any inlined functions are known to be inlineable.  */
+  gcc_checking_assert (DECL_ABSTRACT_P (decl)
+                      || cgraph_function_possibly_inlined_p (decl));
+
   /* Emit info for the abstract instance first, if we haven't yet.  We
      must emit this even if the block is abstract, otherwise when we
      emit the block below (or elsewhere), we may end up trying to emit
@@ -19592,8 +20099,6 @@ gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
                      context_die);
 }
 
-typedef const char *dchar_p; /* For DEF_VEC_P.  */
-
 static char *producer_string;
 
 /* Return a heap allocated producer string including command line options
@@ -19603,7 +20108,7 @@ static char *
 gen_producer_string (void)
 {
   size_t j;
-  auto_vec<dchar_p> switches;
+  auto_vec<const char *> switches;
   const char *language_string = lang_hooks.name;
   char *producer, *tail;
   const char *p;
@@ -19957,6 +20462,18 @@ static void
 gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
                                enum debug_info_usage usage)
 {
+  if (TREE_ASM_WRITTEN (type))
+    {
+      /* Fill in the bound of variable-length fields in late dwarf if
+        still incomplete.  */
+      if (!early_dwarf && variably_modified_type_p (type, NULL))
+       for (tree member = TYPE_FIELDS (type);
+            member;
+            member = DECL_CHAIN (member))
+         fill_variable_array_bounds (TREE_TYPE (member));
+      return;
+    }
+
   dw_die_ref type_die = lookup_type_die (type);
   dw_die_ref scope_die = 0;
   int nested = 0;
@@ -20076,7 +20593,11 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
   tree origin;
 
   if (TREE_ASM_WRITTEN (decl))
-    return;
+    {
+      if (DECL_ORIGINAL_TYPE (decl))
+       fill_variable_array_bounds (DECL_ORIGINAL_TYPE (decl));
+      return;
+    }
 
   TREE_ASM_WRITTEN (decl) = 1;
   type_die = new_die (DW_TAG_typedef, context_die, decl);
@@ -20092,6 +20613,9 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
        {
          type = DECL_ORIGINAL_TYPE (decl);
 
+         if (type == error_mark_node)
+           return;
+
          gcc_assert (type != TREE_TYPE (decl));
          equate_type_number_to_die (TREE_TYPE (decl), type_die);
        }
@@ -20099,6 +20623,9 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
        {
          type = TREE_TYPE (decl);
 
+         if (type == error_mark_node)
+           return;
+
          if (is_naming_typedef_decl (TYPE_NAME (type)))
            {
              /* Here, we are in the case of decl being a typedef naming
@@ -20159,13 +20686,15 @@ gen_tagged_type_die (tree type,
       || !is_tagged_type (type))
     return;
 
+  if (TREE_ASM_WRITTEN (type))
+    need_pop = 0;
   /* 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.  */
-  if (TYPE_CONTEXT (type)
+  else if (TYPE_CONTEXT (type)
       && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
       && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
     {
@@ -20227,10 +20756,8 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   if (type == NULL_TREE || type == error_mark_node)
     return;
 
-#ifdef ENABLE_CHECKING
-  if (type)
+  if (flag_checking && type)
      verify_type (type);
-#endif
 
   if (TYPE_NAME (type) != NULL_TREE
       && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
@@ -20278,9 +20805,10 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   /* 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
+     now.  (Vectors and arrays are special because the debugging info is in the
      cloned type itself).  */
-  if (TREE_CODE (type) != VECTOR_TYPE)
+  if (TREE_CODE (type) != VECTOR_TYPE
+      && TREE_CODE (type) != ARRAY_TYPE)
     type = type_main_variant (type);
 
   /* If this is an array type with hidden descriptor, handle it first.  */
@@ -20297,7 +20825,18 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
     }
 
   if (TREE_ASM_WRITTEN (type))
-    return;
+    {
+      /* Variable-length types may be incomplete even if
+        TREE_ASM_WRITTEN.  For such types, fall through to
+        gen_array_type_die() and possibly fill in
+        DW_AT_{upper,lower}_bound attributes.  */
+      if ((TREE_CODE (type) != ARRAY_TYPE
+          && TREE_CODE (type) != RECORD_TYPE
+          && TREE_CODE (type) != UNION_TYPE
+          && TREE_CODE (type) != QUAL_UNION_TYPE)
+         || !variably_modified_type_p (type, NULL))
+       return;
+    }
 
   switch (TREE_CODE (type))
     {
@@ -20349,9 +20888,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       break;
 
     case ARRAY_TYPE:
-      gen_array_type_die (type, context_die);
-      break;
-
     case VECTOR_TYPE:
       gen_array_type_die (type, context_die);
       break;
@@ -20413,7 +20949,16 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
 static void
 gen_type_die (tree type, dw_die_ref context_die)
 {
-  gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
+  if (type != error_mark_node)
+    {
+      gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
+      if (flag_checking)
+       {
+         dw_die_ref die = lookup_type_die (type);
+         if (die)
+           check_die (die);
+       }
+    }
 }
 
 /* Generate a DW_TAG_lexical_block DIE followed by DIEs to represent all of the
@@ -20522,8 +21067,11 @@ process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die)
   if (die != NULL && die->die_parent == NULL)
     add_child_die (context_die, die);
   else if (TREE_CODE (decl_or_origin) == IMPORTED_DECL)
-    dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
-                                        stmt, context_die);
+    {
+      if (early_dwarf)
+       dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
+                                            stmt, context_die);
+    }
   else
     gen_decl_die (decl, origin, context_die);
 }
@@ -20759,7 +21307,9 @@ setup_namespace_context (tree thing, dw_die_ref context_die)
    type) within its namespace, if appropriate.
 
    For compatibility with older debuggers, namespace DIEs only contain
-   declarations; all definitions are emitted at CU scope.  */
+   declarations; all definitions are emitted at CU scope, with
+   DW_AT_specification pointing to the declaration (like with class
+   members).  */
 
 static dw_die_ref
 declare_in_namespace (tree thing, dw_die_ref context_die)
@@ -21057,11 +21607,15 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
                                       context_die);
 
     case NAMESPACE_DECL:
-    case IMPORTED_DECL:
       if (dwarf_version >= 3 || !dwarf_strict)
        gen_namespace_die (decl, context_die);
       break;
 
+    case IMPORTED_DECL:
+      dwarf2out_imported_module_or_decl_1 (decl, DECL_NAME (decl),
+                                          DECL_CONTEXT (decl), context_die);
+      break;
+
     case NAMELIST_DECL:
       gen_namelist_decl (DECL_NAME (decl), context_die,
                         NAMELIST_DECL_ASSOCIATED_DECL (decl));
@@ -21076,19 +21630,73 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
   return NULL;
 }
 \f
-/* Output debug information for global decl DECL.  Called from toplev.c after
-   compilation proper has finished.  */
+/* Output initial debug information for global DECL.  Called at the
+   end of the parsing process.
+
+   This is the initial debug generation process.  As such, the DIEs
+   generated may be incomplete.  A later debug generation pass
+   (dwarf2out_late_global_decl) will augment the information generated
+   in this pass (e.g., with complete location info).  */
 
 static void
-dwarf2out_global_decl (tree decl)
+dwarf2out_early_global_decl (tree decl)
 {
-  /* Output DWARF2 information for file-scope tentative data object
-     declarations, file-scope (extern) function declarations (which
-     had no corresponding body) and file-scope tagged type declarations
-     and definitions which have not yet been forced out.  */
-  if ((TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))
+  set_early_dwarf s;
+
+  /* gen_decl_die() will set DECL_ABSTRACT because
+     cgraph_function_possibly_inlined_p() returns true.  This is in
+     turn will cause DW_AT_inline attributes to be set.
+
+     This happens because at early dwarf generation, there is no
+     cgraph information, causing cgraph_function_possibly_inlined_p()
+     to return true.  Trick cgraph_function_possibly_inlined_p()
+     while we generate dwarf early.  */
+  bool save = symtab->global_info_ready;
+  symtab->global_info_ready = true;
+
+  /* We don't handle TYPE_DECLs.  If required, they'll be reached via
+     other DECLs and they can point to template types or other things
+     that dwarf2out can't handle when done via dwarf2out_decl.  */
+  if (TREE_CODE (decl) != TYPE_DECL
+      && TREE_CODE (decl) != PARM_DECL)
+    {
+      tree save_fndecl = current_function_decl;
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       {
+         /* No cfun means the symbol has no body, so there's nothing
+            to emit.  */
+         if (!DECL_STRUCT_FUNCTION (decl))
+           goto early_decl_exit;
+
+         current_function_decl = decl;
+       }
+      dwarf2out_decl (decl);
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       current_function_decl = save_fndecl;
+    }
+ early_decl_exit:
+  symtab->global_info_ready = save;
+}
+
+/* Output debug information for global decl DECL.  Called from
+   toplev.c after compilation proper has finished.  */
+
+static void
+dwarf2out_late_global_decl (tree decl)
+{
+  /* We have to generate early debug late for LTO.  */
+  if (in_lto_p)
+    dwarf2out_early_global_decl (decl);
+
+    /* Fill-in any location information we were unable to determine
+       on the first pass.  */
+  if (TREE_CODE (decl) == VAR_DECL
       && !POINTER_BOUNDS_P (decl))
-    dwarf2out_decl (decl);
+    {
+      dw_die_ref die = lookup_decl_die (decl);
+      if (die)
+       add_location_or_const_value_attribute (die, decl, false);
+    }
 }
 
 /* Output debug information for type decl DECL.  Called from toplev.c
@@ -21097,7 +21705,10 @@ static void
 dwarf2out_type_decl (tree decl, int local)
 {
   if (!local)
-    dwarf2out_decl (decl);
+    {
+      set_early_dwarf s;
+      dwarf2out_decl (decl);
+    }
 }
 
 /* Output debug information for imported module or decl DECL.
@@ -21205,6 +21816,8 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
 
   gcc_assert (decl);
 
+  set_early_dwarf s;
+
   /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs.
      We need decl DIE for reference and scope die. First, get DIE for the decl
      itself.  */
@@ -21231,7 +21844,6 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
 
   /* OK, now we have DIEs for decl as well as scope. Emit imported die.  */
   dwarf2out_imported_module_or_decl_1 (decl, name, context, scope_die);
-
 }
 
 /* Output debug information for namelists.   */
@@ -21271,7 +21883,7 @@ gen_namelist_decl (tree name, dw_die_ref scope_die, tree item_decls)
 }
 
 
-/* Write the debugging output for DECL.  */
+/* Write the debugging output for DECL and return the DIE.  */
 
 static void
 dwarf2out_decl (tree decl)
@@ -21330,21 +21942,8 @@ dwarf2out_decl (tree decl)
       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.  */
-      if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
-       return;
-
       /* For local statics lookup proper context die.  */
-      if (TREE_STATIC (decl)
-         && DECL_CONTEXT (decl)
-         && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
+      if (local_function_static (decl))
        context_die = lookup_decl_die (DECL_CONTEXT (decl));
 
       /* If we are in terse mode, don't generate any DIEs to represent any
@@ -21399,6 +21998,13 @@ dwarf2out_decl (tree decl)
     }
 
   gen_decl_die (decl, NULL, context_die);
+
+  if (flag_checking)
+    {
+      dw_die_ref die = lookup_decl_die (decl);
+      if (die)
+       check_die (die);
+    }
 }
 
 /* Write the debugging output for DECL.  */
@@ -21483,25 +22089,18 @@ dwarf_file_hasher::hash (dwarf_file_data *p)
    just a unique number which is associated with only that one filename.  We
    need such numbers for the sake of generating labels (in the .debug_sfnames
    section) and references to those files numbers (in the .debug_srcinfo
-   and.debug_macinfo sections).  If the filename given as an argument is not
+   and .debug_macinfo sections).  If the filename given as an argument is not
    found in our current list, add it to the list and assign it the next
-   available unique index number.  In order to speed up searches, we remember
-   the index of the filename was looked up last.  This handles the majority of
-   all searches.  */
+   available unique index number.  */
 
 static struct dwarf_file_data *
 lookup_filename (const char *file_name)
 {
   struct dwarf_file_data * created;
 
-  /* 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
-      && (file_name == file_table_last_lookup->filename
-         || filename_cmp (file_table_last_lookup->filename, file_name) == 0))
-    return file_table_last_lookup;
+  if (!file_name)
+    return NULL;
 
-  /* Didn't match the previous lookup, search the table.  */
   dwarf_file_data **slot
     = file_table->find_slot_with_hash (file_name, htab_hash_string (file_name),
                                       INSERT);
@@ -21556,6 +22155,8 @@ append_entry_to_tmpl_value_parm_die_table (dw_die_ref die, tree arg)
   if (!die || !arg)
     return;
 
+  gcc_assert (early_dwarf);
+
   if (!tmpl_value_parm_die_table)
     vec_alloc (tmpl_value_parm_die_table, 32);
 
@@ -21585,6 +22186,8 @@ schedule_generic_params_dies_gen (tree t)
   if (!generic_type_p (t))
     return;
 
+  gcc_assert (early_dwarf);
+
   if (!generic_type_instances)
     vec_alloc (generic_type_instances, 256);
 
@@ -21600,11 +22203,21 @@ gen_remaining_tmpl_value_param_die_attribute (void)
 {
   if (tmpl_value_parm_die_table)
     {
-      unsigned i;
+      unsigned i, j;
       die_arg_entry *e;
 
+      /* We do this in two phases - first get the cases we can
+        handle during early-finish, preserving those we cannot
+        (containing symbolic constants where we don't yet know
+        whether we are going to output the referenced symbols).
+        For those we try again at late-finish.  */
+      j = 0;
       FOR_EACH_VEC_ELT (*tmpl_value_parm_die_table, i, e)
-       tree_add_const_value_attribute (e->die, e->arg);
+       {
+         if (!tree_add_const_value_attribute (e->die, e->arg))
+           (*tmpl_value_parm_die_table)[j++] = *e;
+       }
+      tmpl_value_parm_die_table->truncate (j);
     }
 }
 
@@ -21622,9 +22235,15 @@ gen_scheduled_generic_parms_dies (void)
   if (!generic_type_instances)
     return;
   
+  /* We end up "recursing" into schedule_generic_params_dies_gen, so
+     pretend this generation is part of "early dwarf" as well.  */
+  set_early_dwarf s;
+
   FOR_EACH_VEC_ELT (*generic_type_instances, i, t)
     if (COMPLETE_TYPE_P (t))
       gen_generic_params_dies (t);
+
+  generic_type_instances = NULL;
 }
 
 
@@ -21634,7 +22253,7 @@ static void
 dwarf2out_set_name (tree decl, tree name)
 {
   dw_die_ref die;
-  dw_attr_ref attr;
+  dw_attr_node *attr;
   const char *dname;
 
   die = TYPE_SYMTAB_DIE (decl);
@@ -21677,6 +22296,7 @@ dwarf2out_var_location (rtx_insn *loc_note)
   char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
   struct var_loc_node *newloc;
   rtx_insn *next_real, *next_note;
+  rtx_insn *call_insn = NULL;
   static const char *last_label;
   static const char *last_postcall_label;
   static bool last_in_cold_section_p;
@@ -21691,6 +22311,35 @@ dwarf2out_var_location (rtx_insn *loc_note)
          call_site_count++;
          if (SIBLING_CALL_P (loc_note))
            tail_call_site_count++;
+         if (optimize == 0 && !flag_var_tracking)
+           {
+             /* When the var-tracking pass is not running, there is no note
+                for indirect calls whose target is compile-time known. In this
+                case, process such calls specifically so that we generate call
+                sites for them anyway.  */
+             rtx x = PATTERN (loc_note);
+             if (GET_CODE (x) == PARALLEL)
+               x = XVECEXP (x, 0, 0);
+             if (GET_CODE (x) == SET)
+               x = SET_SRC (x);
+             if (GET_CODE (x) == CALL)
+               x = XEXP (x, 0);
+             if (!MEM_P (x)
+                 || GET_CODE (XEXP (x, 0)) != SYMBOL_REF
+                 || !SYMBOL_REF_DECL (XEXP (x, 0))
+                 || (TREE_CODE (SYMBOL_REF_DECL (XEXP (x, 0)))
+                     != FUNCTION_DECL))
+               {
+                 call_insn = loc_note;
+                 loc_note = NULL;
+                 var_loc_p = false;
+
+                 next_real = next_real_insn (call_insn);
+                 next_note = NULL;
+                 cached_next_real_insn = NULL;
+                 goto create_label;
+               }
+           }
        }
       return;
     }
@@ -21736,6 +22385,8 @@ dwarf2out_var_location (rtx_insn *loc_note)
       && !NOTE_DURING_CALL_P (loc_note))
     return;
 
+create_label:
+
   if (next_real == NULL_RTX)
     next_real = get_last_insn ();
 
@@ -21815,12 +22466,16 @@ dwarf2out_var_location (rtx_insn *loc_note)
        }
     }
 
+  gcc_assert ((loc_note == NULL_RTX && call_insn != NULL_RTX)
+             || (loc_note != NULL_RTX && call_insn == NULL_RTX));
+
   if (!var_loc_p)
     {
       struct call_arg_loc_node *ca_loc
        = ggc_cleared_alloc<call_arg_loc_node> ();
-      rtx_insn *prev = prev_real_insn (loc_note);
-      rtx x;
+      rtx_insn *prev
+        = loc_note != NULL_RTX ? prev_real_insn (loc_note) : call_insn;
+
       ca_loc->call_arg_loc_note = loc_note;
       ca_loc->next = NULL;
       ca_loc->label = last_label;
@@ -21832,15 +22487,27 @@ dwarf2out_var_location (rtx_insn *loc_note)
       if (!CALL_P (prev))
        prev = as_a <rtx_sequence *> (PATTERN (prev))->insn (0);
       ca_loc->tail_call_p = SIBLING_CALL_P (prev);
-      x = get_call_rtx_from (PATTERN (prev));
+
+      /* Look for a SYMBOL_REF in the "prev" instruction.  */
+      rtx x = get_call_rtx_from (PATTERN (prev));
       if (x)
        {
-         x = XEXP (XEXP (x, 0), 0);
-         if (GET_CODE (x) == SYMBOL_REF
-             && SYMBOL_REF_DECL (x)
-             && TREE_CODE (SYMBOL_REF_DECL (x)) == FUNCTION_DECL)
-           ca_loc->symbol_ref = x;
+         /* Try to get the call symbol, if any.  */
+         if (MEM_P (XEXP (x, 0)))
+           x = XEXP (x, 0);
+         /* First, look for a memory access to a symbol_ref.  */
+         if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+             && SYMBOL_REF_DECL (XEXP (x, 0))
+             && TREE_CODE (SYMBOL_REF_DECL (XEXP (x, 0))) == FUNCTION_DECL)
+           ca_loc->symbol_ref = XEXP (x, 0);
+         /* Otherwise, look at a compile-time known user-level function
+            declaration.  */
+         else if (MEM_P (x)
+                  && MEM_EXPR (x)
+                  && TREE_CODE (MEM_EXPR (x)) == FUNCTION_DECL)
+           ca_loc->symbol_ref = XEXP (DECL_RTL (MEM_EXPR (x)), 0);
        }
+
       ca_loc->block = insn_scope (prev);
       if (call_arg_locations)
        call_arg_loc_last->next = ca_loc;
@@ -21848,7 +22515,7 @@ dwarf2out_var_location (rtx_insn *loc_note)
        call_arg_locations = ca_loc;
       call_arg_loc_last = ca_loc;
     }
-  else if (!NOTE_DURING_CALL_P (loc_note))
+  else if (loc_note != NULL_RTX && !NOTE_DURING_CALL_P (loc_note))
     newloc->label = last_label;
   else
     {
@@ -21894,7 +22561,7 @@ new_line_info_table (void)
 {
   dw_line_info_table *table;
 
-  table = ggc_cleared_alloc<dw_line_info_table_struct> ();
+  table = ggc_cleared_alloc<dw_line_info_table> ();
   table->file_num = 1;
   table->line_num = 1;
   table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
@@ -22034,6 +22701,26 @@ dwarf2out_end_function (unsigned int)
   maybe_at_text_label_p = false;
 }
 
+/* Temporary holder for dwarf2out_register_main_translation_unit.  Used to let
+   front-ends register a translation unit even before dwarf2out_init is
+   called.  */
+static tree main_translation_unit = NULL_TREE;
+
+/* Hook called by front-ends after they built their main translation unit.
+   Associate comp_unit_die to UNIT.  */
+
+static void
+dwarf2out_register_main_translation_unit (tree unit)
+{
+  gcc_assert (TREE_CODE (unit) == TRANSLATION_UNIT_DECL
+             && main_translation_unit == NULL_TREE);
+  main_translation_unit = unit;
+  /* If dwarf2out_init has not been called yet, it will perform the association
+     itself looking at main_translation_unit.  */
+  if (decl_die_table != NULL)
+    equate_decl_number_to_die (unit, comp_unit_die ());
+}
+
 /* Add OPCODE+VAL as an entry at the end of the opcode array in TABLE.  */
 
 static void
@@ -22242,10 +22929,8 @@ dwarf2out_undef (unsigned int lineno ATTRIBUTE_UNUSED,
 
 /* Helpers to manipulate hash table of CUs.  */
 
-struct macinfo_entry_hasher : typed_noop_remove <macinfo_entry>
+struct macinfo_entry_hasher : nofree_ptr_hash <macinfo_entry>
 {
-  typedef macinfo_entry *value_type;
-  typedef macinfo_entry *compare_type;
   static inline hashval_t hash (const macinfo_entry *);
   static inline bool equal (const macinfo_entry *, const macinfo_entry *);
 };
@@ -22652,6 +23337,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   /* Allocate the file_table.  */
   file_table = hash_table<dwarf_file_hasher>::create_ggc (50);
 
+#ifndef DWARF2_LINENO_DEBUGGING_INFO
   /* Allocate the decl_die_table.  */
   decl_die_table = hash_table<decl_die_hasher>::create_ggc (10);
 
@@ -22767,10 +23453,20 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
 
   switch_to_section (text_section);
   ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
+#endif
 
   /* Make sure the line number table for .text always exists.  */
   text_section_line_info = new_line_info_table ();
   text_section_line_info->end_label = text_end_label;
+
+#ifdef DWARF2_LINENO_DEBUGGING_INFO
+  cur_line_info_table = text_section_line_info;
+#endif
+
+  /* If front-ends already registered a main translation unit but we were not
+     ready to perform the association, do this now.  */
+  if (main_translation_unit != NULL_TREE)
+    equate_decl_number_to_die (main_translation_unit, comp_unit_die ());
 }
 
 /* Called before compile () starts outputtting functions, variables
@@ -22976,7 +23672,7 @@ prune_unmark_dies (dw_die_ref die)
 static void
 prune_unused_types_walk_attribs (dw_die_ref die)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -23183,7 +23879,7 @@ prune_unused_types_walk (dw_die_ref die)
 static void
 prune_unused_types_update_strings (dw_die_ref die)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -23251,7 +23947,7 @@ prune_unused_types (void)
   unsigned int i;
   limbo_die_node *node;
   comdat_type_node *ctnode;
-  pubname_ref pub;
+  pubname_entry *pub;
   dw_die_ref base_type;
 
 #if ENABLE_ASSERT_CHECKING
@@ -23291,8 +23987,17 @@ prune_unused_types (void)
   if (skeleton_debug_str_hash)
     skeleton_debug_str_hash->empty ();
   prune_unused_types_prune (comp_unit_die ());
-  for (node = limbo_die_list; node; node = node->next)
-    prune_unused_types_prune (node->die);
+  for (limbo_die_node **pnode = &limbo_die_list; *pnode; )
+    {
+      node = *pnode;
+      if (!node->die->die_mark)
+       *pnode = node->next;
+      else
+       {
+         prune_unused_types_prune (node->die);
+         pnode = &node->next;
+       }
+    }
   for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next)
     prune_unused_types_prune (ctnode->root_die);
 
@@ -23320,10 +24025,8 @@ file_table_relative_p (dwarf_file_data **slot, bool *p)
 
 /* Helpers to manipulate hash table of comdat type units.  */
 
-struct comdat_type_hasher : typed_noop_remove <comdat_type_node>
+struct comdat_type_hasher : nofree_ptr_hash <comdat_type_node>
 {
-  typedef comdat_type_node *value_type;
-  typedef comdat_type_node *compare_type;
   static inline hashval_t hash (const comdat_type_node *);
   static inline bool equal (const comdat_type_node *, const comdat_type_node *);
 };
@@ -23855,7 +24558,7 @@ static void
 resolve_addr (dw_die_ref die)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   dw_loc_list_ref *curr, *start, loc;
   unsigned ix;
 
@@ -24433,10 +25136,8 @@ compare_locs (dw_loc_descr_ref x, dw_loc_descr_ref y)
 
 /* Hashtable helpers.  */
 
-struct loc_list_hasher : typed_noop_remove <dw_loc_list_struct>
+struct loc_list_hasher : nofree_ptr_hash <dw_loc_list_struct>
 {
-  typedef dw_loc_list_struct *value_type;
-  typedef dw_loc_list_struct *compare_type;
   static inline hashval_t hash (const dw_loc_list_struct *);
   static inline bool equal (const dw_loc_list_struct *,
                            const dw_loc_list_struct *);
@@ -24480,7 +25181,7 @@ static void
 optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type *htab)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
   dw_loc_list_struct **slot;
 
@@ -24509,7 +25210,7 @@ static void
 index_location_lists (dw_die_ref die)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -24544,61 +25245,17 @@ optimize_location_lists (dw_die_ref die)
   optimize_location_lists_1 (die, &htab);
 }
 \f
-/* Output stuff that dwarf requires at the end of every file,
-   and generate the DWARF-2 debugging info.  */
+/* 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.
+   For concrete instances, we can get the parent die from the abstract
+   instance.  */
 
 static void
-dwarf2out_finish (const char *filename)
+flush_limbo_die_list (void)
 {
   limbo_die_node *node, *next_node;
-  comdat_type_node *ctnode;
-  unsigned int i;
-  dw_die_ref main_comp_unit_die;
-
-  /* PCH might result in DW_AT_producer string being restored from the
-     header compilation, so always fill it with empty string initially
-     and overwrite only here.  */
-  dw_attr_ref producer = get_AT (comp_unit_die (), DW_AT_producer);
-  producer_string = gen_producer_string ();
-  producer->dw_attr_val.v.val_str->refcount--;
-  producer->dw_attr_val.v.val_str = find_AT_string (producer_string);
-
-  gen_scheduled_generic_parms_dies ();
-  gen_remaining_tmpl_value_param_die_attribute ();
-
-  /* Add the name for the main input file now.  We delayed this from
-     dwarf2out_init to avoid complications with PCH.
-     For LTO produced units use a fixed artificial name to avoid
-     leaking tempfile names into the dwarf.  */
-  if (!in_lto_p)
-    add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
-  else
-    add_name_attribute (comp_unit_die (), "<artificial>");
-  if (!IS_ABSOLUTE_PATH (filename) || targetm.force_at_comp_dir)
-    add_comp_dir_attribute (comp_unit_die ());
-  else if (get_AT (comp_unit_die (), DW_AT_comp_dir) == NULL)
-    {
-      bool p = false;
-      file_table->traverse<bool *, file_table_relative_p> (&p);
-      if (p)
-       add_comp_dir_attribute (comp_unit_die ());
-    }
-
-  if (deferred_locations_list)
-    for (i = 0; i < deferred_locations_list->length (); i++)
-      {
-       add_location_or_const_value_attribute (
-           (*deferred_locations_list)[i].die,
-           (*deferred_locations_list)[i].variable,
-           false,
-           DW_AT_location);
-      }
 
-  /* 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.
-     For concrete instances, we can get the parent die from the abstract
-     instance.  */
   for (node = limbo_die_list; node; node = next_node)
     {
       dw_die_ref die = node->die;
@@ -24642,6 +25299,51 @@ dwarf2out_finish (const char *filename)
     }
 
   limbo_die_list = NULL;
+}
+
+/* Output stuff that dwarf requires at the end of every file,
+   and generate the DWARF-2 debugging info.  */
+
+static void
+dwarf2out_finish (const char *filename)
+{
+  comdat_type_node *ctnode;
+  dw_die_ref main_comp_unit_die;
+
+  /* Flush out any latecomers to the limbo party.  */
+  flush_limbo_die_list ();
+
+  /* We shouldn't have any symbols with delayed asm names for
+     DIEs generated after early finish.  */
+  gcc_assert (deferred_asm_name == NULL);
+
+  /* PCH might result in DW_AT_producer string being restored from the
+     header compilation, so always fill it with empty string initially
+     and overwrite only here.  */
+  dw_attr_node *producer = get_AT (comp_unit_die (), DW_AT_producer);
+  producer_string = gen_producer_string ();
+  producer->dw_attr_val.v.val_str->refcount--;
+  producer->dw_attr_val.v.val_str = find_AT_string (producer_string);
+
+  gen_remaining_tmpl_value_param_die_attribute ();
+
+  /* Add the name for the main input file now.  We delayed this from
+     dwarf2out_init to avoid complications with PCH.
+     For LTO produced units use a fixed artificial name to avoid
+     leaking tempfile names into the dwarf.  */
+  if (!in_lto_p)
+    add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
+  else
+    add_name_attribute (comp_unit_die (), "<artificial>");
+  if (!IS_ABSOLUTE_PATH (filename) || targetm.force_at_comp_dir)
+    add_comp_dir_attribute (comp_unit_die ());
+  else if (get_AT (comp_unit_die (), DW_AT_comp_dir) == NULL)
+    {
+      bool p = false;
+      file_table->traverse<bool *, file_table_relative_p> (&p);
+      if (p)
+       add_comp_dir_attribute (comp_unit_die ());
+    }
 
 #if ENABLE_ASSERT_CHECKING
   {
@@ -24652,23 +25354,6 @@ dwarf2out_finish (const char *filename)
   resolve_addr (comp_unit_die ());
   move_marked_base_types ();
 
-  for (node = deferred_asm_name; node; node = node->next)
-    {
-      tree decl = node->created_for;
-      /* When generating LTO bytecode we can not generate new assembler
-         names at this point and all important decls got theirs via
-        free-lang-data.  */
-      if (((!flag_generate_lto && !flag_generate_offload)
-          || DECL_ASSEMBLER_NAME_SET_P (decl))
-         && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
-       {
-         add_linkage_attr (node->die, decl);
-         move_linkage_attr (node->die);
-       }
-    }
-
-  deferred_asm_name = NULL;
-
   /* Walk through the list of incomplete types again, trying once more to
      emit full debugging info for them.  */
   retry_incomplete_types ();
@@ -24704,9 +25389,10 @@ dwarf2out_finish (const char *filename)
   if (flag_eliminate_dwarf2_dups)
     break_out_includes (comp_unit_die ());
 
-  /* Traverse the DIE's and add add sibling attributes to those DIE's
-     that have children.  */
+  /* Traverse the DIE's and add sibling attributes to those DIE's that
+     have children.  */
   add_sibling_attributes (comp_unit_die ());
+  limbo_die_node *node;
   for (node = limbo_die_list; node; node = node->next)
     add_sibling_attributes (node->die);
   for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
@@ -24922,10 +25608,8 @@ dwarf2out_finish (const char *filename)
      generate a table that would have contained data.  */
   if (info_section_emitted)
     {
-      unsigned long aranges_length = size_of_aranges ();
-
       switch_to_section (debug_aranges_section);
-      output_aranges (aranges_length);
+      output_aranges ();
     }
 
   /* Output ranges section if necessary.  */
@@ -24968,6 +25652,38 @@ dwarf2out_finish (const char *filename)
     output_indirect_strings ();
 }
 
+/* Perform any cleanups needed after the early debug generation pass
+   has run.  */
+
+static void
+dwarf2out_early_finish (void)
+{
+  limbo_die_node *node;
+
+  /* Add DW_AT_linkage_name for all deferred DIEs.  */
+  for (node = deferred_asm_name; node; node = node->next)
+    {
+      tree decl = node->created_for;
+      if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
+         /* A missing DECL_ASSEMBLER_NAME can be a constant DIE that
+            ended up in deferred_asm_name before we knew it was
+            constant and never written to disk.  */
+         && DECL_ASSEMBLER_NAME (decl))
+       {
+         add_linkage_attr (node->die, decl);
+         move_linkage_attr (node->die);
+       }
+    }
+  deferred_asm_name = NULL;
+
+  /* The point here is to flush out the limbo list so that it is empty
+     and we don't need to stream it for LTO.  */
+  flush_limbo_die_list ();
+
+  gen_scheduled_generic_parms_dies ();
+  gen_remaining_tmpl_value_param_die_attribute ();
+}
+
 /* Reset all state within dwarf2out.c so that we can rerun the compiler
    within the same process.  For use by toplev::finalize.  */
 
@@ -25006,13 +25722,10 @@ dwarf2out_c_finalize (void)
   cold_text_section = NULL;
   current_unit_personality = NULL;
 
-  deferred_locations_list = NULL;
-
   next_die_offset = 0;
   single_comp_unit_die = NULL;
   comdat_type_list = NULL;
   limbo_die_list = NULL;
-  deferred_asm_name = NULL;
   file_table = NULL;
   decl_die_table = NULL;
   common_block_die_table = NULL;
@@ -25045,7 +25758,6 @@ dwarf2out_c_finalize (void)
   poc_label_num = 0;
   last_emitted_file = NULL;
   label_num = 0;
-  file_table_last_lookup = NULL;
   tmpl_value_parm_die_table = NULL;
   generic_type_instances = NULL;
   frame_pointer_fb_offset = 0;