remove unused files
[platform/upstream/gcc48.git] / gcc / dwarf2out.c
index 4ac66f9..77771c0 100644 (file)
@@ -1,7 +1,5 @@
 /* Output Dwarf2 format symbol table information from GCC.
-   Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-   Free Software Foundation, Inc.
+   Copyright (C) 1992-2013 Free Software Foundation, Inc.
    Contributed by Gary Funck (gary@intrepid.com).
    Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
    Extensively modified by Jason Merrill (jason@cygnus.com).
@@ -72,7 +70,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "function.h"
 #include "output.h"
 #include "expr.h"
-#include "libfuncs.h"
 #include "except.h"
 #include "dwarf2.h"
 #include "dwarf2out.h"
@@ -91,9 +88,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "input.h"
 #include "gimple.h"
-#include "tree-pass.h"
-#include "tree-flow.h"
-#include "cfglayout.h"
+#include "ira.h"
+#include "lra.h"
+#include "dumpfile.h"
 #include "opts.h"
 
 static void dwarf2out_source_line (unsigned int, const char *, int, bool);
@@ -131,31 +128,36 @@ int vms_file_stats_name (const char *, long long *, long *, char *, int *);
 
 /* Array of RTXes referenced by the debugging information, which therefore
    must be kept around forever.  */
-static GTY(()) VEC(rtx,gc) *used_rtx_array;
+static GTY(()) vec<rtx, va_gc> *used_rtx_array;
 
 /* A pointer to the base of a list of incomplete types which might be
    completed at some later time.  incomplete_types_list needs to be a
-   VEC(tree,gc) because we want to tell the garbage collector about
+   vec<tree, va_gc> *because we want to tell the garbage collector about
    it.  */
-static GTY(()) VEC(tree,gc) *incomplete_types;
+static GTY(()) vec<tree, va_gc> *incomplete_types;
 
 /* A pointer to the base of a table of references to declaration
    scopes.  This table is a display which tracks the nesting
    of declaration scopes at the current scope and containing
    scopes.  This table is used to find the proper place to
    define type declaration DIE's.  */
-static GTY(()) VEC(tree,gc) *decl_scope_table;
+static GTY(()) vec<tree, va_gc> *decl_scope_table;
 
 /* Pointers to various DWARF2 sections.  */
 static GTY(()) section *debug_info_section;
+static GTY(()) section *debug_skeleton_info_section;
 static GTY(()) section *debug_abbrev_section;
+static GTY(()) section *debug_skeleton_abbrev_section;
 static GTY(()) section *debug_aranges_section;
+static GTY(()) section *debug_addr_section;
 static GTY(()) section *debug_macinfo_section;
 static GTY(()) section *debug_line_section;
+static GTY(()) section *debug_skeleton_line_section;
 static GTY(()) section *debug_loc_section;
 static GTY(()) section *debug_pubnames_section;
 static GTY(()) section *debug_pubtypes_section;
 static GTY(()) section *debug_str_section;
+static GTY(()) section *debug_str_offsets_section;
 static GTY(()) section *debug_ranges_section;
 static GTY(()) section *debug_frame_section;
 
@@ -186,18 +188,20 @@ static GTY(()) section *debug_frame_section;
 #define DWARF_CIE_ID DW_CIE_ID
 #endif
 
-DEF_VEC_P (dw_fde_ref);
-DEF_VEC_ALLOC_P (dw_fde_ref, gc);
 
 /* A vector for a table that contains frame description
    information for each routine.  */
-static GTY(()) VEC(dw_fde_ref, gc) *fde_vec;
+#define NOT_INDEXED (-1U)
+#define NO_INDEX_ASSIGNED (-2U)
+
+static GTY(()) vec<dw_fde_ref, va_gc> *fde_vec;
 
 struct GTY(()) indirect_string_node {
   const char *str;
   unsigned int refcount;
   enum dwarf_form form;
   char *label;
+  unsigned int index;
 };
 
 static GTY ((param_is (struct indirect_string_node))) htab_t debug_str_hash;
@@ -608,7 +612,7 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
     size_t from, until, i;
 
     from = 0;
-    until = VEC_length (dw_cfi_ref, fde->dw_fde_cfi);
+    until = vec_safe_length (fde->dw_fde_cfi);
 
     if (fde->dw_fde_second_begin == NULL)
       ;
@@ -618,7 +622,7 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
       from = fde->dw_fde_switch_cfi_index;
 
     for (i = from; i < until; i++)
-      output_cfi (VEC_index (dw_cfi_ref, fde->dw_fde_cfi, i), fde, for_eh);
+      output_cfi ((*fde->dw_fde_cfi)[i], fde, for_eh);
   }
 
   /* If we are to emit a ref/link from function bodies to their frame tables,
@@ -686,7 +690,7 @@ output_call_frame_info (int for_eh)
   int dw_cie_version;
 
   /* Don't emit a CIE if there won't be any FDEs.  */
-  if (fde_vec == NULL)
+  if (!fde_vec)
     return;
 
   /* Nothing to do if the assembler's doing it all.  */
@@ -703,7 +707,7 @@ output_call_frame_info (int for_eh)
     {
       bool any_eh_needed = false;
 
-      FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, i, fde)
+      FOR_EACH_VEC_ELT (*fde_vec, i, fde)
        {
          if (fde->uses_eh_lsda)
            any_eh_needed = any_lsda_needed = true;
@@ -855,7 +859,7 @@ output_call_frame_info (int for_eh)
                             eh_data_format_name (fde_encoding));
     }
 
-  FOR_EACH_VEC_ELT (dw_cfi_ref, cie_cfi_vec, i, cfi)
+  FOR_EACH_VEC_ELT (*cie_cfi_vec, i, cfi)
     output_cfi (cfi, NULL, for_eh);
 
   /* Pad the CIE out to an address sized boundary.  */
@@ -864,7 +868,7 @@ output_call_frame_info (int for_eh)
   ASM_OUTPUT_LABEL (asm_out_file, l2);
 
   /* Loop through all of the FDE's.  */
-  FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, i, fde)
+  FOR_EACH_VEC_ELT (*fde_vec, i, fde)
     {
       unsigned int k;
 
@@ -879,11 +883,6 @@ output_call_frame_info (int for_eh)
 
   if (for_eh && targetm.terminate_dw2_eh_frame_info)
     dw2_asm_output_data (4, 0, "End of Table");
-#ifdef MIPS_DEBUGGING_INFO
-  /* Work around Irix 6 assembler bug whereby labels at the end of a section
-     get a value of 0.  Putting .align 0 after the label fixes it.  */
-  ASM_OUTPUT_ALIGN (asm_out_file, 0);
-#endif
 
   /* Turn off app to make assembly quicker.  */
   if (flag_debug_asm)
@@ -948,7 +947,7 @@ dwarf2out_alloc_current_fde (void)
   fde = ggc_alloc_cleared_dw_fde_node ();
   fde->decl = current_function_decl;
   fde->funcdef_number = current_function_funcdef_no;
-  fde->fde_index = VEC_length (dw_fde_ref, fde_vec);
+  fde->fde_index = vec_safe_length (fde_vec);
   fde->all_throwers_are_sibcalls = crtl->all_throwers_are_sibcalls;
   fde->uses_eh_lsda = crtl->uses_eh_lsda;
   fde->nothrow = crtl->nothrow;
@@ -957,7 +956,7 @@ dwarf2out_alloc_current_fde (void)
 
   /* Record the FDE associated with this function.  */
   cfun->fde = fde;
-  VEC_safe_push (dw_fde_ref, gc, fde_vec, fde);
+  vec_safe_push (fde_vec, fde);
 
   return fde;
 }
@@ -983,7 +982,7 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
      call-site information.  We must emit this label if it might be used.  */
   if (!do_frame
       && (!flag_exceptions
-         || targetm_common.except_unwind_info (&global_options) != UI_TARGET))
+         || targetm_common.except_unwind_info (&global_options) == UI_SJLJ))
     return;
 
   fnsec = function_section (current_function_decl);
@@ -1196,21 +1195,39 @@ typedef struct GTY(()) deferred_locations_struct
   dw_die_ref die;
 } deferred_locations;
 
-DEF_VEC_O(deferred_locations);
-DEF_VEC_ALLOC_O(deferred_locations,gc);
 
-static GTY(()) VEC(deferred_locations, gc) *deferred_locations_list;
+static GTY(()) vec<deferred_locations, va_gc> *deferred_locations_list;
 
-DEF_VEC_P(dw_die_ref);
-DEF_VEC_ALLOC_P(dw_die_ref,heap);
+
+/* Describe an entry into the .debug_addr section.  */
+
+enum ate_kind {
+  ate_kind_rtx,
+  ate_kind_rtx_dtprel,
+  ate_kind_label
+};
+
+typedef struct GTY(()) addr_table_entry_struct {
+  enum ate_kind kind;
+  unsigned int refcount;
+  unsigned int index;
+  union addr_table_entry_struct_union
+    {
+      rtx GTY ((tag ("0"))) rtl;
+      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
    their entire life.  */
 typedef struct GTY(()) dw_loc_list_struct {
   dw_loc_list_ref dw_loc_next;
-  const char *begin; /* Label for begin address of range */
-  const char *end;  /* Label for end address of range */
+  const char *begin; /* Label and addr_entry for start of range */
+  addr_table_entry *begin_entry;
+  const char *end;  /* Label for end of range */
   char *ll_symbol; /* Label for beginning of location list.
                      Only on head of list */
   const char *section; /* Section this loclist is relative to */
@@ -1234,344 +1251,12 @@ static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
 static const char *
 dwarf_stack_op_name (unsigned int op)
 {
-  switch (op)
-    {
-    case DW_OP_addr:
-      return "DW_OP_addr";
-    case DW_OP_deref:
-      return "DW_OP_deref";
-    case DW_OP_const1u:
-      return "DW_OP_const1u";
-    case DW_OP_const1s:
-      return "DW_OP_const1s";
-    case DW_OP_const2u:
-      return "DW_OP_const2u";
-    case DW_OP_const2s:
-      return "DW_OP_const2s";
-    case DW_OP_const4u:
-      return "DW_OP_const4u";
-    case DW_OP_const4s:
-      return "DW_OP_const4s";
-    case DW_OP_const8u:
-      return "DW_OP_const8u";
-    case DW_OP_const8s:
-      return "DW_OP_const8s";
-    case DW_OP_constu:
-      return "DW_OP_constu";
-    case DW_OP_consts:
-      return "DW_OP_consts";
-    case DW_OP_dup:
-      return "DW_OP_dup";
-    case DW_OP_drop:
-      return "DW_OP_drop";
-    case DW_OP_over:
-      return "DW_OP_over";
-    case DW_OP_pick:
-      return "DW_OP_pick";
-    case DW_OP_swap:
-      return "DW_OP_swap";
-    case DW_OP_rot:
-      return "DW_OP_rot";
-    case DW_OP_xderef:
-      return "DW_OP_xderef";
-    case DW_OP_abs:
-      return "DW_OP_abs";
-    case DW_OP_and:
-      return "DW_OP_and";
-    case DW_OP_div:
-      return "DW_OP_div";
-    case DW_OP_minus:
-      return "DW_OP_minus";
-    case DW_OP_mod:
-      return "DW_OP_mod";
-    case DW_OP_mul:
-      return "DW_OP_mul";
-    case DW_OP_neg:
-      return "DW_OP_neg";
-    case DW_OP_not:
-      return "DW_OP_not";
-    case DW_OP_or:
-      return "DW_OP_or";
-    case DW_OP_plus:
-      return "DW_OP_plus";
-    case DW_OP_plus_uconst:
-      return "DW_OP_plus_uconst";
-    case DW_OP_shl:
-      return "DW_OP_shl";
-    case DW_OP_shr:
-      return "DW_OP_shr";
-    case DW_OP_shra:
-      return "DW_OP_shra";
-    case DW_OP_xor:
-      return "DW_OP_xor";
-    case DW_OP_bra:
-      return "DW_OP_bra";
-    case DW_OP_eq:
-      return "DW_OP_eq";
-    case DW_OP_ge:
-      return "DW_OP_ge";
-    case DW_OP_gt:
-      return "DW_OP_gt";
-    case DW_OP_le:
-      return "DW_OP_le";
-    case DW_OP_lt:
-      return "DW_OP_lt";
-    case DW_OP_ne:
-      return "DW_OP_ne";
-    case DW_OP_skip:
-      return "DW_OP_skip";
-    case DW_OP_lit0:
-      return "DW_OP_lit0";
-    case DW_OP_lit1:
-      return "DW_OP_lit1";
-    case DW_OP_lit2:
-      return "DW_OP_lit2";
-    case DW_OP_lit3:
-      return "DW_OP_lit3";
-    case DW_OP_lit4:
-      return "DW_OP_lit4";
-    case DW_OP_lit5:
-      return "DW_OP_lit5";
-    case DW_OP_lit6:
-      return "DW_OP_lit6";
-    case DW_OP_lit7:
-      return "DW_OP_lit7";
-    case DW_OP_lit8:
-      return "DW_OP_lit8";
-    case DW_OP_lit9:
-      return "DW_OP_lit9";
-    case DW_OP_lit10:
-      return "DW_OP_lit10";
-    case DW_OP_lit11:
-      return "DW_OP_lit11";
-    case DW_OP_lit12:
-      return "DW_OP_lit12";
-    case DW_OP_lit13:
-      return "DW_OP_lit13";
-    case DW_OP_lit14:
-      return "DW_OP_lit14";
-    case DW_OP_lit15:
-      return "DW_OP_lit15";
-    case DW_OP_lit16:
-      return "DW_OP_lit16";
-    case DW_OP_lit17:
-      return "DW_OP_lit17";
-    case DW_OP_lit18:
-      return "DW_OP_lit18";
-    case DW_OP_lit19:
-      return "DW_OP_lit19";
-    case DW_OP_lit20:
-      return "DW_OP_lit20";
-    case DW_OP_lit21:
-      return "DW_OP_lit21";
-    case DW_OP_lit22:
-      return "DW_OP_lit22";
-    case DW_OP_lit23:
-      return "DW_OP_lit23";
-    case DW_OP_lit24:
-      return "DW_OP_lit24";
-    case DW_OP_lit25:
-      return "DW_OP_lit25";
-    case DW_OP_lit26:
-      return "DW_OP_lit26";
-    case DW_OP_lit27:
-      return "DW_OP_lit27";
-    case DW_OP_lit28:
-      return "DW_OP_lit28";
-    case DW_OP_lit29:
-      return "DW_OP_lit29";
-    case DW_OP_lit30:
-      return "DW_OP_lit30";
-    case DW_OP_lit31:
-      return "DW_OP_lit31";
-    case DW_OP_reg0:
-      return "DW_OP_reg0";
-    case DW_OP_reg1:
-      return "DW_OP_reg1";
-    case DW_OP_reg2:
-      return "DW_OP_reg2";
-    case DW_OP_reg3:
-      return "DW_OP_reg3";
-    case DW_OP_reg4:
-      return "DW_OP_reg4";
-    case DW_OP_reg5:
-      return "DW_OP_reg5";
-    case DW_OP_reg6:
-      return "DW_OP_reg6";
-    case DW_OP_reg7:
-      return "DW_OP_reg7";
-    case DW_OP_reg8:
-      return "DW_OP_reg8";
-    case DW_OP_reg9:
-      return "DW_OP_reg9";
-    case DW_OP_reg10:
-      return "DW_OP_reg10";
-    case DW_OP_reg11:
-      return "DW_OP_reg11";
-    case DW_OP_reg12:
-      return "DW_OP_reg12";
-    case DW_OP_reg13:
-      return "DW_OP_reg13";
-    case DW_OP_reg14:
-      return "DW_OP_reg14";
-    case DW_OP_reg15:
-      return "DW_OP_reg15";
-    case DW_OP_reg16:
-      return "DW_OP_reg16";
-    case DW_OP_reg17:
-      return "DW_OP_reg17";
-    case DW_OP_reg18:
-      return "DW_OP_reg18";
-    case DW_OP_reg19:
-      return "DW_OP_reg19";
-    case DW_OP_reg20:
-      return "DW_OP_reg20";
-    case DW_OP_reg21:
-      return "DW_OP_reg21";
-    case DW_OP_reg22:
-      return "DW_OP_reg22";
-    case DW_OP_reg23:
-      return "DW_OP_reg23";
-    case DW_OP_reg24:
-      return "DW_OP_reg24";
-    case DW_OP_reg25:
-      return "DW_OP_reg25";
-    case DW_OP_reg26:
-      return "DW_OP_reg26";
-    case DW_OP_reg27:
-      return "DW_OP_reg27";
-    case DW_OP_reg28:
-      return "DW_OP_reg28";
-    case DW_OP_reg29:
-      return "DW_OP_reg29";
-    case DW_OP_reg30:
-      return "DW_OP_reg30";
-    case DW_OP_reg31:
-      return "DW_OP_reg31";
-    case DW_OP_breg0:
-      return "DW_OP_breg0";
-    case DW_OP_breg1:
-      return "DW_OP_breg1";
-    case DW_OP_breg2:
-      return "DW_OP_breg2";
-    case DW_OP_breg3:
-      return "DW_OP_breg3";
-    case DW_OP_breg4:
-      return "DW_OP_breg4";
-    case DW_OP_breg5:
-      return "DW_OP_breg5";
-    case DW_OP_breg6:
-      return "DW_OP_breg6";
-    case DW_OP_breg7:
-      return "DW_OP_breg7";
-    case DW_OP_breg8:
-      return "DW_OP_breg8";
-    case DW_OP_breg9:
-      return "DW_OP_breg9";
-    case DW_OP_breg10:
-      return "DW_OP_breg10";
-    case DW_OP_breg11:
-      return "DW_OP_breg11";
-    case DW_OP_breg12:
-      return "DW_OP_breg12";
-    case DW_OP_breg13:
-      return "DW_OP_breg13";
-    case DW_OP_breg14:
-      return "DW_OP_breg14";
-    case DW_OP_breg15:
-      return "DW_OP_breg15";
-    case DW_OP_breg16:
-      return "DW_OP_breg16";
-    case DW_OP_breg17:
-      return "DW_OP_breg17";
-    case DW_OP_breg18:
-      return "DW_OP_breg18";
-    case DW_OP_breg19:
-      return "DW_OP_breg19";
-    case DW_OP_breg20:
-      return "DW_OP_breg20";
-    case DW_OP_breg21:
-      return "DW_OP_breg21";
-    case DW_OP_breg22:
-      return "DW_OP_breg22";
-    case DW_OP_breg23:
-      return "DW_OP_breg23";
-    case DW_OP_breg24:
-      return "DW_OP_breg24";
-    case DW_OP_breg25:
-      return "DW_OP_breg25";
-    case DW_OP_breg26:
-      return "DW_OP_breg26";
-    case DW_OP_breg27:
-      return "DW_OP_breg27";
-    case DW_OP_breg28:
-      return "DW_OP_breg28";
-    case DW_OP_breg29:
-      return "DW_OP_breg29";
-    case DW_OP_breg30:
-      return "DW_OP_breg30";
-    case DW_OP_breg31:
-      return "DW_OP_breg31";
-    case DW_OP_regx:
-      return "DW_OP_regx";
-    case DW_OP_fbreg:
-      return "DW_OP_fbreg";
-    case DW_OP_bregx:
-      return "DW_OP_bregx";
-    case DW_OP_piece:
-      return "DW_OP_piece";
-    case DW_OP_deref_size:
-      return "DW_OP_deref_size";
-    case DW_OP_xderef_size:
-      return "DW_OP_xderef_size";
-    case DW_OP_nop:
-      return "DW_OP_nop";
+  const char *name = get_DW_OP_name (op);
 
-    case DW_OP_push_object_address:
-      return "DW_OP_push_object_address";
-    case DW_OP_call2:
-      return "DW_OP_call2";
-    case DW_OP_call4:
-      return "DW_OP_call4";
-    case DW_OP_call_ref:
-      return "DW_OP_call_ref";
-    case DW_OP_implicit_value:
-      return "DW_OP_implicit_value";
-    case DW_OP_stack_value:
-      return "DW_OP_stack_value";
-    case DW_OP_form_tls_address:
-      return "DW_OP_form_tls_address";
-    case DW_OP_call_frame_cfa:
-      return "DW_OP_call_frame_cfa";
-    case DW_OP_bit_piece:
-      return "DW_OP_bit_piece";
-
-    case DW_OP_GNU_push_tls_address:
-      return "DW_OP_GNU_push_tls_address";
-    case DW_OP_GNU_uninit:
-      return "DW_OP_GNU_uninit";
-    case DW_OP_GNU_encoded_addr:
-      return "DW_OP_GNU_encoded_addr";
-    case DW_OP_GNU_implicit_pointer:
-      return "DW_OP_GNU_implicit_pointer";
-    case DW_OP_GNU_entry_value:
-      return "DW_OP_GNU_entry_value";
-    case DW_OP_GNU_const_type:
-      return "DW_OP_GNU_const_type";
-    case DW_OP_GNU_regval_type:
-      return "DW_OP_GNU_regval_type";
-    case DW_OP_GNU_deref_type:
-      return "DW_OP_GNU_deref_type";
-    case DW_OP_GNU_convert:
-      return "DW_OP_GNU_convert";
-    case DW_OP_GNU_reinterpret:
-      return "DW_OP_GNU_reinterpret";
-    case DW_OP_GNU_parameter_ref:
-      return "DW_OP_GNU_parameter_ref";
+  if (name != NULL)
+    return name;
 
-    default:
-      return "OP_<unknown>";
-    }
+  return "OP_<unknown>";
 }
 
 /* Return a pointer to a newly allocated location description.  Location
@@ -1586,8 +1271,10 @@ new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1,
 
   descr->dw_loc_opc = op;
   descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
+  descr->dw_loc_oprnd1.val_entry = NULL;
   descr->dw_loc_oprnd1.v.val_unsigned = oprnd1;
   descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const;
+  descr->dw_loc_oprnd2.val_entry = NULL;
   descr->dw_loc_oprnd2.v.val_unsigned = oprnd2;
 
   return descr;
@@ -1652,6 +1339,7 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b)
     case dw_val_class_fde_ref:
       return a->v.val_fde_index == b->v.val_fde_index;
     case dw_val_class_lbl_id:
+    case dw_val_class_high_pc:
       return strcmp (a->v.val_lbl_id, b->v.val_lbl_id) == 0;
     case dw_val_class_str:
       return a->v.val_str == b->v.val_str;
@@ -1791,6 +1479,11 @@ size_of_loc_descr (dw_loc_descr_ref loc)
     case DW_OP_addr:
       size += DWARF2_ADDR_SIZE;
       break;
+    case DW_OP_GNU_addr_index:
+    case DW_OP_GNU_const_index:
+      gcc_assert (loc->dw_loc_oprnd1.val_entry->index != NO_INDEX_ASSIGNED);
+      size += size_of_uleb128 (loc->dw_loc_oprnd1.val_entry->index);
+      break;
     case DW_OP_const1u:
     case DW_OP_const1s:
       size += 1;
@@ -1915,7 +1608,7 @@ size_of_loc_descr (dw_loc_descr_ref loc)
            size += HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT;
            break;
          case dw_val_class_const_double:
-           size += 2 * HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT;
+           size += HOST_BITS_PER_DOUBLE_INT / BITS_PER_UNIT;
            break;
          default:
            gcc_unreachable ();
@@ -2227,6 +1920,13 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
        }
       break;
 
+    case DW_OP_GNU_addr_index:
+    case DW_OP_GNU_const_index:
+      gcc_assert (loc->dw_loc_oprnd1.val_entry->index != NO_INDEX_ASSIGNED);
+      dw2_asm_output_data_uleb128 (loc->dw_loc_oprnd1.val_entry->index,
+                                   "(index into .debug_addr)");
+      break;
+
     case DW_OP_GNU_implicit_pointer:
       {
        char label[MAX_ARTIFICIAL_LABEL_BYTES
@@ -2402,6 +2102,8 @@ output_loc_operands_raw (dw_loc_descr_ref loc)
   switch (loc->dw_loc_opc)
     {
     case DW_OP_addr:
+    case DW_OP_GNU_addr_index:
+    case DW_OP_GNU_const_index:
     case DW_OP_implicit_value:
       /* We cannot output addresses in .cfi_escape, only bytes.  */
       gcc_unreachable ();
@@ -2585,6 +2287,7 @@ build_cfa_loc (dw_cfa_location *cfa, HOST_WIDE_INT offset)
     {
       head = new_reg_loc_descr (cfa->reg, cfa->base_offset);
       head->dw_loc_oprnd1.val_class = dw_val_class_const;
+      head->dw_loc_oprnd1.val_entry = NULL;
       tmp = new_loc_descr (DW_OP_deref, 0, 0);
       add_loc_descr (&head, tmp);
       if (offset != 0)
@@ -2648,6 +2351,7 @@ static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
 static void dwarf2out_abstract_function (tree);
 static void dwarf2out_var_location (rtx);
 static void dwarf2out_begin_function (tree);
+static void dwarf2out_end_function (unsigned int);
 static void dwarf2out_set_name (tree, tree);
 
 /* The debug hooks structure.  */
@@ -2675,7 +2379,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
 #endif
   dwarf2out_end_epilogue,
   dwarf2out_begin_function,
-  debug_nothing_int,           /* end_function */
+  dwarf2out_end_function,      /* end_function */
   dwarf2out_function_decl,     /* function_decl */
   dwarf2out_global_decl,
   dwarf2out_type_decl,         /* type_decl */
@@ -2763,8 +2467,6 @@ typedef struct GTY(()) dw_line_info_struct {
   unsigned int val;
 } dw_line_info_entry;
 
-DEF_VEC_O(dw_line_info_entry);
-DEF_VEC_ALLOC_O(dw_line_info_entry, gc);
 
 typedef struct GTY(()) dw_line_info_table_struct {
   /* The label that marks the end of this section.  */
@@ -2779,13 +2481,11 @@ typedef struct GTY(()) dw_line_info_table_struct {
   bool is_stmt;
   bool in_use;
 
-  VEC(dw_line_info_entry, gc) *entries;
+  vec<dw_line_info_entry, va_gc> *entries;
 } dw_line_info_table;
 
 typedef dw_line_info_table *dw_line_info_table_p;
 
-DEF_VEC_P(dw_line_info_table_p);
-DEF_VEC_ALLOC_P(dw_line_info_table_p, gc);
 
 /* Each DIE attribute has a field specifying the attribute kind,
    a link to the next attribute in the chain, and an attribute value.
@@ -2797,8 +2497,6 @@ typedef struct GTY(()) dw_attr_struct {
 }
 dw_attr_node;
 
-DEF_VEC_O(dw_attr_node);
-DEF_VEC_ALLOC_O(dw_attr_node,gc);
 
 /* The Debugging Information Entry (DIE) structure.  DIEs form a tree.
    The children of each node form a circular list linked by
@@ -2807,11 +2505,11 @@ DEF_VEC_ALLOC_O(dw_attr_node,gc);
 typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
   union die_symbol_or_type_node
     {
-      char * GTY ((tag ("0"))) die_symbol;
+      const char * GTY ((tag ("0"))) die_symbol;
       comdat_type_node_ref GTY ((tag ("1"))) die_type_node;
     }
-  GTY ((desc ("use_debug_types"))) die_id;
-  VEC(dw_attr_node,gc) * die_attr;
+  GTY ((desc ("%0.comdat_type_p"))) die_id;
+  vec<dw_attr_node, va_gc> *die_attr;
   dw_die_ref die_parent;
   dw_die_ref die_child;
   dw_die_ref die_sib;
@@ -2819,10 +2517,12 @@ typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
   dw_offset die_offset;
   unsigned long die_abbrev;
   int die_mark;
-  /* Die is used and must not be pruned as unused.  */
-  int die_perennial_p;
   unsigned int decl_id;
   enum dwarf_tag die_tag;
+  /* Die is used and must not be pruned as unused.  */
+  BOOL_BITFIELD die_perennial_p : 1;
+  BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
+  /* Lots of spare bits.  */
 }
 die_node;
 
@@ -2843,8 +2543,6 @@ typedef struct GTY(()) pubname_struct {
 }
 pubname_entry;
 
-DEF_VEC_O(pubname_entry);
-DEF_VEC_ALLOC_O(pubname_entry, gc);
 
 struct GTY(()) dw_ranges_struct {
   /* If this is positive, it's a block number, otherwise it's a
@@ -2861,8 +2559,6 @@ typedef struct GTY(()) macinfo_struct {
 }
 macinfo_entry;
 
-DEF_VEC_O(macinfo_entry);
-DEF_VEC_ALLOC_O(macinfo_entry, gc);
 
 struct GTY(()) dw_ranges_by_label_struct {
   const char *begin;
@@ -2874,6 +2570,7 @@ typedef struct GTY(()) comdat_type_struct
 {
   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;
 }
@@ -3007,8 +2704,6 @@ typedef struct GTY(()) die_arg_entry_struct {
     tree arg;
 } die_arg_entry;
 
-DEF_VEC_O(die_arg_entry);
-DEF_VEC_ALLOC_O(die_arg_entry,gc);
 
 /* Node of the variable location list.  */
 struct GTY ((chain_next ("%h.next"))) var_loc_node {
@@ -3072,7 +2767,7 @@ static int tail_call_site_count = -1;
 
 /* Vector mapping block numbers to DW_TAG_{lexical_block,inlined_subroutine}
    DIEs.  */
-static VEC (dw_die_ref, heap) *block_map;
+static vec<dw_die_ref> block_map;
 
 /* A cached location list.  */
 struct GTY (()) cached_dw_loc_list_def {
@@ -3116,7 +2811,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, gc) *separate_line_info;
+static GTY(()) vec<dw_line_info_table_p, va_gc> *separate_line_info;
 
 /* A flag to tell pubnames/types export if there is an info section to
    refer to.  */
@@ -3124,21 +2819,21 @@ static bool info_section_emitted;
 
 /* A pointer to the base of a table that contains a list of publicly
    accessible names.  */
-static GTY (()) VEC (pubname_entry, gc) *  pubname_table;
+static GTY (()) vec<pubname_entry, va_gc> *pubname_table;
 
 /* A pointer to the base of a table that contains a list of publicly
    accessible types.  */
-static GTY (()) VEC (pubname_entry, gc) * pubtype_table;
+static GTY (()) vec<pubname_entry, va_gc> *pubtype_table;
 
 /* A pointer to the base of a table that contains a list of macro
    defines/undefines (and file start/end markers).  */
-static GTY (()) VEC (macinfo_entry, gc) * macinfo_table;
+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 \
-   && !VEC_empty (macinfo_entry, macinfo_table))
+   && !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;
@@ -3184,20 +2879,20 @@ 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,gc) *tmpl_value_parm_die_table;
+static GTY(()) vec<die_arg_entry, va_gc> *tmpl_value_parm_die_table;
 
 /* Instances of generic types for which we need to generate debug
    info that describe their generic parameters and arguments. That
    generation needs to happen once all types are properly laid out so
    we do it at the end of compilation.  */
-static GTY(()) VEC(tree,gc) *generic_type_instances;
+static GTY(()) vec<tree, va_gc> *generic_type_instances;
 
 /* Offset from the "steady-state frame pointer" to the frame base,
    within the current function.  */
 static HOST_WIDE_INT frame_pointer_fb_offset;
 static bool frame_pointer_fb_offset_valid;
 
-static VEC (dw_die_ref, heap) *base_types;
+static vec<dw_die_ref> base_types;
 
 /* Forward declarations for functions defined in this file.  */
 
@@ -3211,6 +2906,7 @@ 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_AT_flag (dw_die_ref, enum dwarf_attribute, unsigned);
 static inline unsigned AT_flag (dw_attr_ref);
 static void add_AT_int (dw_die_ref, enum dwarf_attribute, HOST_WIDE_INT);
@@ -3238,7 +2934,9 @@ static inline dw_loc_descr_ref AT_loc (dw_attr_ref);
 static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute,
                             dw_loc_list_ref);
 static inline dw_loc_list_ref AT_loc_list (dw_attr_ref);
-static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx);
+static 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 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 *);
@@ -3246,7 +2944,7 @@ static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *);
 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);
+                               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 const char *get_AT_low_pc (dw_die_ref);
@@ -3327,7 +3025,7 @@ static void htab_cu_del (void *);
 static int check_duplicate_cu (dw_die_ref, htab_t, unsigned *);
 static void record_comdat_symbol_number (dw_die_ref, htab_t, unsigned);
 static void add_sibling_attributes (dw_die_ref);
-static void build_abbrev_table (dw_die_ref);
+static void build_abbrev_table (dw_die_ref, htab_t);
 static void output_location_lists (dw_die_ref);
 static int constant_size (unsigned HOST_WIDE_INT);
 static unsigned long size_of_die (dw_die_ref);
@@ -3336,11 +3034,12 @@ static void calc_base_type_die_sizes (void);
 static void mark_dies (dw_die_ref);
 static void unmark_dies (dw_die_ref);
 static void unmark_all_dies (dw_die_ref);
-static unsigned long size_of_pubnames (VEC (pubname_entry,gc) *);
+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 void output_abbrev_section (void);
+static void output_die_abbrevs (unsigned long, dw_die_ref);
 static void output_die_symbol (dw_die_ref);
 static void output_die (dw_die_ref);
 static void output_compilation_unit_header (void);
@@ -3348,17 +3047,18 @@ static void output_comp_unit (dw_die_ref, int);
 static void output_comdat_type_unit (comdat_type_node *);
 static const char *dwarf2_name (tree, int);
 static void add_pubname (tree, dw_die_ref);
+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,gc) *);
+static void output_pubnames (vec<pubname_entry, va_gc> *);
 static void output_aranges (unsigned long);
 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 *,
-                                 bool *);
+                                  bool *, bool);
 static void output_ranges (void);
 static dw_line_info_table *new_line_info_table (void);
-static void output_line_info (void);
+static void output_line_info (bool);
 static void output_file_names (void);
 static dw_die_ref base_type_die (tree);
 static int is_base_type (tree);
@@ -3477,6 +3177,7 @@ static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *,
                                     const char *, const char *);
 static void output_loc_list (dw_loc_list_ref);
 static char *gen_internal_sym (const char *);
+static bool want_pubnames (void);
 
 static void prune_unmark_dies (dw_die_ref);
 static void prune_unused_types_mark_generic_parms_dies (dw_die_ref);
@@ -3496,36 +3197,124 @@ static bool generic_type_p (tree);
 static void schedule_generic_params_dies_gen (tree t);
 static void gen_scheduled_generic_parms_dies (void);
 
+/* enum for tracking thread-local variables whose address is really an offset
+   relative to the TLS pointer, which will need link-time relocation, but will
+   not need relocation by the DWARF consumer.  */
+
+enum dtprel_bool
+{
+  dtprel_false = 0,
+  dtprel_true = 1
+};
+
+/* Return the operator to use for an address of a variable.  For dtprel_true, we
+   use DW_OP_const*.  For regular variables, which need both link-time
+   relocation and consumer-level relocation (e.g., to account for shared objects
+   loaded at a random address), we use DW_OP_addr*.  */
+
+static inline enum dwarf_location_atom
+dw_addr_op (enum dtprel_bool dtprel)
+{
+  if (dtprel == dtprel_true)
+    return (dwarf_split_debug_info ? DW_OP_GNU_const_index
+            : (DWARF2_ADDR_SIZE == 4 ? DW_OP_const4u : DW_OP_const8u));
+  else
+    return dwarf_split_debug_info ? DW_OP_GNU_addr_index : DW_OP_addr;
+}
+
+/* Return a pointer to a newly allocated address location description.  If
+   dwarf_split_debug_info is true, then record the address with the appropriate
+   relocation.  */
+static inline dw_loc_descr_ref
+new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel)
+{
+  dw_loc_descr_ref ref = new_loc_descr (dw_addr_op (dtprel), 0, 0);
+
+  ref->dw_loc_oprnd1.val_class = dw_val_class_addr;
+  ref->dw_loc_oprnd1.v.val_addr = addr;
+  ref->dtprel = dtprel;
+  if (dwarf_split_debug_info)
+    ref->dw_loc_oprnd1.val_entry
+        = add_addr_table_entry (addr,
+                                dtprel ? ate_kind_rtx_dtprel : ate_kind_rtx);
+  else
+    ref->dw_loc_oprnd1.val_entry = NULL;
+
+  return ref;
+}
+
 /* Section names used to hold DWARF debugging information.  */
+
 #ifndef DEBUG_INFO_SECTION
 #define DEBUG_INFO_SECTION     ".debug_info"
 #endif
+#ifndef DEBUG_DWO_INFO_SECTION
+#define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
+#endif
 #ifndef DEBUG_ABBREV_SECTION
 #define DEBUG_ABBREV_SECTION   ".debug_abbrev"
 #endif
+#ifndef DEBUG_DWO_ABBREV_SECTION
+#define DEBUG_DWO_ABBREV_SECTION ".debug_abbrev.dwo"
+#endif
 #ifndef DEBUG_ARANGES_SECTION
 #define DEBUG_ARANGES_SECTION  ".debug_aranges"
 #endif
+#ifndef DEBUG_ADDR_SECTION
+#define DEBUG_ADDR_SECTION     ".debug_addr"
+#endif
+#ifndef DEBUG_NORM_MACINFO_SECTION
+#define DEBUG_NORM_MACINFO_SECTION     ".debug_macinfo"
+#endif
+#ifndef DEBUG_DWO_MACINFO_SECTION
+#define DEBUG_DWO_MACINFO_SECTION      ".debug_macinfo.dwo"
+#endif
 #ifndef DEBUG_MACINFO_SECTION
-#define DEBUG_MACINFO_SECTION  ".debug_macinfo"
+#define DEBUG_MACINFO_SECTION                                           \
+  (!dwarf_split_debug_info                                              \
+   ? (DEBUG_NORM_MACINFO_SECTION) : (DEBUG_DWO_MACINFO_SECTION))
+#endif
+#ifndef DEBUG_NORM_MACRO_SECTION
+#define DEBUG_NORM_MACRO_SECTION ".debug_macro"
+#endif
+#ifndef DEBUG_DWO_MACRO_SECTION
+#define DEBUG_DWO_MACRO_SECTION        ".debug_macro.dwo"
 #endif
 #ifndef DEBUG_MACRO_SECTION
-#define DEBUG_MACRO_SECTION    ".debug_macro"
+#define DEBUG_MACRO_SECTION                                             \
+  (!dwarf_split_debug_info                                              \
+   ? (DEBUG_NORM_MACRO_SECTION) : (DEBUG_DWO_MACRO_SECTION))
 #endif
 #ifndef DEBUG_LINE_SECTION
 #define DEBUG_LINE_SECTION     ".debug_line"
 #endif
+#ifndef DEBUG_DWO_LINE_SECTION
+#define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
+#endif
 #ifndef DEBUG_LOC_SECTION
 #define DEBUG_LOC_SECTION      ".debug_loc"
 #endif
+#ifndef DEBUG_DWO_LOC_SECTION
+#define DEBUG_DWO_LOC_SECTION  ".debug_loc.dwo"
+#endif
 #ifndef DEBUG_PUBNAMES_SECTION
 #define DEBUG_PUBNAMES_SECTION ".debug_pubnames"
 #endif
 #ifndef DEBUG_PUBTYPES_SECTION
 #define DEBUG_PUBTYPES_SECTION ".debug_pubtypes"
 #endif
+#define DEBUG_NORM_STR_OFFSETS_SECTION ".debug_str_offsets"
+#define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo"
+#ifndef DEBUG_STR_OFFSETS_SECTION
+#define DEBUG_STR_OFFSETS_SECTION                                       \
+  (!dwarf_split_debug_info                                              \
+   ? (DEBUG_NORM_STR_OFFSETS_SECTION) : (DEBUG_DWO_STR_OFFSETS_SECTION))
+#endif
+#define DEBUG_DWO_STR_SECTION   ".debug_str.dwo"
+#define DEBUG_NORM_STR_SECTION  ".debug_str"
 #ifndef DEBUG_STR_SECTION
-#define DEBUG_STR_SECTION      ".debug_str"
+#define DEBUG_STR_SECTION                               \
+  (!dwarf_split_debug_info ? (DEBUG_NORM_STR_SECTION) : (DEBUG_DWO_STR_SECTION))
 #endif
 #ifndef DEBUG_RANGES_SECTION
 #define DEBUG_RANGES_SECTION   ".debug_ranges"
@@ -3536,43 +3325,62 @@ static void gen_scheduled_generic_parms_dies (void);
 #define TEXT_SECTION_NAME      ".text"
 #endif
 
+/* Section flags for .debug_macinfo/.debug_macro section.  */
+#define DEBUG_MACRO_SECTION_FLAGS \
+  (dwarf_split_debug_info ? SECTION_DEBUG | SECTION_EXCLUDE : SECTION_DEBUG)
+
 /* Section flags for .debug_str section.  */
 #define DEBUG_STR_SECTION_FLAGS \
-  (HAVE_GAS_SHF_MERGE && flag_merge_debug_strings              \
-   ? SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1       \
-   : SECTION_DEBUG)
+  (dwarf_split_debug_info \
+   ? SECTION_DEBUG | SECTION_EXCLUDE \
+   : (HAVE_GAS_SHF_MERGE && flag_merge_debug_strings \
+      ? SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1        \
+      : SECTION_DEBUG))
 
 /* Labels we insert at beginning sections we can reference instead of
    the section names themselves.  */
 
 #ifndef TEXT_SECTION_LABEL
-#define TEXT_SECTION_LABEL             "Ltext"
+#define TEXT_SECTION_LABEL                 "Ltext"
 #endif
 #ifndef COLD_TEXT_SECTION_LABEL
-#define COLD_TEXT_SECTION_LABEL         "Ltext_cold"
+#define COLD_TEXT_SECTION_LABEL             "Ltext_cold"
 #endif
 #ifndef DEBUG_LINE_SECTION_LABEL
-#define DEBUG_LINE_SECTION_LABEL       "Ldebug_line"
+#define DEBUG_LINE_SECTION_LABEL           "Ldebug_line"
+#endif
+#ifndef DEBUG_SKELETON_LINE_SECTION_LABEL
+#define DEBUG_SKELETON_LINE_SECTION_LABEL   "Lskeleton_debug_line"
 #endif
 #ifndef DEBUG_INFO_SECTION_LABEL
-#define DEBUG_INFO_SECTION_LABEL       "Ldebug_info"
+#define DEBUG_INFO_SECTION_LABEL           "Ldebug_info"
+#endif
+#ifndef DEBUG_SKELETON_INFO_SECTION_LABEL
+#define DEBUG_SKELETON_INFO_SECTION_LABEL   "Lskeleton_debug_info"
 #endif
 #ifndef DEBUG_ABBREV_SECTION_LABEL
-#define DEBUG_ABBREV_SECTION_LABEL     "Ldebug_abbrev"
+#define DEBUG_ABBREV_SECTION_LABEL         "Ldebug_abbrev"
+#endif
+#ifndef DEBUG_SKELETON_ABBREV_SECTION_LABEL
+#define DEBUG_SKELETON_ABBREV_SECTION_LABEL "Lskeleton_debug_abbrev"
+#endif
+#ifndef DEBUG_ADDR_SECTION_LABEL
+#define DEBUG_ADDR_SECTION_LABEL           "Ldebug_addr"
 #endif
 #ifndef DEBUG_LOC_SECTION_LABEL
-#define DEBUG_LOC_SECTION_LABEL                "Ldebug_loc"
+#define DEBUG_LOC_SECTION_LABEL                    "Ldebug_loc"
 #endif
 #ifndef DEBUG_RANGES_SECTION_LABEL
-#define DEBUG_RANGES_SECTION_LABEL     "Ldebug_ranges"
+#define DEBUG_RANGES_SECTION_LABEL         "Ldebug_ranges"
 #endif
 #ifndef DEBUG_MACINFO_SECTION_LABEL
-#define DEBUG_MACINFO_SECTION_LABEL     "Ldebug_macinfo"
+#define DEBUG_MACINFO_SECTION_LABEL         "Ldebug_macinfo"
 #endif
 #ifndef DEBUG_MACRO_SECTION_LABEL
-#define DEBUG_MACRO_SECTION_LABEL      "Ldebug_macro"
+#define DEBUG_MACRO_SECTION_LABEL          "Ldebug_macro"
 #endif
-
+#define SKELETON_COMP_DIE_ABBREV 1
+#define SKELETON_TYPE_DIE_ABBREV 2
 
 /* Definitions of defaults for formats and names of various special
    (artificial) labels which may be generated within this file (when the -g
@@ -3586,7 +3394,11 @@ static char cold_text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char cold_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_skeleton_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_skeleton_abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_addr_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_skeleton_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
@@ -3706,155 +3518,12 @@ get_ref_die_offset (dw_die_ref ref)
 static const char *
 dwarf_tag_name (unsigned int tag)
 {
-  switch (tag)
-    {
-    case DW_TAG_padding:
-      return "DW_TAG_padding";
-    case DW_TAG_array_type:
-      return "DW_TAG_array_type";
-    case DW_TAG_class_type:
-      return "DW_TAG_class_type";
-    case DW_TAG_entry_point:
-      return "DW_TAG_entry_point";
-    case DW_TAG_enumeration_type:
-      return "DW_TAG_enumeration_type";
-    case DW_TAG_formal_parameter:
-      return "DW_TAG_formal_parameter";
-    case DW_TAG_imported_declaration:
-      return "DW_TAG_imported_declaration";
-    case DW_TAG_label:
-      return "DW_TAG_label";
-    case DW_TAG_lexical_block:
-      return "DW_TAG_lexical_block";
-    case DW_TAG_member:
-      return "DW_TAG_member";
-    case DW_TAG_pointer_type:
-      return "DW_TAG_pointer_type";
-    case DW_TAG_reference_type:
-      return "DW_TAG_reference_type";
-    case DW_TAG_compile_unit:
-      return "DW_TAG_compile_unit";
-    case DW_TAG_string_type:
-      return "DW_TAG_string_type";
-    case DW_TAG_structure_type:
-      return "DW_TAG_structure_type";
-    case DW_TAG_subroutine_type:
-      return "DW_TAG_subroutine_type";
-    case DW_TAG_typedef:
-      return "DW_TAG_typedef";
-    case DW_TAG_union_type:
-      return "DW_TAG_union_type";
-    case DW_TAG_unspecified_parameters:
-      return "DW_TAG_unspecified_parameters";
-    case DW_TAG_variant:
-      return "DW_TAG_variant";
-    case DW_TAG_common_block:
-      return "DW_TAG_common_block";
-    case DW_TAG_common_inclusion:
-      return "DW_TAG_common_inclusion";
-    case DW_TAG_inheritance:
-      return "DW_TAG_inheritance";
-    case DW_TAG_inlined_subroutine:
-      return "DW_TAG_inlined_subroutine";
-    case DW_TAG_module:
-      return "DW_TAG_module";
-    case DW_TAG_ptr_to_member_type:
-      return "DW_TAG_ptr_to_member_type";
-    case DW_TAG_set_type:
-      return "DW_TAG_set_type";
-    case DW_TAG_subrange_type:
-      return "DW_TAG_subrange_type";
-    case DW_TAG_with_stmt:
-      return "DW_TAG_with_stmt";
-    case DW_TAG_access_declaration:
-      return "DW_TAG_access_declaration";
-    case DW_TAG_base_type:
-      return "DW_TAG_base_type";
-    case DW_TAG_catch_block:
-      return "DW_TAG_catch_block";
-    case DW_TAG_const_type:
-      return "DW_TAG_const_type";
-    case DW_TAG_constant:
-      return "DW_TAG_constant";
-    case DW_TAG_enumerator:
-      return "DW_TAG_enumerator";
-    case DW_TAG_file_type:
-      return "DW_TAG_file_type";
-    case DW_TAG_friend:
-      return "DW_TAG_friend";
-    case DW_TAG_namelist:
-      return "DW_TAG_namelist";
-    case DW_TAG_namelist_item:
-      return "DW_TAG_namelist_item";
-    case DW_TAG_packed_type:
-      return "DW_TAG_packed_type";
-    case DW_TAG_subprogram:
-      return "DW_TAG_subprogram";
-    case DW_TAG_template_type_param:
-      return "DW_TAG_template_type_param";
-    case DW_TAG_template_value_param:
-      return "DW_TAG_template_value_param";
-    case DW_TAG_thrown_type:
-      return "DW_TAG_thrown_type";
-    case DW_TAG_try_block:
-      return "DW_TAG_try_block";
-    case DW_TAG_variant_part:
-      return "DW_TAG_variant_part";
-    case DW_TAG_variable:
-      return "DW_TAG_variable";
-    case DW_TAG_volatile_type:
-      return "DW_TAG_volatile_type";
-    case DW_TAG_dwarf_procedure:
-      return "DW_TAG_dwarf_procedure";
-    case DW_TAG_restrict_type:
-      return "DW_TAG_restrict_type";
-    case DW_TAG_interface_type:
-      return "DW_TAG_interface_type";
-    case DW_TAG_namespace:
-      return "DW_TAG_namespace";
-    case DW_TAG_imported_module:
-      return "DW_TAG_imported_module";
-    case DW_TAG_unspecified_type:
-      return "DW_TAG_unspecified_type";
-    case DW_TAG_partial_unit:
-      return "DW_TAG_partial_unit";
-    case DW_TAG_imported_unit:
-      return "DW_TAG_imported_unit";
-    case DW_TAG_condition:
-      return "DW_TAG_condition";
-    case DW_TAG_shared_type:
-      return "DW_TAG_shared_type";
-    case DW_TAG_type_unit:
-      return "DW_TAG_type_unit";
-    case DW_TAG_rvalue_reference_type:
-      return "DW_TAG_rvalue_reference_type";
-    case DW_TAG_template_alias:
-      return "DW_TAG_template_alias";
-    case DW_TAG_GNU_template_parameter_pack:
-      return "DW_TAG_GNU_template_parameter_pack";
-    case DW_TAG_GNU_formal_parameter_pack:
-      return "DW_TAG_GNU_formal_parameter_pack";
-    case DW_TAG_MIPS_loop:
-      return "DW_TAG_MIPS_loop";
-    case DW_TAG_format_label:
-      return "DW_TAG_format_label";
-    case DW_TAG_function_template:
-      return "DW_TAG_function_template";
-    case DW_TAG_class_template:
-      return "DW_TAG_class_template";
-    case DW_TAG_GNU_BINCL:
-      return "DW_TAG_GNU_BINCL";
-    case DW_TAG_GNU_EINCL:
-      return "DW_TAG_GNU_EINCL";
-    case DW_TAG_GNU_template_template_param:
-      return "DW_TAG_GNU_template_template_param";
-    case DW_TAG_GNU_call_site:
-      return "DW_TAG_GNU_call_site";
-    case DW_TAG_GNU_call_site_parameter:
-      return "DW_TAG_GNU_call_site_parameter";
-    default:
-      return "DW_TAG_<unknown>";
-    }
+  const char *name = get_DW_TAG_name (tag);
+
+  if (name != NULL)
+    return name;
+
+  return "DW_TAG_<unknown>";
 }
 
 /* Convert a DWARF attribute code into its string name.  */
@@ -3862,183 +3531,10 @@ dwarf_tag_name (unsigned int tag)
 static const char *
 dwarf_attr_name (unsigned int attr)
 {
+  const char *name;
+
   switch (attr)
     {
-    case DW_AT_sibling:
-      return "DW_AT_sibling";
-    case DW_AT_location:
-      return "DW_AT_location";
-    case DW_AT_name:
-      return "DW_AT_name";
-    case DW_AT_ordering:
-      return "DW_AT_ordering";
-    case DW_AT_subscr_data:
-      return "DW_AT_subscr_data";
-    case DW_AT_byte_size:
-      return "DW_AT_byte_size";
-    case DW_AT_bit_offset:
-      return "DW_AT_bit_offset";
-    case DW_AT_bit_size:
-      return "DW_AT_bit_size";
-    case DW_AT_element_list:
-      return "DW_AT_element_list";
-    case DW_AT_stmt_list:
-      return "DW_AT_stmt_list";
-    case DW_AT_low_pc:
-      return "DW_AT_low_pc";
-    case DW_AT_high_pc:
-      return "DW_AT_high_pc";
-    case DW_AT_language:
-      return "DW_AT_language";
-    case DW_AT_member:
-      return "DW_AT_member";
-    case DW_AT_discr:
-      return "DW_AT_discr";
-    case DW_AT_discr_value:
-      return "DW_AT_discr_value";
-    case DW_AT_visibility:
-      return "DW_AT_visibility";
-    case DW_AT_import:
-      return "DW_AT_import";
-    case DW_AT_string_length:
-      return "DW_AT_string_length";
-    case DW_AT_common_reference:
-      return "DW_AT_common_reference";
-    case DW_AT_comp_dir:
-      return "DW_AT_comp_dir";
-    case DW_AT_const_value:
-      return "DW_AT_const_value";
-    case DW_AT_containing_type:
-      return "DW_AT_containing_type";
-    case DW_AT_default_value:
-      return "DW_AT_default_value";
-    case DW_AT_inline:
-      return "DW_AT_inline";
-    case DW_AT_is_optional:
-      return "DW_AT_is_optional";
-    case DW_AT_lower_bound:
-      return "DW_AT_lower_bound";
-    case DW_AT_producer:
-      return "DW_AT_producer";
-    case DW_AT_prototyped:
-      return "DW_AT_prototyped";
-    case DW_AT_return_addr:
-      return "DW_AT_return_addr";
-    case DW_AT_start_scope:
-      return "DW_AT_start_scope";
-    case DW_AT_bit_stride:
-      return "DW_AT_bit_stride";
-    case DW_AT_upper_bound:
-      return "DW_AT_upper_bound";
-    case DW_AT_abstract_origin:
-      return "DW_AT_abstract_origin";
-    case DW_AT_accessibility:
-      return "DW_AT_accessibility";
-    case DW_AT_address_class:
-      return "DW_AT_address_class";
-    case DW_AT_artificial:
-      return "DW_AT_artificial";
-    case DW_AT_base_types:
-      return "DW_AT_base_types";
-    case DW_AT_calling_convention:
-      return "DW_AT_calling_convention";
-    case DW_AT_count:
-      return "DW_AT_count";
-    case DW_AT_data_member_location:
-      return "DW_AT_data_member_location";
-    case DW_AT_decl_column:
-      return "DW_AT_decl_column";
-    case DW_AT_decl_file:
-      return "DW_AT_decl_file";
-    case DW_AT_decl_line:
-      return "DW_AT_decl_line";
-    case DW_AT_declaration:
-      return "DW_AT_declaration";
-    case DW_AT_discr_list:
-      return "DW_AT_discr_list";
-    case DW_AT_encoding:
-      return "DW_AT_encoding";
-    case DW_AT_external:
-      return "DW_AT_external";
-    case DW_AT_explicit:
-      return "DW_AT_explicit";
-    case DW_AT_frame_base:
-      return "DW_AT_frame_base";
-    case DW_AT_friend:
-      return "DW_AT_friend";
-    case DW_AT_identifier_case:
-      return "DW_AT_identifier_case";
-    case DW_AT_macro_info:
-      return "DW_AT_macro_info";
-    case DW_AT_namelist_items:
-      return "DW_AT_namelist_items";
-    case DW_AT_priority:
-      return "DW_AT_priority";
-    case DW_AT_segment:
-      return "DW_AT_segment";
-    case DW_AT_specification:
-      return "DW_AT_specification";
-    case DW_AT_static_link:
-      return "DW_AT_static_link";
-    case DW_AT_type:
-      return "DW_AT_type";
-    case DW_AT_use_location:
-      return "DW_AT_use_location";
-    case DW_AT_variable_parameter:
-      return "DW_AT_variable_parameter";
-    case DW_AT_virtuality:
-      return "DW_AT_virtuality";
-    case DW_AT_vtable_elem_location:
-      return "DW_AT_vtable_elem_location";
-
-    case DW_AT_allocated:
-      return "DW_AT_allocated";
-    case DW_AT_associated:
-      return "DW_AT_associated";
-    case DW_AT_data_location:
-      return "DW_AT_data_location";
-    case DW_AT_byte_stride:
-      return "DW_AT_byte_stride";
-    case DW_AT_entry_pc:
-      return "DW_AT_entry_pc";
-    case DW_AT_use_UTF8:
-      return "DW_AT_use_UTF8";
-    case DW_AT_extension:
-      return "DW_AT_extension";
-    case DW_AT_ranges:
-      return "DW_AT_ranges";
-    case DW_AT_trampoline:
-      return "DW_AT_trampoline";
-    case DW_AT_call_column:
-      return "DW_AT_call_column";
-    case DW_AT_call_file:
-      return "DW_AT_call_file";
-    case DW_AT_call_line:
-      return "DW_AT_call_line";
-    case DW_AT_object_pointer:
-      return "DW_AT_object_pointer";
-
-    case DW_AT_signature:
-      return "DW_AT_signature";
-    case DW_AT_main_subprogram:
-      return "DW_AT_main_subprogram";
-    case DW_AT_data_bit_offset:
-      return "DW_AT_data_bit_offset";
-    case DW_AT_const_expr:
-      return "DW_AT_const_expr";
-    case DW_AT_enum_class:
-      return "DW_AT_enum_class";
-    case DW_AT_linkage_name:
-      return "DW_AT_linkage_name";
-
-    case DW_AT_MIPS_fde:
-      return "DW_AT_MIPS_fde";
-    case DW_AT_MIPS_loop_begin:
-      return "DW_AT_MIPS_loop_begin";
-    case DW_AT_MIPS_tail_loop_begin:
-      return "DW_AT_MIPS_tail_loop_begin";
-    case DW_AT_MIPS_epilog_begin:
-      return "DW_AT_MIPS_epilog_begin";
 #if VMS_DEBUGGING_INFO
     case DW_AT_HP_prologue:
       return "DW_AT_HP_prologue";
@@ -4046,10 +3542,7 @@ dwarf_attr_name (unsigned int attr)
     case DW_AT_MIPS_loop_unroll_factor:
       return "DW_AT_MIPS_loop_unroll_factor";
 #endif
-    case DW_AT_MIPS_software_pipeline_depth:
-      return "DW_AT_MIPS_software_pipeline_depth";
-    case DW_AT_MIPS_linkage_name:
-      return "DW_AT_MIPS_linkage_name";
+
 #if VMS_DEBUGGING_INFO
     case DW_AT_HP_epilogue:
       return "DW_AT_HP_epilogue";
@@ -4057,74 +3550,14 @@ dwarf_attr_name (unsigned int attr)
     case DW_AT_MIPS_stride:
       return "DW_AT_MIPS_stride";
 #endif
-    case DW_AT_MIPS_abstract_name:
-      return "DW_AT_MIPS_abstract_name";
-    case DW_AT_MIPS_clone_origin:
-      return "DW_AT_MIPS_clone_origin";
-    case DW_AT_MIPS_has_inlines:
-      return "DW_AT_MIPS_has_inlines";
-
-    case DW_AT_sf_names:
-      return "DW_AT_sf_names";
-    case DW_AT_src_info:
-      return "DW_AT_src_info";
-    case DW_AT_mac_info:
-      return "DW_AT_mac_info";
-    case DW_AT_src_coords:
-      return "DW_AT_src_coords";
-    case DW_AT_body_begin:
-      return "DW_AT_body_begin";
-    case DW_AT_body_end:
-      return "DW_AT_body_end";
-
-    case DW_AT_GNU_vector:
-      return "DW_AT_GNU_vector";
-    case DW_AT_GNU_guarded_by:
-      return "DW_AT_GNU_guarded_by";
-    case DW_AT_GNU_pt_guarded_by:
-      return "DW_AT_GNU_pt_guarded_by";
-    case DW_AT_GNU_guarded:
-      return "DW_AT_GNU_guarded";
-    case DW_AT_GNU_pt_guarded:
-      return "DW_AT_GNU_pt_guarded";
-    case DW_AT_GNU_locks_excluded:
-      return "DW_AT_GNU_locks_excluded";
-    case DW_AT_GNU_exclusive_locks_required:
-      return "DW_AT_GNU_exclusive_locks_required";
-    case DW_AT_GNU_shared_locks_required:
-      return "DW_AT_GNU_shared_locks_required";
-    case DW_AT_GNU_odr_signature:
-      return "DW_AT_GNU_odr_signature";
-    case DW_AT_GNU_template_name:
-      return "DW_AT_GNU_template_name";
-    case DW_AT_GNU_call_site_value:
-      return "DW_AT_GNU_call_site_value";
-    case DW_AT_GNU_call_site_data_value:
-      return "DW_AT_GNU_call_site_data_value";
-    case DW_AT_GNU_call_site_target:
-      return "DW_AT_GNU_call_site_target";
-    case DW_AT_GNU_call_site_target_clobbered:
-      return "DW_AT_GNU_call_site_target_clobbered";
-    case DW_AT_GNU_tail_call:
-      return "DW_AT_GNU_tail_call";
-    case DW_AT_GNU_all_tail_call_sites:
-      return "DW_AT_GNU_all_tail_call_sites";
-    case DW_AT_GNU_all_call_sites:
-      return "DW_AT_GNU_all_call_sites";
-    case DW_AT_GNU_all_source_call_sites:
-      return "DW_AT_GNU_all_source_call_sites";
-    case DW_AT_GNU_macros:
-      return "DW_AT_GNU_macros";
-
-    case DW_AT_GNAT_descriptive_type:
-      return "DW_AT_GNAT_descriptive_type";
-
-    case DW_AT_VMS_rtnbeg_pd_address:
-      return "DW_AT_VMS_rtnbeg_pd_address";
-
-    default:
-      return "DW_AT_<unknown>";
     }
+
+  name = get_DW_AT_name (attr);
+
+  if (name != NULL)
+    return name;
+
+  return "DW_AT_<unknown>";
 }
 
 /* Convert a DWARF value form code into its string name.  */
@@ -4132,61 +3565,12 @@ dwarf_attr_name (unsigned int attr)
 static const char *
 dwarf_form_name (unsigned int form)
 {
-  switch (form)
-    {
-    case DW_FORM_addr:
-      return "DW_FORM_addr";
-    case DW_FORM_block2:
-      return "DW_FORM_block2";
-    case DW_FORM_block4:
-      return "DW_FORM_block4";
-    case DW_FORM_data2:
-      return "DW_FORM_data2";
-    case DW_FORM_data4:
-      return "DW_FORM_data4";
-    case DW_FORM_data8:
-      return "DW_FORM_data8";
-    case DW_FORM_string:
-      return "DW_FORM_string";
-    case DW_FORM_block:
-      return "DW_FORM_block";
-    case DW_FORM_block1:
-      return "DW_FORM_block1";
-    case DW_FORM_data1:
-      return "DW_FORM_data1";
-    case DW_FORM_flag:
-      return "DW_FORM_flag";
-    case DW_FORM_sdata:
-      return "DW_FORM_sdata";
-    case DW_FORM_strp:
-      return "DW_FORM_strp";
-    case DW_FORM_udata:
-      return "DW_FORM_udata";
-    case DW_FORM_ref_addr:
-      return "DW_FORM_ref_addr";
-    case DW_FORM_ref1:
-      return "DW_FORM_ref1";
-    case DW_FORM_ref2:
-      return "DW_FORM_ref2";
-    case DW_FORM_ref4:
-      return "DW_FORM_ref4";
-    case DW_FORM_ref8:
-      return "DW_FORM_ref8";
-    case DW_FORM_ref_udata:
-      return "DW_FORM_ref_udata";
-    case DW_FORM_indirect:
-      return "DW_FORM_indirect";
-    case DW_FORM_sec_offset:
-      return "DW_FORM_sec_offset";
-    case DW_FORM_exprloc:
-      return "DW_FORM_exprloc";
-    case DW_FORM_flag_present:
-      return "DW_FORM_flag_present";
-    case DW_FORM_ref_sig8:
-      return "DW_FORM_ref_sig8";
-    default:
-      return "DW_FORM_<unknown>";
-    }
+  const char *name = get_DW_FORM_name (form);
+
+  if (name != NULL)
+    return name;
+
+  return "DW_FORM_<unknown>";
 }
 \f
 /* Determine the "ultimate origin" of a decl.  The decl may be an inlined
@@ -4244,9 +3628,8 @@ add_dwarf_attr (dw_die_ref die, dw_attr_ref attr)
   if (die == NULL)
     return;
 
-  if (die->die_attr == NULL)
-    die->die_attr = VEC_alloc (dw_attr_node, gc, 1);
-  VEC_safe_push (dw_attr_node, gc, die->die_attr, attr);
+  vec_safe_reserve (die->die_attr, 1);
+  vec_safe_push (die->die_attr, *attr);
 }
 
 static inline enum dw_val_class
@@ -4255,6 +3638,21 @@ AT_class (dw_attr_ref a)
   return a->dw_attr_val.val_class;
 }
 
+/* Return the index for any attribute that will be referenced with a
+   DW_FORM_GNU_addr_index or DW_FORM_GNU_str_index.  String indices
+   are stored in dw_attr_val.v.val_str for reference counting
+   pruning.  */
+
+static inline unsigned int
+AT_index (dw_attr_ref a)
+{
+  if (AT_class (a) == dw_val_class_str)
+    return a->dw_attr_val.v.val_str->index;
+  else if (a->dw_attr_val.val_entry != NULL)
+    return a->dw_attr_val.val_entry->index;
+  return NOT_INDEXED;
+}
+
 /* Add a flag value attribute to a DIE.  */
 
 static inline void
@@ -4264,6 +3662,7 @@ add_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int flag)
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_flag;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_flag = flag;
   add_dwarf_attr (die, &attr);
 }
@@ -4284,6 +3683,7 @@ add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, HOST_WIDE_INT int_va
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_const;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_int = int_val;
   add_dwarf_attr (die, &attr);
 }
@@ -4305,6 +3705,7 @@ add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind,
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_unsigned_const;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_unsigned = unsigned_val;
   add_dwarf_attr (die, &attr);
 }
@@ -4326,6 +3727,7 @@ add_AT_double (dw_die_ref die, enum dwarf_attribute attr_kind,
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_const_double;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_double.high = high;
   attr.dw_attr_val.v.val_double.low = low;
   add_dwarf_attr (die, &attr);
@@ -4341,6 +3743,7 @@ add_AT_vec (dw_die_ref die, enum dwarf_attribute attr_kind,
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_vec;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_vec.length = length;
   attr.dw_attr_val.v.val_vec.elt_size = elt_size;
   attr.dw_attr_val.v.val_vec.array = array;
@@ -4357,10 +3760,50 @@ add_AT_data8 (dw_die_ref die, enum dwarf_attribute attr_kind,
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_data8;
+  attr.dw_attr_val.val_entry = NULL;
   memcpy (attr.dw_attr_val.v.val_data8, data8, 8);
   add_dwarf_attr (die, &attr);
 }
 
+/* Add DW_AT_low_pc and DW_AT_high_pc to a DIE.  When using
+   dwarf_split_debug_info, address attributes in dies destined for the
+   final executable have force_direct set to avoid using indexed
+   references.  */
+
+static inline void
+add_AT_low_high_pc (dw_die_ref die, const char *lbl_low, const char *lbl_high,
+                    bool force_direct)
+{
+  dw_attr_node attr;
+  char * lbl_id;
+
+  lbl_id = xstrdup (lbl_low);
+  attr.dw_attr = DW_AT_low_pc;
+  attr.dw_attr_val.val_class = dw_val_class_lbl_id;
+  attr.dw_attr_val.v.val_lbl_id = lbl_id;
+  if (dwarf_split_debug_info && !force_direct)
+    attr.dw_attr_val.val_entry
+        = add_addr_table_entry (lbl_id, ate_kind_label);
+  else
+    attr.dw_attr_val.val_entry = NULL;
+  add_dwarf_attr (die, &attr);
+
+  attr.dw_attr = DW_AT_high_pc;
+  if (dwarf_version < 4)
+    attr.dw_attr_val.val_class = dw_val_class_lbl_id;
+  else
+    attr.dw_attr_val.val_class = dw_val_class_high_pc;
+  lbl_id = xstrdup (lbl_high);
+  attr.dw_attr_val.v.val_lbl_id = lbl_id;
+  if (attr.dw_attr_val.val_class == dw_val_class_lbl_id
+      && dwarf_split_debug_info && !force_direct)
+    attr.dw_attr_val.val_entry
+        = add_addr_table_entry (lbl_id, ate_kind_label);
+  else
+    attr.dw_attr_val.val_entry = NULL;
+  add_dwarf_attr (die, &attr);
+}
+
 /* Hash and equality functions for debug_str_hash.  */
 
 static hashval_t
@@ -4415,6 +3858,7 @@ add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str)
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_str;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_str = node;
   add_dwarf_attr (die, &attr);
 }
@@ -4426,19 +3870,43 @@ AT_string (dw_attr_ref a)
   return a->dw_attr_val.v.val_str->str;
 }
 
+/* Call this function directly to bypass AT_string_form's logic to put
+   the string inline in the die. */
+
+static void
+set_indirect_string (struct indirect_string_node *node)
+{
+  char label[32];
+  /* Already indirect is a no op.  */
+  if (node->form == DW_FORM_strp || node->form == DW_FORM_GNU_str_index)
+    {
+      gcc_assert (node->label);
+      return;
+    }
+  ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
+  ++dw2_string_counter;
+  node->label = xstrdup (label);
+
+  if (!dwarf_split_debug_info)
+    {
+      node->form = DW_FORM_strp;
+      node->index = NOT_INDEXED;
+    }
+  else
+    {
+      node->form = DW_FORM_GNU_str_index;
+      node->index = NO_INDEX_ASSIGNED;
+    }
+}
+
 /* Find out whether a string should be output inline in DIE
    or out-of-line in .debug_str section.  */
 
 static enum dwarf_form
-AT_string_form (dw_attr_ref a)
+find_string_form (struct indirect_string_node *node)
 {
-  struct indirect_string_node *node;
   unsigned int len;
-  char label[32];
 
-  gcc_assert (a && AT_class (a) == dw_val_class_str);
-
-  node = a->dw_attr_val.v.val_str;
   if (node->form)
     return node->form;
 
@@ -4457,11 +3925,19 @@ AT_string_form (dw_attr_ref a)
       && (len - DWARF_OFFSET_SIZE) * node->refcount <= len))
     return node->form = DW_FORM_string;
 
-  ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
-  ++dw2_string_counter;
-  node->label = xstrdup (label);
+  set_indirect_string (node);
 
-  return node->form = DW_FORM_strp;
+  return node->form;
+}
+
+/* Find out whether the string referenced from the attribute should be
+   output inline in DIE or out-of-line in .debug_str section.  */
+
+static enum dwarf_form
+AT_string_form (dw_attr_ref a)
+{
+  gcc_assert (a && AT_class (a) == dw_val_class_str);
+  return find_string_form (a->dw_attr_val.v.val_str);
 }
 
 /* Add a DIE reference attribute value to a DIE.  */
@@ -4482,11 +3958,22 @@ add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_die_ref;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_die_ref.die = targ_die;
   attr.dw_attr_val.v.val_die_ref.external = 0;
   add_dwarf_attr (die, &attr);
 }
 
+/* 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)
+{
+  gcc_assert (ref->dw_attr_val.val_class == dw_val_class_die_ref);
+  ref->dw_attr_val.v.val_die_ref.die = new_die;
+  ref->dw_attr_val.v.val_die_ref.external = 0;
+}
+
 /* Add an AT_specification attribute to a DIE, and also make the back
    pointer from the specification to the definition.  */
 
@@ -4530,6 +4017,7 @@ add_AT_fde_ref (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int tar
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_fde_ref;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_fde_index = targ_fde;
   add_dwarf_attr (die, &attr);
 }
@@ -4543,6 +4031,7 @@ add_AT_loc (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_descr_ref loc
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_loc;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_loc = loc;
   add_dwarf_attr (die, &attr);
 }
@@ -4561,6 +4050,7 @@ add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_loc_list;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_loc_list = loc_list;
   add_dwarf_attr (die, &attr);
   have_location_lists = true;
@@ -4580,16 +4070,173 @@ AT_loc_list_ptr (dw_attr_ref a)
   return &a->dw_attr_val.v.val_loc_list;
 }
 
-/* Add an address constant attribute value to a DIE.  */
+/* Table of entries into the .debug_addr section.  */
+
+static GTY ((param_is (addr_table_entry))) htab_t addr_index_table;
+
+/* Hash an address_table_entry.  */
+
+static hashval_t
+addr_table_entry_do_hash (const void *x)
+{
+  const addr_table_entry *a = (const addr_table_entry *) x;
+  switch (a->kind)
+    {
+      case ate_kind_rtx:
+        return iterative_hash_rtx (a->addr.rtl, 0);
+      case ate_kind_rtx_dtprel:
+        return iterative_hash_rtx (a->addr.rtl, 1);
+      case ate_kind_label:
+        return htab_hash_string (a->addr.label);
+      default:
+        gcc_unreachable ();
+    }
+}
+
+/* Determine equality for two address_table_entries.  */
+
+static int
+addr_table_entry_eq (const void *x1, const void *x2)
+{
+  const addr_table_entry *a1 = (const addr_table_entry *) x1;
+  const addr_table_entry *a2 = (const addr_table_entry *) x2;
+
+  if (a1->kind != a2->kind)
+    return 0;
+  switch (a1->kind)
+    {
+      case ate_kind_rtx:
+      case ate_kind_rtx_dtprel:
+        return rtx_equal_p (a1->addr.rtl, a2->addr.rtl);
+      case ate_kind_label:
+        return strcmp (a1->addr.label, a2->addr.label) == 0;
+      default:
+        gcc_unreachable ();
+    }
+}
+
+/* Initialize an addr_table_entry.  */
+
+void
+init_addr_table_entry (addr_table_entry *e, enum ate_kind kind, void *addr)
+{
+  e->kind = kind;
+  switch (kind)
+    {
+      case ate_kind_rtx:
+      case ate_kind_rtx_dtprel:
+        e->addr.rtl = (rtx) addr;
+        break;
+      case ate_kind_label:
+        e->addr.label = (char *) addr;
+        break;
+    }
+  e->refcount = 0;
+  e->index = NO_INDEX_ASSIGNED;
+}
+
+/* Add attr to the address table entry to the table.  Defer setting an
+   index until output time.  */
+
+static addr_table_entry *
+add_addr_table_entry (void *addr, enum ate_kind kind)
+{
+  addr_table_entry *node;
+  addr_table_entry finder;
+  void **slot;
+
+  gcc_assert (dwarf_split_debug_info);
+  if (! addr_index_table)
+    addr_index_table = htab_create_ggc (10, addr_table_entry_do_hash,
+                                        addr_table_entry_eq, NULL);
+  init_addr_table_entry (&finder, kind, addr);
+  slot = htab_find_slot (addr_index_table, &finder, INSERT);
+
+  if (*slot == HTAB_EMPTY_ENTRY)
+    {
+      node = ggc_alloc_cleared_addr_table_entry ();
+      init_addr_table_entry (node, kind, addr);
+      *slot = node;
+    }
+  else
+    node = (addr_table_entry *) *slot;
+
+  node->refcount++;
+  return node;
+}
+
+/* Remove an entry from the addr table by decrementing its refcount.
+   Strictly, decrementing the refcount would be enough, but the
+   assertion that the entry is actually in the table has found
+   bugs.  */
+
+static void
+remove_addr_table_entry (addr_table_entry *entry)
+{
+  addr_table_entry *node;
+
+  gcc_assert (dwarf_split_debug_info && addr_index_table);
+  node = (addr_table_entry *) htab_find (addr_index_table, entry);
+  /* After an index is assigned, the table is frozen.  */
+  gcc_assert (node->refcount > 0 && node->index == NO_INDEX_ASSIGNED);
+  node->refcount--;
+}
+
+/* Given a location list, remove all addresses it refers to from the
+   address_table.  */
+
+static void
+remove_loc_list_addr_table_entries (dw_loc_descr_ref descr)
+{
+  for (; descr; descr = descr->dw_loc_next)
+    if (descr->dw_loc_oprnd1.val_entry != NULL)
+      {
+        gcc_assert (descr->dw_loc_oprnd1.val_entry->index == NO_INDEX_ASSIGNED);
+        remove_addr_table_entry (descr->dw_loc_oprnd1.val_entry);
+      }
+}
+
+/* A helper function for dwarf2out_finish called through
+   htab_traverse.  Assign an addr_table_entry its index.  All entries
+   must be collected into the table when this function is called,
+   because the indexing code relies on htab_traverse to traverse nodes
+   in the same order for each run. */
+
+static int
+index_addr_table_entry (void **h, void *v)
+{
+  addr_table_entry *node = (addr_table_entry *) *h;
+  unsigned int *index = (unsigned int *) v;
+
+  /* Don't index unreferenced nodes.  */
+  if (node->refcount == 0)
+    return 1;
+
+  gcc_assert(node->index == NO_INDEX_ASSIGNED);
+  node->index = *index;
+  *index += 1;
+
+  return 1;
+}
+
+/* Add an address constant attribute value to a DIE.  When using
+   dwarf_split_debug_info, address attributes in dies destined for the
+   final executable should be direct references--setting the parameter
+   force_direct ensures this behavior.  */
 
 static inline void
-add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr)
+add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr,
+             bool force_direct)
 {
   dw_attr_node attr;
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_addr;
   attr.dw_attr_val.v.val_addr = addr;
+  if (dwarf_split_debug_info && !force_direct)
+    attr.dw_attr_val.val_entry = add_addr_table_entry (addr, ate_kind_rtx);
+  else
+    attr.dw_attr_val.val_entry = NULL;
   add_dwarf_attr (die, &attr);
 }
 
@@ -4612,6 +4259,7 @@ add_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind,
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_file;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_file = fd;
   add_dwarf_attr (die, &attr);
 }
@@ -4635,6 +4283,7 @@ add_AT_vms_delta (dw_die_ref die, enum dwarf_attribute attr_kind,
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_vms_delta;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_vms_delta.lbl1 = xstrdup (lbl1);
   attr.dw_attr_val.v.val_vms_delta.lbl2 = xstrdup (lbl2);
   add_dwarf_attr (die, &attr);
@@ -4643,13 +4292,19 @@ add_AT_vms_delta (dw_die_ref die, enum dwarf_attribute attr_kind,
 /* Add a label identifier attribute value to a DIE.  */
 
 static inline void
-add_AT_lbl_id (dw_die_ref die, enum dwarf_attribute attr_kind, const char *lbl_id)
+add_AT_lbl_id (dw_die_ref die, enum dwarf_attribute attr_kind,
+               const char *lbl_id)
 {
   dw_attr_node attr;
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_lbl_id;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_id);
+  if (dwarf_split_debug_info)
+    attr.dw_attr_val.val_entry
+        = add_addr_table_entry (attr.dw_attr_val.v.val_lbl_id,
+                                ate_kind_label);
   add_dwarf_attr (die, &attr);
 }
 
@@ -4664,6 +4319,7 @@ add_AT_lineptr (dw_die_ref die, enum dwarf_attribute attr_kind,
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_lineptr;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_lbl_id = xstrdup (label);
   add_dwarf_attr (die, &attr);
 }
@@ -4679,6 +4335,7 @@ add_AT_macptr (dw_die_ref die, enum dwarf_attribute attr_kind,
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_macptr;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_lbl_id = xstrdup (label);
   add_dwarf_attr (die, &attr);
 }
@@ -4693,20 +4350,34 @@ add_AT_offset (dw_die_ref die, enum dwarf_attribute attr_kind,
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_offset;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_offset = offset;
   add_dwarf_attr (die, &attr);
 }
 
-/* Add an range_list attribute value to a DIE.  */
+/* Add a range_list attribute value to a DIE.  When using
+   dwarf_split_debug_info, address attributes in dies destined for the
+   final executable should be direct references--setting the parameter
+   force_direct ensures this behavior.  */
+
+#define UNRELOCATED_OFFSET ((addr_table_entry *) 1)
+#define RELOCATED_OFFSET (NULL)
 
 static void
 add_AT_range_list (dw_die_ref die, enum dwarf_attribute attr_kind,
-                  long unsigned int offset)
+                   long unsigned int offset, bool force_direct)
 {
   dw_attr_node attr;
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_range_list;
+  /* For the range_list attribute, use val_entry to store whether the
+     offset should follow split-debug-info or normal semantics.  This
+     value is read in output_range_list_offset.  */
+  if (dwarf_split_debug_info && !force_direct)
+    attr.dw_attr_val.val_entry = UNRELOCATED_OFFSET;
+  else
+    attr.dw_attr_val.val_entry = RELOCATED_OFFSET;
   attr.dw_attr_val.v.val_offset = offset;
   add_dwarf_attr (die, &attr);
 }
@@ -4734,7 +4405,8 @@ AT_lbl (dw_attr_ref a)
 {
   gcc_assert (a && (AT_class (a) == dw_val_class_lbl_id
                    || AT_class (a) == dw_val_class_lineptr
-                   || AT_class (a) == dw_val_class_macptr));
+                   || AT_class (a) == dw_val_class_macptr
+                   || AT_class (a) == dw_val_class_high_pc));
   return a->dw_attr_val.v.val_lbl_id;
 }
 
@@ -4750,7 +4422,7 @@ get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
   if (! die)
     return NULL;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (a->dw_attr == attr_kind)
       return a;
     else if (a->dw_attr == DW_AT_specification
@@ -4763,6 +4435,23 @@ get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
   return NULL;
 }
 
+/* Returns the parent of the declaration of DIE.  */
+
+static dw_die_ref
+get_die_parent (dw_die_ref die)
+{
+  dw_die_ref t;
+
+  if (!die)
+    return NULL;
+
+  if ((t = get_AT_ref (die, DW_AT_abstract_origin))
+      || (t = get_AT_ref (die, DW_AT_specification)))
+    die = t;
+
+  return die->die_parent;
+}
+
 /* Return the "low pc" attribute value, typically associated with a subprogram
    DIE.  Return null if the "low pc" attribute is either not present, or if it
    cannot be represented as an assembler label identifier.  */
@@ -4879,16 +4568,16 @@ remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
   if (! die)
     return;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (a->dw_attr == attr_kind)
       {
        if (AT_class (a) == dw_val_class_str)
          if (a->dw_attr_val.v.val_str->refcount)
            a->dw_attr_val.v.val_str->refcount--;
 
-       /* VEC_ordered_remove should help reduce the number of abbrevs
+       /* vec::ordered_remove should help reduce the number of abbrevs
           that are needed.  */
-       VEC_ordered_remove (dw_attr_node, die->die_attr, ix);
+       die->die_attr->ordered_remove (ix);
        return;
       }
 }
@@ -5257,7 +4946,7 @@ adjust_piece_list (rtx *dest, rtx *src, rtx *inner,
 
   if (copy)
     {
-      /* First copy all nodes preceeding the current bitpos.  */
+      /* First copy all nodes preceding the current bitpos.  */
       while (src != inner)
        {
          *dest = decl_piece_node (*decl_piece_varloc_ptr (*src),
@@ -5334,7 +5023,10 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
   if (DECL_DEBUG_EXPR_IS_FROM (decl))
     {
       tree realdecl = DECL_DEBUG_EXPR (decl);
-      if (realdecl && handled_component_p (realdecl))
+      if (realdecl
+         && (handled_component_p (realdecl)
+             || (TREE_CODE (realdecl) == MEM_REF
+                 && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR)))
        {
          HOST_WIDE_INT maxsize;
          tree innerdecl;
@@ -5538,7 +5230,7 @@ print_die (dw_die_ref die, FILE *outfile)
   fprintf (outfile, " offset: %ld", die->die_offset);
   fprintf (outfile, " mark: %d\n", die->die_mark);
 
-  if (use_debug_types && die->die_id.die_type_node)
+  if (die->comdat_type_p)
     {
       print_spaces (outfile);
       fprintf (outfile, "  signature: ");
@@ -5546,7 +5238,7 @@ print_die (dw_die_ref die, FILE *outfile)
       fprintf (outfile, "\n");
     }
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     {
       print_spaces (outfile);
       fprintf (outfile, "  %s: ", dwarf_attr_name (a->dw_attr));
@@ -5590,13 +5282,13 @@ print_die (dw_die_ref die, FILE *outfile)
        case dw_val_class_die_ref:
          if (AT_ref (a) != NULL)
            {
-             if (use_debug_types && AT_ref (a)->die_id.die_type_node)
+             if (AT_ref (a)->comdat_type_p)
                {
                  fprintf (outfile, "die -> signature: ");
                  print_signature (outfile,
                                   AT_ref (a)->die_id.die_type_node->signature);
                 }
-             else if (! use_debug_types && AT_ref (a)->die_id.die_symbol)
+             else if (AT_ref (a)->die_id.die_symbol)
                fprintf (outfile, "die -> label: %s",
                         AT_ref (a)->die_id.die_symbol);
              else
@@ -5613,6 +5305,7 @@ print_die (dw_die_ref die, FILE *outfile)
        case dw_val_class_lbl_id:
        case dw_val_class_lineptr:
        case dw_val_class_macptr:
+       case dw_val_class_high_pc:
          fprintf (outfile, "label: %s", AT_lbl (a));
          break;
        case dw_val_class_str:
@@ -5769,6 +5462,7 @@ attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark)
     case dw_val_class_lbl_id:
     case dw_val_class_lineptr:
     case dw_val_class_macptr:
+    case dw_val_class_high_pc:
       break;
 
     case dw_val_class_file:
@@ -5803,7 +5497,7 @@ die_checksum (dw_die_ref die, struct md5_ctx *ctx, int *mark)
 
   CHECKSUM (die->die_tag);
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     attr_checksum (a, ctx, mark);
 
   FOR_EACH_CHILD (die, c, die_checksum (c, ctx, mark));
@@ -6041,6 +5735,7 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
     case dw_val_class_lbl_id:
     case dw_val_class_lineptr:
     case dw_val_class_macptr:
+    case dw_val_class_high_pc:
       break;
 
     case dw_val_class_file:
@@ -6116,7 +5811,7 @@ collect_checksum_attributes (struct checksum_attributes *attrs, dw_die_ref die)
   dw_attr_ref a;
   unsigned ix;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     {
       switch (a->dw_attr)
         {
@@ -6382,9 +6077,11 @@ generate_type_signature (dw_die_ref die, comdat_type_node *type_node)
   unsigned char checksum[16];
   struct md5_ctx ctx;
   dw_die_ref decl;
+  dw_die_ref parent;
 
   name = get_AT_string (die, DW_AT_name);
   decl = get_AT_ref (die, DW_AT_specification);
+  parent = get_die_parent (die);
 
   /* First, compute a signature for just the type name (and its surrounding
      context, if any.  This is stored in the type unit DIE for link-time
@@ -6395,8 +6092,8 @@ generate_type_signature (dw_die_ref die, comdat_type_node *type_node)
       md5_init_ctx (&ctx);
 
       /* Checksum the names of surrounding namespaces and structures.  */
-      if (decl != NULL && decl->die_parent != NULL)
-        checksum_die_context (decl->die_parent, &ctx);
+      if (parent != NULL)
+        checksum_die_context (parent, &ctx);
 
       md5_process_bytes (&die->die_tag, sizeof (die->die_tag), &ctx);
       md5_process_bytes (name, strlen (name) + 1, &ctx);
@@ -6412,8 +6109,8 @@ generate_type_signature (dw_die_ref die, comdat_type_node *type_node)
   die->die_mark = mark;
 
   /* Checksum the names of surrounding namespaces and structures.  */
-  if (decl != NULL && decl->die_parent != NULL)
-    checksum_die_context (decl->die_parent, &ctx);
+  if (parent != NULL)
+    checksum_die_context (parent, &ctx);
 
   /* Checksum the DIE and its children.  */
   die_checksum_ordered (die, &ctx, &mark);
@@ -6424,13 +6121,17 @@ generate_type_signature (dw_die_ref die, comdat_type_node *type_node)
      type node together.  */
   memcpy (type_node->signature, &checksum[16 - DWARF_TYPE_SIGNATURE_SIZE],
           DWARF_TYPE_SIGNATURE_SIZE);
+  die->comdat_type_p = true;
   die->die_id.die_type_node = type_node;
   type_node->type_die = die;
 
   /* If the DIE is a specification, link its declaration to the type node
      as well.  */
   if (decl != NULL)
-    decl->die_id.die_type_node = type_node;
+    {
+      decl->comdat_type_p = true;
+      decl->die_id.die_type_node = type_node;
+    }
 }
 
 /* Do the location expressions look same?  */
@@ -6500,6 +6201,7 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
     case dw_val_class_lbl_id:
     case dw_val_class_lineptr:
     case dw_val_class_macptr:
+    case dw_val_class_high_pc:
       return 1;
 
     case dw_val_class_file:
@@ -6546,12 +6248,11 @@ same_die_p (dw_die_ref die1, dw_die_ref die2, int *mark)
   if (die1->die_tag != die2->die_tag)
     return 0;
 
-  if (VEC_length (dw_attr_node, die1->die_attr)
-      != VEC_length (dw_attr_node, die2->die_attr))
+  if (vec_safe_length (die1->die_attr) != vec_safe_length (die2->die_attr))
     return 0;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die1->die_attr, ix, a1)
-    if (!same_attr_p (a1, VEC_index (dw_attr_node, die2->die_attr, ix), mark))
+  FOR_EACH_VEC_SAFE_ELT (die1->die_attr, ix, a1)
+    if (!same_attr_p (a1, &(*die2->die_attr)[ix], mark))
       return 0;
 
   c1 = die1->die_child;
@@ -6596,7 +6297,7 @@ same_die_p_wrap (dw_die_ref die1, dw_die_ref die2)
 
 /* The prefix to attach to symbols on DIEs in the current comdat debug
    info section.  */
-static char *comdat_symbol_id;
+static const char *comdat_symbol_id;
 
 /* The index of the current symbol within the current comdat CU.  */
 static unsigned int comdat_symbol_number;
@@ -6721,6 +6422,33 @@ is_cu_die (dw_die_ref c)
   return c && c->die_tag == DW_TAG_compile_unit;
 }
 
+/* Returns true iff C is a unit DIE of some sort.  */
+
+static inline bool
+is_unit_die (dw_die_ref c)
+{
+  return c && (c->die_tag == DW_TAG_compile_unit
+              || c->die_tag == DW_TAG_partial_unit
+              || c->die_tag == DW_TAG_type_unit);
+}
+
+/* Returns true iff C is a namespace DIE.  */
+
+static inline bool
+is_namespace_die (dw_die_ref c)
+{
+  return c && c->die_tag == DW_TAG_namespace;
+}
+
+/* Returns true iff C is a class or structure DIE.  */
+
+static inline bool
+is_class_die (dw_die_ref c)
+{
+  return c && (c->die_tag == DW_TAG_class_type
+               || c->die_tag == DW_TAG_structure_type);
+}
+
 static char *
 gen_internal_sym (const char *prefix)
 {
@@ -6737,7 +6465,7 @@ assign_symbol_names (dw_die_ref die)
 {
   dw_die_ref c;
 
-  if (is_symbol_die (die))
+  if (is_symbol_die (die) && !die->comdat_type_p)
     {
       if (comdat_symbol_id)
        {
@@ -6919,7 +6647,7 @@ is_declaration_die (dw_die_ref die)
   dw_attr_ref a;
   unsigned ix;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (a->dw_attr == DW_AT_declaration)
       return 1;
 
@@ -7006,7 +6734,7 @@ clone_die (dw_die_ref die)
   clone = ggc_alloc_cleared_die_node ();
   clone->die_tag = die->die_tag;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     add_dwarf_attr (clone, a);
 
   return clone;
@@ -7042,12 +6770,17 @@ clone_as_declaration (dw_die_ref die)
   /* If the DIE is a specification, just clone its declaration DIE.  */
   decl = get_AT_ref (die, DW_AT_specification);
   if (decl != NULL)
-    return clone_die (decl);
+    {
+      clone = clone_die (decl);
+      if (die->comdat_type_p)
+       add_AT_die_ref (clone, DW_AT_signature, die);
+      return clone;
+    }
 
   clone = ggc_alloc_cleared_die_node ();
   clone->die_tag = die->die_tag;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     {
       /* We don't want to copy over all attributes.
          For example we don't want DW_AT_byte_size because otherwise we will no
@@ -7071,7 +6804,7 @@ clone_as_declaration (dw_die_ref die)
         }
     }
 
-  if (die->die_id.die_type_node)
+  if (die->comdat_type_p)
     add_AT_die_ref (clone, DW_AT_signature, die);
 
   add_AT_flag (clone, DW_AT_declaration, 1);
@@ -7106,11 +6839,12 @@ copy_declaration_context (dw_die_ref unit, dw_die_ref die)
 
       /* Copy the type node pointer from the new DIE to the original
          declaration DIE so we can forward references later.  */
+      decl->comdat_type_p = true;
       decl->die_id.die_type_node = die->die_id.die_type_node;
 
       remove_AT (die, DW_AT_specification);
 
-      FOR_EACH_VEC_ELT (dw_attr_node, decl->die_attr, ix, a)
+      FOR_EACH_VEC_SAFE_ELT (decl->die_attr, ix, a)
         {
           if (a->dw_attr != DW_AT_name
               && a->dw_attr != DW_AT_declaration
@@ -7122,8 +6856,7 @@ copy_declaration_context (dw_die_ref unit, dw_die_ref die)
     }
 
   if (decl->die_parent != NULL
-      && decl->die_parent->die_tag != DW_TAG_compile_unit
-      && decl->die_parent->die_tag != DW_TAG_type_unit)
+      && !is_unit_die (decl->die_parent))
     {
       new_decl = copy_ancestor_tree (unit, decl, NULL);
       if (new_decl != NULL)
@@ -7240,6 +6973,7 @@ remove_child_or_replace_with_skeleton (dw_die_ref unit, dw_die_ref child,
     remove_child_with_prev (child, prev);
   else
     {
+      skeleton->comdat_type_p = true;
       skeleton->die_id.die_type_node = child->die_id.die_type_node;
 
       /* If the original DIE was a specification, we need to put
@@ -7301,6 +7035,7 @@ break_out_comdat_types (dw_die_ref die)
            declaration into the new type unit DIE, then remove this DIE
           from the main CU (or replace it with a skeleton if necessary).  */
        replacement = remove_child_or_replace_with_skeleton (unit, c, prev);
+       type_node->skeleton_die = replacement;
 
         /* Break out nested types into their own type units.  */
         break_out_comdat_types (c);
@@ -7396,8 +7131,7 @@ copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
       dw_die_ref spec = get_AT_ref (parent, DW_AT_specification);
       if (spec != NULL)
         parent = spec;
-      if (parent->die_tag != DW_TAG_compile_unit
-          && parent->die_tag != DW_TAG_type_unit)
+      if (!is_unit_die (parent))
         new_parent = copy_ancestor_tree (unit, parent, decl_table);
     }
 
@@ -7450,16 +7184,15 @@ copy_decls_walk (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
   dw_attr_ref a;
   unsigned ix;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     {
       if (AT_class (a) == dw_val_class_die_ref)
         {
           dw_die_ref targ = AT_ref (a);
-          comdat_type_node_ref type_node = targ->die_id.die_type_node;
           void **slot;
           struct decl_table_entry *entry;
 
-          if (targ->die_mark != 0 || type_node != NULL)
+          if (targ->die_mark != 0 || targ->comdat_type_p)
             continue;
 
           slot = htab_find_slot_with_hash (decl_table, targ,
@@ -7497,8 +7230,7 @@ copy_decls_walk (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
               /* If TARG has surrounding context, copy its ancestor tree
                  into the new type unit.  */
               if (targ->die_parent != NULL
-                  && targ->die_parent->die_tag != DW_TAG_compile_unit
-                  && targ->die_parent->die_tag != DW_TAG_type_unit)
+                 && !is_unit_die (targ->die_parent))
                 parent = copy_ancestor_tree (unit, targ->die_parent,
                                              decl_table);
 
@@ -7573,20 +7305,161 @@ output_location_lists (dw_die_ref die)
   dw_attr_ref a;
   unsigned ix;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (AT_class (a) == dw_val_class_loc_list)
       output_loc_list (AT_loc_list (a));
 
   FOR_EACH_CHILD (die, c, output_location_lists (c));
 }
 
+/* We want to limit the number of external references, because they are
+   larger than local references: a relocation takes multiple words, and
+   even a sig8 reference is always eight bytes, whereas a local reference
+   can be as small as one byte (though DW_FORM_ref is usually 4 in GCC).
+   So if we encounter multiple external references to the same type DIE, we
+   make a local typedef stub for it and redirect all references there.
+
+   This is the element of the hash table for keeping track of these
+   references.  */
+
+struct external_ref
+{
+  dw_die_ref type;
+  dw_die_ref stub;
+  unsigned n_refs;
+};
+
+/* Hash an external_ref.  */
+
+static hashval_t
+hash_external_ref (const void *p)
+{
+  const struct external_ref *r = (const struct external_ref *)p;
+  return htab_hash_pointer (r->type);
+}
+
+/* Compare external_refs.  */
+
+static int
+external_ref_eq (const void *p1, const void *p2)
+{
+  const struct external_ref *r1 = (const struct external_ref *)p1;
+  const struct external_ref *r2 = (const struct external_ref *)p2;
+  return r1->type == r2->type;
+}
+
+/* Return a pointer to the external_ref for references to DIE.  */
+
+static struct external_ref *
+lookup_external_ref (htab_t map, dw_die_ref die)
+{
+  struct external_ref ref, *ref_p;
+  void ** slot;
+
+  ref.type = die;
+  slot = htab_find_slot (map, &ref, INSERT);
+  if (*slot != HTAB_EMPTY_ENTRY)
+    return (struct external_ref *) *slot;
+
+  ref_p = XCNEW (struct external_ref);
+  ref_p->type = die;
+  *slot = ref_p;
+  return ref_p;
+}
+
+/* Subroutine of optimize_external_refs, below.
+
+   If we see a type skeleton, record it as our stub.  If we see external
+   references, remember how many we've seen.  */
+
+static void
+optimize_external_refs_1 (dw_die_ref die, htab_t map)
+{
+  dw_die_ref c;
+  dw_attr_ref a;
+  unsigned ix;
+  struct external_ref *ref_p;
+
+  if (is_type_die (die)
+      && (c = get_AT_ref (die, DW_AT_signature)))
+    {
+      /* This is a local skeleton; use it for local references.  */
+      ref_p = lookup_external_ref (map, c);
+      ref_p->stub = die;
+    }
+
+  /* Scan the DIE references, and remember any that refer to DIEs from
+     other CUs (i.e. those which are not marked).  */
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+    if (AT_class (a) == dw_val_class_die_ref
+       && (c = AT_ref (a))->die_mark == 0
+       && is_type_die (c))
+      {
+       ref_p = lookup_external_ref (map, c);
+       ref_p->n_refs++;
+      }
+
+  FOR_EACH_CHILD (die, c, optimize_external_refs_1 (c, map));
+}
+
+/* htab_traverse callback function for optimize_external_refs, below.  SLOT
+   points to an external_ref, DATA is the CU we're processing.  If we don't
+   already have a local stub, and we have multiple refs, build a stub.  */
+
+static int
+build_local_stub (void **slot, void *data)
+{
+  struct external_ref *ref_p = (struct external_ref *)*slot;
+
+  if (ref_p->stub == NULL && ref_p->n_refs > 1 && !dwarf_strict)
+    {
+      /* We have multiple references to this type, so build a small stub.
+        Both of these forms are a bit dodgy from the perspective of the
+        DWARF standard, since technically they should have names.  */
+      dw_die_ref cu = (dw_die_ref) data;
+      dw_die_ref type = ref_p->type;
+      dw_die_ref stub = NULL;
+
+      if (type->comdat_type_p)
+       {
+         /* If we refer to this type via sig8, use AT_signature.  */
+         stub = new_die (type->die_tag, cu, NULL_TREE);
+         add_AT_die_ref (stub, DW_AT_signature, type);
+       }
+      else
+       {
+         /* Otherwise, use a typedef with no name.  */
+         stub = new_die (DW_TAG_typedef, cu, NULL_TREE);
+         add_AT_die_ref (stub, DW_AT_type, type);
+       }
+
+      stub->die_mark++;
+      ref_p->stub = stub;
+    }
+  return 1;
+}
+
+/* DIE is a unit; look through all the DIE references to see if there are
+   any external references to types, and if so, create local stubs for
+   them which will be applied in build_abbrev_table.  This is useful because
+   references to local DIEs are smaller.  */
+
+static htab_t
+optimize_external_refs (dw_die_ref die)
+{
+  htab_t map = htab_create (10, hash_external_ref, external_ref_eq, free);
+  optimize_external_refs_1 (die, map);
+  htab_traverse (map, build_local_stub, die);
+  return map;
+}
+
 /* The format of each DIE (and its attribute value pairs) is encoded in an
    abbreviation table.  This routine builds the abbreviation table and assigns
    a unique abbreviation id for each abbreviation entry.  The children of each
    die are visited recursively.  */
 
 static void
-build_abbrev_table (dw_die_ref die)
+build_abbrev_table (dw_die_ref die, htab_t extern_map)
 {
   unsigned long abbrev_id;
   unsigned int n_alloc;
@@ -7594,14 +7467,22 @@ build_abbrev_table (dw_die_ref die)
   dw_attr_ref a;
   unsigned ix;
 
-  /* Scan the DIE references, and mark as external any that refer to
-     DIEs from other CUs (i.e. those which are not marked).  */
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  /* Scan the DIE references, and replace any that refer to
+     DIEs from other CUs (i.e. those which are not marked) with
+     the local stubs we built in optimize_external_refs.  */
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (AT_class (a) == dw_val_class_die_ref
-       && AT_ref (a)->die_mark == 0)
+       && (c = AT_ref (a))->die_mark == 0)
       {
-       gcc_assert (use_debug_types || AT_ref (a)->die_id.die_symbol);
-       set_AT_ref_external (a, 1);
+       struct external_ref *ref_p;
+       gcc_assert (AT_ref (a)->comdat_type_p || AT_ref (a)->die_id.die_symbol);
+
+       ref_p = lookup_external_ref (extern_map, c);
+       if (ref_p->stub && ref_p->stub != die)
+         change_AT_die_ref (a, ref_p->stub);
+       else
+         /* We aren't changing this reference, so mark it external.  */
+         set_AT_ref_external (a, 1);
       }
 
   for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
@@ -7616,13 +7497,12 @@ build_abbrev_table (dw_die_ref die)
       if ((abbrev->die_child != NULL) != (die->die_child != NULL))
        continue;
 
-      if (VEC_length (dw_attr_node, abbrev->die_attr)
-         != VEC_length (dw_attr_node, die->die_attr))
+      if (vec_safe_length (abbrev->die_attr) != vec_safe_length (die->die_attr))
        continue;
 
-      FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, die_a)
+      FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, die_a)
        {
-         abbrev_a = VEC_index (dw_attr_node, abbrev->die_attr, ix);
+         abbrev_a = &(*abbrev->die_attr)[ix];
          if ((abbrev_a->dw_attr != die_a->dw_attr)
              || (value_format (abbrev_a) != value_format (die_a)))
            {
@@ -7652,7 +7532,7 @@ build_abbrev_table (dw_die_ref die)
     }
 
   die->die_abbrev = abbrev_id;
-  FOR_EACH_CHILD (die, c, build_abbrev_table (c));
+  FOR_EACH_CHILD (die, c, build_abbrev_table (c, extern_map));
 }
 \f
 /* Return the power-of-two number of bytes necessary to represent VALUE.  */
@@ -7682,14 +7562,21 @@ size_of_die (dw_die_ref die)
   unsigned long size = 0;
   dw_attr_ref a;
   unsigned ix;
+  enum dwarf_form form;
 
   size += size_of_uleb128 (die->die_abbrev);
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     {
       switch (AT_class (a))
        {
        case dw_val_class_addr:
-         size += DWARF2_ADDR_SIZE;
+          if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
+            {
+              gcc_assert (AT_index (a) != NO_INDEX_ASSIGNED);
+              size += size_of_uleb128 (AT_index (a));
+            }
+          else
+            size += DWARF2_ADDR_SIZE;
          break;
        case dw_val_class_offset:
          size += DWARF_OFFSET_SIZE;
@@ -7707,10 +7594,16 @@ size_of_die (dw_die_ref die)
          }
          break;
        case dw_val_class_loc_list:
-         size += DWARF_OFFSET_SIZE;
+          if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
+            {
+              gcc_assert (AT_index (a) != NO_INDEX_ASSIGNED);
+              size += size_of_uleb128 (AT_index (a));
+            }
+          else
+            size += DWARF_OFFSET_SIZE;
          break;
        case dw_val_class_range_list:
-         size += DWARF_OFFSET_SIZE;
+          size += DWARF_OFFSET_SIZE;
          break;
        case dw_val_class_const:
          size += size_of_sleb128 (AT_int (a));
@@ -7727,7 +7620,7 @@ size_of_die (dw_die_ref die)
          }
          break;
        case dw_val_class_const_double:
-         size += 2 * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
+         size += HOST_BITS_PER_DOUBLE_INT / HOST_BITS_PER_CHAR;
          if (HOST_BITS_PER_WIDE_INT >= 64)
            size++; /* block */
          break;
@@ -7770,15 +7663,24 @@ size_of_die (dw_die_ref die)
          size += DWARF_OFFSET_SIZE;
          break;
        case dw_val_class_lbl_id:
-         size += DWARF2_ADDR_SIZE;
+          if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
+            {
+              gcc_assert (AT_index (a) != NO_INDEX_ASSIGNED);
+              size += size_of_uleb128 (AT_index (a));
+            }
+          else
+            size += DWARF2_ADDR_SIZE;
          break;
        case dw_val_class_lineptr:
        case dw_val_class_macptr:
-         size += DWARF_OFFSET_SIZE;
+          size += DWARF_OFFSET_SIZE;
          break;
        case dw_val_class_str:
-         if (AT_string_form (a) == DW_FORM_strp)
+          form = AT_string_form (a);
+          if (form == DW_FORM_strp)
            size += DWARF_OFFSET_SIZE;
+         else if (form == DW_FORM_GNU_str_index)
+            size += size_of_uleb128 (AT_index (a));
          else
            size += strlen (a->dw_attr_val.v.val_str->str) + 1;
          break;
@@ -7791,6 +7693,9 @@ size_of_die (dw_die_ref die)
        case dw_val_class_vms_delta:
          size += DWARF_OFFSET_SIZE;
          break;
+       case dw_val_class_high_pc:
+         size += DWARF2_ADDR_SIZE;
+         break;
        default:
          gcc_unreachable ();
        }
@@ -7837,7 +7742,7 @@ calc_base_type_die_sizes (void)
 #endif
 
   die_offset += size_of_die (comp_unit_die ());
-  for (i = 0; VEC_iterate (dw_die_ref, base_types, i, base_type); i++)
+  for (i = 0; base_types.iterate (i, &base_type); i++)
     {
 #if ENABLE_ASSERT_CHECKING
       gcc_assert (base_type->die_offset == 0
@@ -7896,7 +7801,7 @@ unmark_all_dies (dw_die_ref die)
 
   FOR_EACH_CHILD (die, c, unmark_all_dies (c));
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (AT_class (a) == dw_val_class_die_ref)
       unmark_all_dies (AT_ref (a));
 }
@@ -7905,14 +7810,14 @@ unmark_all_dies (dw_die_ref die)
    generated for the compilation unit.  */
 
 static unsigned long
-size_of_pubnames (VEC (pubname_entry, gc) * names)
+size_of_pubnames (vec<pubname_entry, va_gc> *names)
 {
   unsigned long size;
   unsigned i;
   pubname_ref p;
 
   size = DWARF_PUBNAMES_HEADER_SIZE;
-  FOR_EACH_VEC_ELT (pubname_entry, names, i, p)
+  FOR_EACH_VEC_ELT (*names, i, p)
     if (names != pubtype_table
        || p->die->die_offset != 0
        || !flag_eliminate_unused_debug_types)
@@ -7941,8 +7846,10 @@ size_of_aranges (void)
       unsigned fde_idx;
       dw_fde_ref fde;
 
-      FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, fde_idx, fde)
+      FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde)
        {
+         if (DECL_IGNORED_P (fde->decl))
+           continue;
          if (!fde->in_std_section)
            size += 2 * DWARF2_ADDR_SIZE;
          if (fde->dw_fde_second_begin && !fde->second_in_std_section)
@@ -7960,7 +7867,7 @@ size_of_aranges (void)
 static enum dwarf_form
 value_format (dw_attr_ref a)
 {
-  switch (a->dw_attr_val.val_class)
+  switch (AT_class (a))
     {
     case dw_val_class_addr:
       /* Only very few attributes allow DW_FORM_addr.  */
@@ -7970,7 +7877,8 @@ value_format (dw_attr_ref a)
        case DW_AT_high_pc:
        case DW_AT_entry_pc:
        case DW_AT_trampoline:
-         return DW_FORM_addr;
+          return (AT_index (a) == NOT_INDEXED
+                  ? DW_FORM_addr : DW_FORM_GNU_addr_index);
        default:
          break;
        }
@@ -8088,7 +7996,8 @@ value_format (dw_attr_ref a)
     case dw_val_class_fde_ref:
       return DW_FORM_data;
     case dw_val_class_lbl_id:
-      return DW_FORM_addr;
+      return (AT_index (a) == NOT_INDEXED
+              ? DW_FORM_addr : DW_FORM_GNU_addr_index);
     case dw_val_class_lineptr:
     case dw_val_class_macptr:
       return dwarf_version >= 4 ? DW_FORM_sec_offset : DW_FORM_data;
@@ -8107,9 +8016,24 @@ value_format (dw_attr_ref a)
          gcc_unreachable ();
        }
 
-    case dw_val_class_data8:
-      return DW_FORM_data8;
-
+    case dw_val_class_data8:
+      return DW_FORM_data8;
+
+    case dw_val_class_high_pc:
+      switch (DWARF2_ADDR_SIZE)
+       {
+       case 1:
+         return DW_FORM_data1;
+       case 2:
+         return DW_FORM_data2;
+       case 4:
+         return DW_FORM_data4;
+       case 8:
+         return DW_FORM_data8;
+       default:
+         gcc_unreachable ();
+       }
+
     default:
       gcc_unreachable ();
     }
@@ -8125,40 +8049,45 @@ output_value_format (dw_attr_ref a)
   dw2_asm_output_data_uleb128 (form, "(%s)", dwarf_form_name (form));
 }
 
-/* Output the .debug_abbrev section which defines the DIE abbreviation
-   table.  */
+/* Given a die and id, produce the appropriate abbreviations.  */
 
 static void
-output_abbrev_section (void)
+output_die_abbrevs (unsigned long abbrev_id, dw_die_ref abbrev)
 {
-  unsigned long abbrev_id;
+  unsigned ix;
+  dw_attr_ref a_attr;
 
-  for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
+  dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)");
+  dw2_asm_output_data_uleb128 (abbrev->die_tag, "(TAG: %s)",
+                               dwarf_tag_name (abbrev->die_tag));
+
+  if (abbrev->die_child != NULL)
+    dw2_asm_output_data (1, DW_children_yes, "DW_children_yes");
+  else
+    dw2_asm_output_data (1, DW_children_no, "DW_children_no");
+
+  for (ix = 0; vec_safe_iterate (abbrev->die_attr, ix, &a_attr); ix++)
     {
-      dw_die_ref abbrev = abbrev_die_table[abbrev_id];
-      unsigned ix;
-      dw_attr_ref a_attr;
+      dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)",
+                                   dwarf_attr_name (a_attr->dw_attr));
+      output_value_format (a_attr);
+    }
+
+  dw2_asm_output_data (1, 0, NULL);
+  dw2_asm_output_data (1, 0, NULL);
+}
 
-      dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)");
-      dw2_asm_output_data_uleb128 (abbrev->die_tag, "(TAG: %s)",
-                                  dwarf_tag_name (abbrev->die_tag));
 
-      if (abbrev->die_child != NULL)
-       dw2_asm_output_data (1, DW_children_yes, "DW_children_yes");
-      else
-       dw2_asm_output_data (1, DW_children_no, "DW_children_no");
+/* Output the .debug_abbrev section which defines the DIE abbreviation
+   table.  */
 
-      for (ix = 0; VEC_iterate (dw_attr_node, abbrev->die_attr, ix, a_attr);
-          ix++)
-       {
-         dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)",
-                                      dwarf_attr_name (a_attr->dw_attr));
-         output_value_format (a_attr);
-       }
+static void
+output_abbrev_section (void)
+{
+  unsigned long abbrev_id;
 
-      dw2_asm_output_data (1, 0, NULL);
-      dw2_asm_output_data (1, 0, NULL);
-    }
+  for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
+    output_die_abbrevs (abbrev_id, abbrev_die_table[abbrev_id]);
 
   /* Terminate the table.  */
   dw2_asm_output_data (1, 0, NULL);
@@ -8169,7 +8098,9 @@ output_abbrev_section (void)
 static inline void
 output_die_symbol (dw_die_ref die)
 {
-  char *sym = die->die_id.die_symbol;
+  const char *sym = die->die_id.die_symbol;
+
+  gcc_assert (!die->comdat_type_p);
 
   if (sym == 0)
     return;
@@ -8193,6 +8124,7 @@ new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
   dw_loc_list_ref retlist = ggc_alloc_cleared_dw_loc_list_node ();
 
   retlist->begin = begin;
+  retlist->begin_entry = NULL;
   retlist->end = end;
   retlist->expr = expr;
   retlist->section = section;
@@ -8237,7 +8169,22 @@ output_loc_list (dw_loc_list_ref list_head)
         in a single range are unlikely very useful.  */
       if (size > 0xffff)
        continue;
-      if (!have_multiple_function_sections)
+      if (dwarf_split_debug_info)
+        {
+          dw2_asm_output_data (1, DW_LLE_GNU_start_length_entry,
+                               "Location list start/length entry (%s)",
+                               list_head->ll_symbol);
+          dw2_asm_output_data_uleb128 (curr->begin_entry->index,
+                                       "Location list range start index (%s)",
+                                       curr->begin);
+          /* The length field is 4 bytes.  If we ever need to support
+            an 8-byte length, we can add a new DW_LLE code or fall back
+            to DW_LLE_GNU_start_end_entry.  */
+          dw2_asm_output_delta (4, curr->end, curr->begin,
+                                "Location list range length (%s)",
+                                list_head->ll_symbol);
+        }
+      else if (!have_multiple_function_sections)
        {
          dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section,
                                "Location list begin address (%s)",
@@ -8263,12 +8210,86 @@ output_loc_list (dw_loc_list_ref list_head)
       output_loc_sequence (curr->expr, -1);
     }
 
-  dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
-                      "Location list terminator begin (%s)",
-                      list_head->ll_symbol);
-  dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
-                      "Location list terminator end (%s)",
-                      list_head->ll_symbol);
+  if (dwarf_split_debug_info)
+    dw2_asm_output_data (1, DW_LLE_GNU_end_of_list_entry,
+                         "Location list terminator (%s)",
+                         list_head->ll_symbol);
+  else
+    {
+      dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
+                           "Location list terminator begin (%s)",
+                           list_head->ll_symbol);
+      dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
+                           "Location list terminator end (%s)",
+                           list_head->ll_symbol);
+    }
+}
+
+/* Output a range_list offset into the debug_range section.  Emit a
+   relocated reference if val_entry is NULL, otherwise, emit an
+   indirect reference.  */
+
+static void
+output_range_list_offset (dw_attr_ref a)
+{
+  const char *name = dwarf_attr_name (a->dw_attr);
+
+  if (a->dw_attr_val.val_entry == RELOCATED_OFFSET)
+    {
+      char *p = strchr (ranges_section_label, '\0');
+      sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX, a->dw_attr_val.v.val_offset);
+      dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label,
+                             debug_ranges_section, "%s", name);
+      *p = '\0';
+    }
+  else
+    dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset,
+                         "%s (offset from %s)", name, ranges_section_label);
+}
+
+/* Output the offset into the debug_loc section.  */
+
+static void
+output_loc_list_offset (dw_attr_ref a)
+{
+  char *sym = AT_loc_list (a)->ll_symbol;
+
+  gcc_assert (sym);
+  if (dwarf_split_debug_info)
+    dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label,
+                          "%s", dwarf_attr_name (a->dw_attr));
+  else
+    dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section,
+                           "%s", dwarf_attr_name (a->dw_attr));
+}
+
+/* Output an attribute's index or value appropriately.  */
+
+static void
+output_attr_index_or_value (dw_attr_ref a)
+{
+  const char *name = dwarf_attr_name (a->dw_attr);
+
+  if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
+    {
+      dw2_asm_output_data_uleb128 (AT_index (a), "%s", name);
+      return;
+    }
+  switch (AT_class (a))
+    {
+      case dw_val_class_addr:
+        dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name);
+        break;
+      case dw_val_class_high_pc:
+      case dw_val_class_lbl_id:
+        dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name);
+        break;
+      case dw_val_class_loc_list:
+        output_loc_list_offset (a);
+        break;
+      default:
+        gcc_unreachable ();
+    }
 }
 
 /* Output a type signature.  */
@@ -8295,21 +8316,21 @@ output_die (dw_die_ref die)
 
   /* If someone in another CU might refer to us, set up a symbol for
      them to point to.  */
-  if (! use_debug_types && die->die_id.die_symbol)
+  if (! die->comdat_type_p && die->die_id.die_symbol)
     output_die_symbol (die);
 
   dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
                               (unsigned long)die->die_offset,
                               dwarf_tag_name (die->die_tag));
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     {
       const char *name = dwarf_attr_name (a->dw_attr);
 
       switch (AT_class (a))
        {
        case dw_val_class_addr:
-         dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name);
+          output_attr_index_or_value (a);
          break;
 
        case dw_val_class_offset:
@@ -8318,15 +8339,7 @@ output_die (dw_die_ref die)
          break;
 
        case dw_val_class_range_list:
-         {
-           char *p = strchr (ranges_section_label, '\0');
-
-           sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX,
-                    a->dw_attr_val.v.val_offset);
-           dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label,
-                                  debug_ranges_section, "%s", name);
-           *p = '\0';
-         }
+          output_range_list_offset (a);
          break;
 
        case dw_val_class_loc:
@@ -8366,7 +8379,7 @@ output_die (dw_die_ref die)
 
            if (HOST_BITS_PER_WIDE_INT >= 64)
              dw2_asm_output_data (1,
-                                  2 * HOST_BITS_PER_WIDE_INT
+                                  HOST_BITS_PER_DOUBLE_INT
                                   / HOST_BITS_PER_CHAR,
                                   NULL);
 
@@ -8382,7 +8395,7 @@ output_die (dw_die_ref die)
              }
 
            dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
-                                first, name);
+                                 first, "%s", name);
            dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
                                 second, NULL);
          }
@@ -8429,19 +8442,13 @@ output_die (dw_die_ref die)
          break;
 
        case dw_val_class_loc_list:
-         {
-           char *sym = AT_loc_list (a)->ll_symbol;
-
-           gcc_assert (sym);
-           dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section,
-                                  "%s", name);
-         }
+          output_attr_index_or_value (a);
          break;
 
        case dw_val_class_die_ref:
          if (AT_ref_external (a))
            {
-             if (use_debug_types)
+             if (AT_ref (a)->comdat_type_p)
                {
                  comdat_type_node_ref type_node =
                    AT_ref (a)->die_id.die_type_node;
@@ -8451,7 +8458,7 @@ output_die (dw_die_ref die)
                }
              else
                {
-                 char *sym = AT_ref (a)->die_id.die_symbol;
+                 const char *sym = AT_ref (a)->die_id.die_symbol;
                  int size;
 
                  gcc_assert (sym);
@@ -8492,7 +8499,7 @@ output_die (dw_die_ref die)
          break;
 
        case dw_val_class_lbl_id:
-         dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name);
+          output_attr_index_or_value (a);
          break;
 
        case dw_val_class_lineptr:
@@ -8506,12 +8513,15 @@ output_die (dw_die_ref die)
          break;
 
        case dw_val_class_str:
-         if (AT_string_form (a) == DW_FORM_strp)
-           dw2_asm_output_offset (DWARF_OFFSET_SIZE,
-                                  a->dw_attr_val.v.val_str->label,
-                                  debug_str_section,
-                                  "%s: \"%s\"", name, AT_string (a));
-         else
+          if (a->dw_attr_val.v.val_str->form == DW_FORM_strp)
+            dw2_asm_output_offset (DWARF_OFFSET_SIZE,
+                                   a->dw_attr_val.v.val_str->label,
+                                   debug_str_section,
+                                   "%s: \"%s\"", name, AT_string (a));
+          else if (a->dw_attr_val.v.val_str->form == DW_FORM_GNU_str_index)
+            dw2_asm_output_data_uleb128 (AT_index (a),
+                                         "%s: \"%s\"", name, AT_string (a));
+          else
            dw2_asm_output_nstring (AT_string (a), -1, "%s", name);
          break;
 
@@ -8534,6 +8544,11 @@ output_die (dw_die_ref die)
            break;
          }
 
+       case dw_val_class_high_pc:
+         dw2_asm_output_delta (DWARF2_ADDR_SIZE, AT_lbl (a),
+                               get_AT_low_pc (die), "DW_AT_high_pc");
+         break;
+
        default:
          gcc_unreachable ();
        }
@@ -8573,8 +8588,9 @@ output_compilation_unit_header (void)
 static void
 output_comp_unit (dw_die_ref die, int output_if_empty)
 {
-  const char *secname;
-  char *oldsym, *tmp;
+  const char *secname, *oldsym;
+  char *tmp;
+  htab_t extern_map;
 
   /* Unless we are outputting main CU, we may throw away empty ones.  */
   if (!output_if_empty && die->die_child == NULL)
@@ -8587,7 +8603,11 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
      this CU so we know which get local refs.  */
   mark_dies (die);
 
-  build_abbrev_table (die);
+  extern_map = optimize_external_refs (die);
+
+  build_abbrev_table (die, extern_map);
+
+  htab_delete (extern_map);
 
   /* Initialize the beginning DIE offset - and calculate sizes/offsets.  */
   next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
@@ -8623,6 +8643,117 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
     }
 }
 
+/* Whether to generate the DWARF accelerator tables in .debug_pubnames
+   and .debug_pubtypes.  This is configured per-target, but can be
+   overridden by the -gpubnames or -gno-pubnames options.  */
+
+static inline bool
+want_pubnames (void)
+{
+  return (debug_generate_pub_sections != -1
+         ? debug_generate_pub_sections
+         : targetm.want_debug_pub_sections);
+}
+
+/* Add the DW_AT_GNU_pubnames and DW_AT_GNU_pubtypes attributes.  */
+
+static void
+add_AT_pubnames (dw_die_ref die)
+{
+  if (want_pubnames ())
+    add_AT_flag (die, DW_AT_GNU_pubnames, 1);
+}
+
+/* Helper function to generate top-level dies for skeleton debug_info and
+   debug_types.  */
+
+static void
+add_top_level_skeleton_die_attrs (dw_die_ref die)
+{
+  const char *dwo_file_name = concat (aux_base_name, ".dwo", NULL);
+  dw_attr_ref attr;
+
+  add_comp_dir_attribute (die);
+  add_AT_string (die, DW_AT_GNU_dwo_name, dwo_file_name);
+  /* The specification suggests that these attributes be inline to avoid
+     having a .debug_str section.  We know that they exist in the die because
+     we just added them.  */
+  attr = get_AT (die, DW_AT_GNU_dwo_name);
+  attr->dw_attr_val.v.val_str->form = DW_FORM_string;
+  attr = get_AT (die, DW_AT_comp_dir);
+  attr->dw_attr_val.v.val_str->form = DW_FORM_string;
+
+  add_AT_pubnames (die);
+  add_AT_lineptr (die, DW_AT_GNU_addr_base, debug_addr_section_label);
+}
+
+/* Return the single type-unit die for skeleton type units.  */
+
+static dw_die_ref
+get_skeleton_type_unit (void)
+{
+  /* For dwarf_split_debug_sections with use_type info, all type units in the
+     skeleton sections have identical dies (but different headers).  This
+     single die will be output many times.  */
+
+  static dw_die_ref skeleton_type_unit = NULL;
+
+  if (skeleton_type_unit == NULL)
+    {
+      skeleton_type_unit = new_die (DW_TAG_type_unit, NULL, NULL);
+      add_top_level_skeleton_die_attrs (skeleton_type_unit);
+      skeleton_type_unit->die_abbrev = SKELETON_TYPE_DIE_ABBREV;
+    }
+  return skeleton_type_unit;
+}
+
+/* Output skeleton debug sections that point to the dwo file.  */
+
+static void
+output_skeleton_debug_sections (dw_die_ref comp_unit)
+{
+  /* These attributes will be found in the full debug_info section.  */
+  remove_AT (comp_unit, DW_AT_producer);
+  remove_AT (comp_unit, DW_AT_language);
+
+  /* Add attributes common to skeleton compile_units and type_units.  */
+  add_top_level_skeleton_die_attrs (comp_unit);
+
+  switch_to_section (debug_skeleton_info_section);
+  ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_info_section_label);
+
+  /* Produce the skeleton compilation-unit header.  This one differs enough from
+     a normal CU header that it's better not to call output_compilation_unit
+     header.  */
+  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,
+                       DWARF_COMPILE_UNIT_HEADER_SIZE
+                       - DWARF_INITIAL_LENGTH_SIZE
+                       + size_of_die (comp_unit),
+                      "Length of Compilation Unit Info");
+  dw2_asm_output_data (2, dwarf_version, "DWARF version number");
+  dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_abbrev_section_label,
+                         debug_abbrev_section,
+                         "Offset Into Abbrev. Section");
+  dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
+
+  comp_unit->die_abbrev = SKELETON_COMP_DIE_ABBREV;
+  output_die (comp_unit);
+
+  /* Build the skeleton debug_abbrev section.  */
+  switch_to_section (debug_skeleton_abbrev_section);
+  ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_abbrev_section_label);
+
+  output_die_abbrevs (SKELETON_COMP_DIE_ABBREV, comp_unit);
+  if (use_debug_types)
+    output_die_abbrevs (SKELETON_TYPE_DIE_ABBREV, get_skeleton_type_unit ());
+
+  dw2_asm_output_data (1, 0, "end of skeleton .debug_abbrev");
+}
+
 /* Output a comdat type unit DIE and its children.  */
 
 static void
@@ -8634,18 +8765,27 @@ output_comdat_type_unit (comdat_type_node *node)
 #if defined (OBJECT_FORMAT_ELF)
   tree comdat_key;
 #endif
+  htab_t extern_map;
 
   /* First mark all the DIEs in this CU so we know which get local refs.  */
   mark_dies (node->root_die);
 
-  build_abbrev_table (node->root_die);
+  extern_map = optimize_external_refs (node->root_die);
+
+  build_abbrev_table (node->root_die, extern_map);
+
+  htab_delete (extern_map);
 
   /* Initialize the beginning DIE offset - and calculate sizes/offsets.  */
   next_die_offset = DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE;
   calc_die_sizes (node->root_die);
 
 #if defined (OBJECT_FORMAT_ELF)
-  secname = ".debug_types";
+  if (!dwarf_split_debug_info)
+    secname = ".debug_types";
+  else
+    secname = ".debug_types.dwo";
+
   tmp = XALLOCAVEC (char, 4 + DWARF_TYPE_SIGNATURE_SIZE * 2);
   sprintf (tmp, "wt.");
   for (i = 0; i < DWARF_TYPE_SIGNATURE_SIZE; i++)
@@ -8671,6 +8811,38 @@ output_comdat_type_unit (comdat_type_node *node)
   output_die (node->root_die);
 
   unmark_dies (node->root_die);
+
+#if defined (OBJECT_FORMAT_ELF)
+  if (dwarf_split_debug_info)
+    {
+      /* Produce the skeleton type-unit header.  */
+      const char *secname = ".debug_types";
+
+      targetm.asm_out.named_section (secname,
+                                     SECTION_DEBUG | SECTION_LINKONCE,
+                                     comdat_key);
+      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,
+                           DWARF_COMPILE_UNIT_HEADER_SIZE
+                           - DWARF_INITIAL_LENGTH_SIZE
+                           + size_of_die (get_skeleton_type_unit ())
+                           + DWARF_TYPE_SIGNATURE_SIZE + DWARF_OFFSET_SIZE,
+                           "Length of Type Unit Info");
+      dw2_asm_output_data (2, dwarf_version, "DWARF version number");
+      dw2_asm_output_offset (DWARF_OFFSET_SIZE,
+                             debug_skeleton_abbrev_section_label,
+                             debug_abbrev_section,
+                             "Offset Into Abbrev. Section");
+      dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
+      output_signature (node->signature, "Type Signature");
+      dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, "Offset to Type DIE");
+
+      output_die (get_skeleton_type_unit ());
+    }
+#endif
 }
 
 /* Return the DWARF2/3 pubname associated with a decl.  */
@@ -8688,27 +8860,47 @@ dwarf2_name (tree decl, int scope)
 static void
 add_pubname_string (const char *str, dw_die_ref die)
 {
-  if (targetm.want_debug_pub_sections)
-    {
-      pubname_entry e;
+  pubname_entry e;
 
-      e.die = die;
-      e.name = xstrdup (str);
-      VEC_safe_push (pubname_entry, gc, pubname_table, &e);
-    }
+  e.die = die;
+  e.name = xstrdup (str);
+  vec_safe_push (pubname_table, e);
 }
 
 static void
 add_pubname (tree decl, dw_die_ref die)
 {
-  if (targetm.want_debug_pub_sections && TREE_PUBLIC (decl))
+  if (!want_pubnames ())
+    return;
+
+  /* Don't add items to the table when we expect that the consumer will have
+     just read the enclosing die.  For example, if the consumer is looking at a
+     class_member, it will either be inside the class already, or will have just
+     looked up the class to find the member.  Either way, searching the class is
+     faster than searching the index.  */
+  if ((TREE_PUBLIC (decl) && !class_scope_p (die->die_parent))
+      || is_cu_die (die->die_parent) || is_namespace_die (die->die_parent))
     {
       const char *name = dwarf2_name (decl, 1);
+
       if (name)
        add_pubname_string (name, die);
     }
 }
 
+/* Add an enumerator to the pubnames section.  */
+
+static void
+add_enumerator_pubname (const char *scope_name, dw_die_ref die)
+{
+  pubname_entry e;
+
+  gcc_assert (scope_name);
+  e.name = concat (scope_name, get_AT_string (die, DW_AT_name), NULL);
+  e.die = die;
+  vec_safe_push (pubname_table, e);
+}
+
 /* Add a new entry to .debug_pubtypes if appropriate.  */
 
 static void
@@ -8716,39 +8908,54 @@ add_pubtype (tree decl, dw_die_ref die)
 {
   pubname_entry e;
 
-  if (!targetm.want_debug_pub_sections)
+  if (!want_pubnames ())
     return;
 
-  e.name = NULL;
   if ((TREE_PUBLIC (decl)
-       || is_cu_die (die->die_parent))
+       || is_cu_die (die->die_parent) || is_namespace_die (die->die_parent))
       && (die->die_tag == DW_TAG_typedef || COMPLETE_TYPE_P (decl)))
     {
-      e.die = die;
-      if (TYPE_P (decl))
-       {
-         if (TYPE_NAME (decl))
-           {
-             if (TREE_CODE (TYPE_NAME (decl)) == IDENTIFIER_NODE)
-               e.name = IDENTIFIER_POINTER (TYPE_NAME (decl));
-             else if (TREE_CODE (TYPE_NAME (decl)) == TYPE_DECL
-                      && DECL_NAME (TYPE_NAME (decl)))
-               e.name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (decl)));
-             else
-              e.name = xstrdup ((const char *) get_AT_string (die, DW_AT_name));
-           }
+      tree scope = NULL;
+      const char *scope_name = "";
+      const char *sep = is_cxx () ? "::" : ".";
+      const char *name;
+
+      scope = TYPE_P (decl) ? TYPE_CONTEXT (decl) : NULL;
+      if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
+        {
+          scope_name = lang_hooks.dwarf_name (scope, 1);
+          if (scope_name != NULL && scope_name[0] != '\0')
+            scope_name = concat (scope_name, sep, NULL);
+          else
+            scope_name = "";
        }
+
+      if (TYPE_P (decl))
+        name = type_tag (decl);
       else
-       {
-         e.name = dwarf2_name (decl, 1);
-         if (e.name)
-           e.name = xstrdup (e.name);
-       }
+        name = lang_hooks.dwarf_name (decl, 1);
 
       /* If we don't have a name for the type, there's no point in adding
         it to the table.  */
-      if (e.name && e.name[0] != '\0')
-       VEC_safe_push (pubname_entry, gc, pubtype_table, &e);
+      if (name != NULL && name[0] != '\0')
+        {
+          e.die = die;
+          e.name = concat (scope_name, name, NULL);
+          vec_safe_push (pubtype_table, e);
+        }
+
+      /* Although it might be more consistent to add the pubinfo for the
+         enumerators as their dies are created, they should only be added if the
+         enum type meets the criteria above.  So rather than re-check the parent
+         enum type whenever an enumerator die is created, just output them all
+         here.  This isn't protected by the name conditional because anonymous
+         enums don't have names.  */
+      if (die->die_tag == DW_TAG_enumeration_type)
+        {
+          dw_die_ref c;
+
+          FOR_EACH_CHILD (die, c, add_enumerator_pubname (scope_name, c));
+        }
     }
 }
 
@@ -8756,12 +8963,18 @@ add_pubtype (tree decl, dw_die_ref die)
    visible names; or the public types table used to find type definitions.  */
 
 static void
-output_pubnames (VEC (pubname_entry, gc) * names)
+output_pubnames (vec<pubname_entry, va_gc> *names)
 {
   unsigned i;
   unsigned long pubnames_length = size_of_pubnames (names);
   pubname_ref pub;
 
+  if (!want_pubnames () || !info_section_emitted)
+    return;
+  if (names == pubname_table)
+    switch_to_section (debug_pubnames_section);
+  else
+    switch_to_section (debug_pubtypes_section);
   if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
     dw2_asm_output_data (4, 0xffffffff,
       "Initial length escape value indicating 64-bit DWARF extension");
@@ -8773,14 +8986,25 @@ output_pubnames (VEC (pubname_entry, gc) * names)
                         "Length of Public Type Names Info");
   /* Version number for pubnames/pubtypes is still 2, even in DWARF3.  */
   dw2_asm_output_data (2, 2, "DWARF Version");
-  dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
-                        debug_info_section,
-                        "Offset of Compilation Unit Info");
+  if (dwarf_split_debug_info)
+    dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
+                           debug_skeleton_info_section,
+                           "Offset of Compilation Unit Info");
+  else
+    dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
+                           debug_info_section,
+                           "Offset of Compilation Unit Info");
   dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset,
                       "Compilation Unit Length");
 
-  FOR_EACH_VEC_ELT (pubname_entry, names, i, pub)
+  FOR_EACH_VEC_ELT (*names, i, pub)
     {
+      /* Enumerator names are part of the pubname table, but the parent
+         DW_TAG_enumeration_type die may have been pruned.  Don't output
+         them if that is the case.  */
+      if (pub->die->die_tag == DW_TAG_enumerator && !pub->die->die_mark)
+        continue;
+
       /* We shouldn't see pubnames for DIEs outside of the main CU.  */
       if (names == pubname_table)
        gcc_assert (pub->die->die_mark);
@@ -8789,8 +9013,23 @@ output_pubnames (VEC (pubname_entry, gc) * names)
          || pub->die->die_offset != 0
          || !flag_eliminate_unused_debug_types)
        {
-         dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset,
-                              "DIE offset");
+         dw_offset die_offset = pub->die->die_offset;
+
+         /* If we're putting types in their own .debug_types sections,
+            the .debug_pubtypes table will still point to the compile
+            unit (not the type unit), so we want to use the offset of
+            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;
+
+             if (type_node != NULL)
+               die_offset = (type_node->skeleton_die != NULL
+                             ? type_node->skeleton_die->die_offset
+                             : 0);
+           }
+
+         dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset");
 
          dw2_asm_output_nstring (pub->name, -1, "external name");
        }
@@ -8815,9 +9054,14 @@ output_aranges (unsigned long aranges_length)
                       "Length of Address Ranges Info");
   /* Version number for aranges is still 2, even in DWARF3.  */
   dw2_asm_output_data (2, 2, "DWARF Version");
-  dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
-                        debug_info_section,
-                        "Offset of Compilation Unit Info");
+  if (dwarf_split_debug_info)
+    dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
+                           debug_skeleton_info_section,
+                           "Offset of Compilation Unit Info");
+  else
+    dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
+                           debug_info_section,
+                           "Offset of Compilation Unit Info");
   dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address");
   dw2_asm_output_data (1, 0, "Size of Segment Descriptor");
 
@@ -8856,8 +9100,10 @@ output_aranges (unsigned long aranges_length)
       unsigned fde_idx;
       dw_fde_ref fde;
 
-      FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, fde_idx, fde)
+      FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde)
        {
+         if (DECL_IGNORED_P (fde->decl))
+           continue;
          if (!fde->in_std_section)
            {
              dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
@@ -8912,12 +9158,14 @@ add_ranges (const_tree block)
   return add_ranges_num (block ? BLOCK_NUMBER (block) : 0);
 }
 
-/* Add a new entry to .debug_ranges corresponding to a pair of
-   labels.  */
+/* Add a new entry to .debug_ranges corresponding to a pair of labels.
+   When using dwarf_split_debug_info, address attributes in dies destined
+   for the final executable should be direct references--setting the
+   parameter force_direct ensures this behavior.  */
 
 static void
 add_ranges_by_labels (dw_die_ref die, const char *begin, const char *end,
-                     bool *added)
+                      bool *added, bool force_direct)
 {
   unsigned int in_use = ranges_by_label_in_use;
   unsigned int offset;
@@ -8940,7 +9188,7 @@ add_ranges_by_labels (dw_die_ref die, const char *begin, const char *end,
   offset = add_ranges_num (-(int)in_use - 1);
   if (!*added)
     {
-      add_AT_range_list (die, DW_AT_ranges, offset);
+      add_AT_range_list (die, DW_AT_ranges, offset, force_direct);
       *added = true;
     }
 }
@@ -9373,7 +9621,7 @@ output_one_line_info_table (dw_line_info_table *table)
   dw_line_info_entry *ent;
   size_t i;
 
-  FOR_EACH_VEC_ELT (dw_line_info_entry, table->entries, i, ent)
+  FOR_EACH_VEC_SAFE_ELT (table->entries, i, ent)
     {
       switch (ent->opcode)
        {
@@ -9477,7 +9725,7 @@ output_one_line_info_table (dw_line_info_table *table)
    information goes into the .debug_line section.  */
 
 static void
-output_line_info (void)
+output_line_info (bool prologue_only)
 {
   char l1[20], l2[20], p1[20], p2[20];
   int ver = dwarf_version;
@@ -9547,13 +9795,19 @@ output_line_info (void)
   /* Write out the information about the files we use.  */
   output_file_names ();
   ASM_OUTPUT_LABEL (asm_out_file, p2);
+  if (prologue_only)
+    {
+      /* Output the marker for the end of the line number info.  */
+      ASM_OUTPUT_LABEL (asm_out_file, l2);
+      return;
+    }
 
   if (separate_line_info)
     {
       dw_line_info_table *table;
       size_t i;
 
-      FOR_EACH_VEC_ELT (dw_line_info_table_p, separate_line_info, i, table)
+      FOR_EACH_VEC_ELT (*separate_line_info, i, table)
        if (table->in_use)
          {
            output_one_line_info_table (table);
@@ -9673,6 +9927,7 @@ base_type_die (tree type)
   add_AT_unsigned (base_type_result, DW_AT_byte_size,
                   int_size_in_bytes (type));
   add_AT_unsigned (base_type_result, DW_AT_encoding, encoding);
+  add_pubtype (type, base_type_result);
 
   return base_type_result;
 }
@@ -9741,13 +9996,13 @@ static inline double_int
 double_int_type_size_in_bits (const_tree type)
 {
   if (TREE_CODE (type) == ERROR_MARK)
-    return uhwi_to_double_int (BITS_PER_WORD);
+    return double_int::from_uhwi (BITS_PER_WORD);
   else if (TYPE_SIZE (type) == NULL_TREE)
     return double_int_zero;
   else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
     return tree_to_double_int (TYPE_SIZE (type));
   else
-    return uhwi_to_double_int (TYPE_ALIGN (type));
+    return double_int::from_uhwi (TYPE_ALIGN (type));
 }
 
 /*  Given a pointer to a tree node for a subrange type, return a pointer
@@ -10175,7 +10430,7 @@ dbx_reg_number (const_rtx rtl)
   gcc_assert (regno < FIRST_PSEUDO_REGISTER);
 
 #ifdef LEAF_REG_REMAP
-  if (current_function_uses_only_leaf_regs)
+  if (crtl->uses_only_leaf_regs)
     {
       int leaf_reg = LEAF_REG_REMAP (regno);
       if (leaf_reg != -1)
@@ -10183,7 +10438,9 @@ dbx_reg_number (const_rtx rtl)
     }
 #endif
 
-  return DBX_REGISTER_NUMBER (regno);
+  regno = DBX_REGISTER_NUMBER (regno);
+  gcc_assert (regno != INVALID_REGNUM);
+  return regno;
 }
 
 /* Optionally add a DW_OP_piece term to a location description expression.
@@ -10243,7 +10500,12 @@ reg_loc_descriptor (rtx rtl, enum var_init_status initialized)
   if (hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)] > 1 || regs)
     return multiple_reg_loc_descriptor (rtl, regs, initialized);
   else
-    return one_reg_loc_descriptor (dbx_reg_number (rtl), initialized);
+    {
+      unsigned int dbx_regnum = dbx_reg_number (rtl);
+      if (dbx_regnum == IGNORED_DWARF_REGNUM)
+       return 0;
+      return one_reg_loc_descriptor (dbx_regnum, initialized);
+    }
 }
 
 /* Return a location descriptor that designates a machine register for
@@ -10279,7 +10541,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs,
 
   reg = REGNO (rtl);
 #ifdef LEAF_REG_REMAP
-  if (current_function_uses_only_leaf_regs)
+  if (crtl->uses_only_leaf_regs)
     {
       int leaf_reg = LEAF_REG_REMAP (reg);
       if (leaf_reg != -1)
@@ -10567,7 +10829,9 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset,
      argument pointer and soft frame pointer rtx's.  */
   if (reg == arg_pointer_rtx || reg == frame_pointer_rtx)
     {
-      rtx elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
+      rtx elim = (ira_use_lra_p
+                 ? lra_eliminate_regs (reg, VOIDmode, NULL_RTX)
+                 : eliminate_regs (reg, VOIDmode, NULL_RTX));
 
       if (elim != reg)
        {
@@ -10605,7 +10869,7 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset,
 
   regno = REGNO (reg);
 #ifdef LEAF_REG_REMAP
-  if (current_function_uses_only_leaf_regs)
+  if (crtl->uses_only_leaf_regs)
     {
       int leaf_reg = LEAF_REG_REMAP (regno);
       if (leaf_reg != -1)
@@ -10711,12 +10975,12 @@ const_ok_for_output_1 (rtx *rtlp, void *data ATTRIBUTE_UNUSED)
         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.  */
-      if (XVECLEN (rtl, 0) != 1
+        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_DECL (XVECEXP (rtl, 0, 0)) == NULL
-         || TREE_CODE (SYMBOL_REF_DECL (XVECEXP (rtl, 0, 0))) != VAR_DECL
-         || !DECL_THREAD_LOCAL_P (SYMBOL_REF_DECL (XVECEXP (rtl, 0, 0))))
+         || SYMBOL_REF_TLS_MODEL (XVECEXP (rtl, 0, 0)) == TLS_MODEL_NONE)
        inform (current_function_decl
                ? DECL_SOURCE_LOCATION (current_function_decl)
                : UNKNOWN_LOCATION,
@@ -11218,7 +11482,7 @@ clz_loc_descriptor (rtx rtl, enum machine_mode mode,
   if (GET_MODE_CLASS (mode) != MODE_INT
       || GET_MODE (XEXP (rtl, 0)) != mode
       || (GET_CODE (rtl) == CLZ
-         && GET_MODE_BITSIZE (mode) > 2 * HOST_BITS_PER_WIDE_INT))
+         && GET_MODE_BITSIZE (mode) > HOST_BITS_PER_DOUBLE_INT))
     return NULL;
 
   op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
@@ -11561,17 +11825,6 @@ parameter_ref_descriptor (rtx rtl)
   return ret;
 }
 
-/* Helper function to get mode of MEM's address.  */
-
-enum machine_mode
-get_address_mode (rtx mem)
-{
-  enum machine_mode mode = GET_MODE (XEXP (mem, 0));
-  if (mode != VOIDmode)
-    return mode;
-  return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem));
-}
-
 /* The following routine converts the RTL for a variable or parameter
    (resident in memory) into an equivalent Dwarf representation of a
    mechanism for getting the address of that same variable onto the top of a
@@ -11597,6 +11850,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
   dw_loc_descr_ref mem_loc_result = NULL;
   enum dwarf_location_atom op;
   dw_loc_descr_ref op0, op1;
+  rtx inner = NULL_RTX;
 
   if (mode == VOIDmode)
     mode = GET_MODE (rtl);
@@ -11626,35 +11880,39 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
         contains the given subreg.  */
       if (!subreg_lowpart_p (rtl))
        break;
+      inner = SUBREG_REG (rtl);
+    case TRUNCATE:
+      if (inner == NULL_RTX)
+        inner = XEXP (rtl, 0);
       if (GET_MODE_CLASS (mode) == MODE_INT
-         && GET_MODE_CLASS (GET_MODE (SUBREG_REG (rtl))) == MODE_INT
+         && GET_MODE_CLASS (GET_MODE (inner)) == MODE_INT
          && (GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
 #ifdef POINTERS_EXTEND_UNSIGNED
              || (mode == Pmode && mem_mode != VOIDmode)
 #endif
             )
-         && GET_MODE_SIZE (GET_MODE (SUBREG_REG (rtl))) <= DWARF2_ADDR_SIZE)
+         && GET_MODE_SIZE (GET_MODE (inner)) <= DWARF2_ADDR_SIZE)
        {
-         mem_loc_result = mem_loc_descriptor (SUBREG_REG (rtl),
-                                              GET_MODE (SUBREG_REG (rtl)),
+         mem_loc_result = mem_loc_descriptor (inner,
+                                              GET_MODE (inner),
                                               mem_mode, initialized);
          break;
        }
       if (dwarf_strict)
        break;
-      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (rtl))))
+      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (inner)))
        break;
-      if (GET_MODE_SIZE (mode) != GET_MODE_SIZE (GET_MODE (SUBREG_REG (rtl)))
+      if (GET_MODE_SIZE (mode) != GET_MODE_SIZE (GET_MODE (inner))
          && (GET_MODE_CLASS (mode) != MODE_INT
-             || GET_MODE_CLASS (GET_MODE (SUBREG_REG (rtl))) != MODE_INT))
+             || GET_MODE_CLASS (GET_MODE (inner)) != MODE_INT))
        break;
       else
        {
          dw_die_ref type_die;
          dw_loc_descr_ref cvt;
 
-         mem_loc_result = mem_loc_descriptor (SUBREG_REG (rtl),
-                                              GET_MODE (SUBREG_REG (rtl)),
+         mem_loc_result = mem_loc_descriptor (inner,
+                                              GET_MODE (inner),
                                               mem_mode, initialized);
          if (mem_loc_result == NULL)
            break;
@@ -11666,7 +11924,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
              break;
            }
          if (GET_MODE_SIZE (mode)
-             != GET_MODE_SIZE (GET_MODE (SUBREG_REG (rtl))))
+             != GET_MODE_SIZE (GET_MODE (inner)))
            cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
          else
            cvt = new_loc_descr (DW_OP_GNU_reinterpret, 0, 0);
@@ -11680,12 +11938,15 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
     case REG:
       if (GET_MODE_CLASS (mode) != MODE_INT
          || (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
+             && rtl != arg_pointer_rtx
+             && rtl != frame_pointer_rtx
 #ifdef POINTERS_EXTEND_UNSIGNED
              && (mode != Pmode || mem_mode == VOIDmode)
 #endif
              ))
        {
          dw_die_ref type_die;
+         unsigned int dbx_regnum;
 
          if (dwarf_strict)
            break;
@@ -11695,8 +11956,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
                                         GET_MODE_CLASS (mode) == MODE_INT);
          if (type_die == NULL)
            break;
+
+         dbx_regnum = dbx_reg_number (rtl);
+         if (dbx_regnum == IGNORED_DWARF_REGNUM)
+           break;
          mem_loc_result = new_loc_descr (DW_OP_GNU_regval_type,
-                                         dbx_reg_number (rtl), 0);
+                                         dbx_regnum, 0);
          mem_loc_result->dw_loc_oprnd2.val_class = dw_val_class_die_ref;
          mem_loc_result->dw_loc_oprnd2.v.val_die_ref.die = type_die;
          mem_loc_result->dw_loc_oprnd2.v.val_die_ref.external = 0;
@@ -11864,14 +12129,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
          if (!targetm.have_tls || !targetm.asm_out.output_dwarf_dtprel)
            break;
 
-         /* We used to emit DW_OP_addr here, but that's wrong, since
-            DW_OP_addr should be relocated by the debug info consumer,
-            while DW_OP_GNU_push_tls_address operand should not.  */
-         temp = new_loc_descr (DWARF2_ADDR_SIZE == 4
-                               ? DW_OP_const4u : DW_OP_const8u, 0, 0);
-         temp->dw_loc_oprnd1.val_class = dw_val_class_addr;
-         temp->dw_loc_oprnd1.v.val_addr = rtl;
-         temp->dtprel = true;
+          temp = new_addr_loc_descr (rtl, dtprel_true);
 
          mem_loc_result = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
          add_loc_descr (&mem_loc_result, temp);
@@ -11883,10 +12141,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
        break;
 
     symref:
-      mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
-      mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr;
-      mem_loc_result->dw_loc_oprnd1.v.val_addr = rtl;
-      VEC_safe_push (rtx, gc, used_rtx_array, rtl);
+      mem_loc_result = new_addr_loc_descr (rtl, dtprel_false);
+      vec_safe_push (used_rtx_array, rtl);
       break;
 
     case CONCAT:
@@ -11907,9 +12163,13 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
            op0 = mem_loc_descriptor (ENTRY_VALUE_EXP (rtl), mode,
                                      VOIDmode, VAR_INIT_STATUS_INITIALIZED);
          else
-           op0
-             = one_reg_loc_descriptor (dbx_reg_number (ENTRY_VALUE_EXP (rtl)),
-                                       VAR_INIT_STATUS_INITIALIZED);
+           {
+              unsigned int dbx_regnum = dbx_reg_number (ENTRY_VALUE_EXP (rtl));
+             if (dbx_regnum == IGNORED_DWARF_REGNUM)
+               return NULL;
+             op0 = one_reg_loc_descriptor (dbx_regnum,
+                                           VAR_INIT_STATUS_INITIALIZED);
+           }
        }
       else if (MEM_P (ENTRY_VALUE_EXP (rtl))
               && REG_P (XEXP (ENTRY_VALUE_EXP (rtl), 0)))
@@ -11952,7 +12212,9 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
     case PLUS:
     plus:
       if (is_based_loc (rtl)
-         && GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
+         && (GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
+             || XEXP (rtl, 0) == arg_pointer_rtx
+             || XEXP (rtl, 0) == frame_pointer_rtx)
          && GET_MODE_CLASS (mode) == MODE_INT)
        mem_loc_result = based_loc_descr (XEXP (rtl, 0),
                                          INTVAL (XEXP (rtl, 1)),
@@ -12145,7 +12407,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
        }
       if (!dwarf_strict
          && (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT
-             || GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT))
+             || GET_MODE_BITSIZE (mode) == HOST_BITS_PER_DOUBLE_INT))
        {
          dw_die_ref type_die = base_type_for_mode (mode, 1);
          enum machine_mode amode;
@@ -12181,7 +12443,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
              mem_loc_result->dw_loc_oprnd2.val_class
                = dw_val_class_const_double;
              mem_loc_result->dw_loc_oprnd2.v.val_double
-               = shwi_to_double_int (INTVAL (rtl));
+               = double_int::from_shwi (INTVAL (rtl));
            }
        }
       break;
@@ -12197,7 +12459,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
             adequately represented.  We output CONST_DOUBLEs as blocks.  */
          if (mode == VOIDmode
              || (GET_MODE (rtl) == VOIDmode
-                 && GET_MODE_BITSIZE (mode) != 2 * HOST_BITS_PER_WIDE_INT))
+                 && GET_MODE_BITSIZE (mode) != HOST_BITS_PER_DOUBLE_INT))
            break;
          type_die = base_type_for_mode (mode,
                                         GET_MODE_CLASS (mode) == MODE_INT);
@@ -12419,7 +12681,6 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
       break;
 
     case COMPARE:
-    case TRUNCATE:
       /* In theory, we could implement the above.  */
       /* DWARF cannot represent the unsigned compare operations
         natively.  */
@@ -12463,6 +12724,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
     case CONST_VECTOR:
     case CONST_FIXED:
     case CLRSB:
+    case CLOBBER:
       /* If delegitimize_address couldn't do anything with the UNSPEC, we
         can't express it in the debug info.  This can happen e.g. with some
         TLS UNSPECs.  */
@@ -12740,7 +13002,7 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
                  double_int val = rtx_to_double_int (elt);
 
                  if (elt_size <= sizeof (HOST_WIDE_INT))
-                   insert_int (double_int_to_shwi (val), elt_size, p);
+                   insert_int (val.to_shwi (), elt_size, p);
                  else
                    {
                      gcc_assert (elt_size == 2 * sizeof (HOST_WIDE_INT));
@@ -12772,8 +13034,8 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
 
     case CONST:
       if (mode == VOIDmode
-         || GET_CODE (XEXP (rtl, 0)) == CONST_INT
-         || GET_CODE (XEXP (rtl, 0)) == CONST_DOUBLE
+         || CONST_SCALAR_INT_P (XEXP (rtl, 0))
+         || CONST_DOUBLE_AS_FLOAT_P (XEXP (rtl, 0))
          || GET_CODE (XEXP (rtl, 0)) == CONST_VECTOR)
        {
          loc_result = loc_descriptor (XEXP (rtl, 0), mode, initialized);
@@ -12787,11 +13049,9 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
       if (mode != VOIDmode && GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE
          && (dwarf_version >= 4 || !dwarf_strict))
        {
-         loc_result = new_loc_descr (DW_OP_addr, 0, 0);
-         loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr;
-         loc_result->dw_loc_oprnd1.v.val_addr = rtl;
+         loc_result = new_addr_loc_descr (rtl, dtprel_false);
          add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0));
-         VEC_safe_push (rtx, gc, used_rtx_array, rtl);
+         vec_safe_push (used_rtx_array, rtl);
        }
       break;
 
@@ -13286,7 +13546,7 @@ add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
 
 /* Given two lists RET and LIST
    produce location list that is result of adding expression in LIST
-   to expression in RET on each possition in program.
+   to expression in RET on each position in program.
    Might be destructive on both RET and LIST.
 
    TODO: We handle only simple cases of RET or LIST having at most one
@@ -13353,8 +13613,8 @@ cst_pool_loc_descr (tree loc)
 }
 
 /* Return dw_loc_list representing address of addr_expr LOC
-   by looking for innder INDIRECT_REF expression and turing it
-   into simple arithmetics.  */
+   by looking for inner INDIRECT_REF expression and turning
+   it into simple arithmetics.  */
 
 static dw_loc_list_ref
 loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
@@ -13362,8 +13622,7 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
   tree obj, offset;
   HOST_WIDE_INT bitsize, bitpos, bytepos;
   enum machine_mode mode;
-  int volatilep;
-  int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc));
+  int unsignedp, volatilep = 0;
   dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
 
   obj = get_inner_reference (TREE_OPERAND (loc, 0),
@@ -13490,9 +13749,8 @@ loc_list_from_tree (tree loc, int want_address)
       if (DECL_THREAD_LOCAL_P (loc))
        {
          rtx rtl;
-         enum dwarf_location_atom first_op;
-         enum dwarf_location_atom second_op;
-         bool dtprel = false;
+         enum dwarf_location_atom tls_op;
+         enum dtprel_bool dtprel = dtprel_false;
 
          if (targetm.have_tls)
            {
@@ -13509,9 +13767,8 @@ loc_list_from_tree (tree loc, int want_address)
                  operand shouldn't be.  */
              if (DECL_EXTERNAL (loc) && !targetm.binds_local_p (loc))
                return 0;
-             first_op = DWARF2_ADDR_SIZE == 4 ? DW_OP_const4u : DW_OP_const8u;
-             dtprel = true;
-             second_op = DW_OP_GNU_push_tls_address;
+             dtprel = dtprel_true;
+             tls_op = DW_OP_GNU_push_tls_address;
            }
          else
            {
@@ -13523,8 +13780,7 @@ loc_list_from_tree (tree loc, int want_address)
                 no longer appear in gimple code.  We used the control
                 variable in specific so that we could pick it up here.  */
              loc = DECL_VALUE_EXPR (loc);
-             first_op = DW_OP_addr;
-             second_op = DW_OP_form_tls_address;
+              tls_op = DW_OP_form_tls_address;
            }
 
          rtl = rtl_for_decl_location (loc);
@@ -13537,12 +13793,8 @@ loc_list_from_tree (tree loc, int want_address)
          if (! CONSTANT_P (rtl))
            return 0;
 
-         ret = new_loc_descr (first_op, 0, 0);
-         ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
-         ret->dw_loc_oprnd1.v.val_addr = rtl;
-         ret->dtprel = dtprel;
-
-         ret1 = new_loc_descr (second_op, 0, 0);
+          ret = new_addr_loc_descr (rtl, dtprel);
+          ret1 = new_loc_descr (tls_op, 0, 0);
          add_loc_descr (&ret, ret1);
 
          have_address = 1;
@@ -13587,11 +13839,7 @@ loc_list_from_tree (tree loc, int want_address)
            return 0;
          }
        else if (CONSTANT_P (rtl) && const_ok_for_output (rtl))
-         {
-           ret = new_loc_descr (DW_OP_addr, 0, 0);
-           ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
-           ret->dw_loc_oprnd1.v.val_addr = rtl;
-         }
+          ret = new_addr_loc_descr (rtl, dtprel_false);
        else
          {
            enum machine_mode mode, mem_mode;
@@ -13653,8 +13901,7 @@ loc_list_from_tree (tree loc, int want_address)
        tree obj, offset;
        HOST_WIDE_INT bitsize, bitpos, bytepos;
        enum machine_mode mode;
-       int volatilep;
-       int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc));
+       int unsignedp, volatilep = 0;
 
        obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
                                   &unsignedp, &volatilep, false);
@@ -14071,11 +14318,11 @@ simple_decl_align_in_bits (const_tree decl)
 static inline double_int
 round_up_to_align (double_int t, unsigned int align)
 {
-  double_int alignd = uhwi_to_double_int (align);
-  t = double_int_add (t, alignd);
-  t = double_int_add (t, double_int_minus_one);
-  t = double_int_div (t, alignd, true, TRUNC_DIV_EXPR);
-  t = double_int_mul (t, alignd);
+  double_int alignd = double_int::from_uhwi (align);
+  t += alignd;
+  t += double_int_minus_one;
+  t = t.div (alignd, true, TRUNC_DIV_EXPR);
+  t *= alignd;
   return t;
 }
 
@@ -14182,23 +14429,21 @@ field_byte_offset (const_tree decl)
 
       /* Figure out the bit-distance from the start of the structure to
         the "deepest" bit of the bit-field.  */
-      deepest_bitpos = double_int_add (bitpos_int, field_size_in_bits);
+      deepest_bitpos = bitpos_int + field_size_in_bits;
 
       /* This is the tricky part.  Use some fancy footwork to deduce
         where the lowest addressed bit of the containing object must
         be.  */
-      object_offset_in_bits
-       = double_int_sub (deepest_bitpos, type_size_in_bits);
+      object_offset_in_bits = deepest_bitpos - type_size_in_bits;
 
       /* Round up to type_align by default.  This works best for
         bitfields.  */
       object_offset_in_bits
        = round_up_to_align (object_offset_in_bits, type_align_in_bits);
 
-      if (double_int_ucmp (object_offset_in_bits, bitpos_int) > 0)
+      if (object_offset_in_bits.ugt (bitpos_int))
        {
-         object_offset_in_bits
-           = double_int_sub (deepest_bitpos, type_size_in_bits);
+         object_offset_in_bits = deepest_bitpos - type_size_in_bits;
 
          /* Round up to decl_align instead.  */
          object_offset_in_bits
@@ -14210,10 +14455,9 @@ field_byte_offset (const_tree decl)
     object_offset_in_bits = bitpos_int;
 
   object_offset_in_bytes
-    = double_int_div (object_offset_in_bits,
-                     uhwi_to_double_int (BITS_PER_UNIT), true,
-                     TRUNC_DIV_EXPR);
-  return double_int_to_shwi (object_offset_in_bytes);
+    = object_offset_in_bits.div (double_int::from_uhwi (BITS_PER_UNIT),
+                                true, TRUNC_DIV_EXPR);
+  return object_offset_in_bytes.to_shwi ();
 }
 \f
 /* The following routines define various Dwarf attributes and any data
@@ -14350,16 +14594,7 @@ add_data_member_location_attribute (dw_die_ref die, tree decl)
          /* The DWARF2 standard says that we should assume that the structure
             address is already on the stack, so we can specify a structure
             field address by using DW_OP_plus_uconst.  */
-
-#ifdef MIPS_DEBUGGING_INFO
-         /* ??? The SGI dwarf reader does not handle the DW_OP_plus_uconst
-            operator correctly.  It works only if we leave the offset on the
-            stack.  */
-         op = DW_OP_constu;
-#else
          op = DW_OP_plus_uconst;
-#endif
-
          loc_descr = new_loc_descr (op, offset, 0);
        }
     }
@@ -14498,7 +14733,7 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
                double_int val = rtx_to_double_int (elt);
 
                if (elt_size <= sizeof (HOST_WIDE_INT))
-                 insert_int (double_int_to_shwi (val), elt_size, p);
+                 insert_int (val.to_shwi (), elt_size, p);
                else
                  {
                    gcc_assert (elt_size == 2 * sizeof (HOST_WIDE_INT));
@@ -14529,12 +14764,10 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
          dw_loc_descr_ref loc_result;
          resolve_one_addr (&rtl, NULL);
        rtl_addr:
-         loc_result = new_loc_descr (DW_OP_addr, 0, 0);
-         loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr;
-         loc_result->dw_loc_oprnd1.v.val_addr = rtl;
+          loc_result = new_addr_loc_descr (rtl, dtprel_false);
          add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0));
          add_AT_loc (die, DW_AT_location, loc_result);
-         VEC_safe_push (rtx, gc, used_rtx_array, rtl);
+         vec_safe_push (used_rtx_array, rtl);
          return true;
        }
       return false;
@@ -14608,7 +14841,7 @@ reference_to_unused (tree * tp, int * walk_subtrees,
   else if (TREE_CODE (*tp) == VAR_DECL)
     {
       struct varpool_node *node = varpool_get_node (*tp);
-      if (!node || !node->needed)
+      if (!node || !node->analyzed)
        return *tp;
     }
   else if (TREE_CODE (*tp) == FUNCTION_DECL
@@ -14687,7 +14920,7 @@ rtl_for_decl_init (tree init, tree type)
          case CONSTRUCTOR:
            if (TREE_CONSTANT (init))
              {
-               VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS (init);
+               vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (init);
                bool constant_p = true;
                tree value;
                unsigned HOST_WIDE_INT ix;
@@ -14887,11 +15120,12 @@ rtl_for_decl_location (tree decl)
               && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))
                   < UNITS_PER_WORD))
        {
+         enum machine_mode addr_mode = get_address_mode (rtl);
          int offset = (UNITS_PER_WORD
                        - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))));
 
          rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
-                            plus_constant (XEXP (rtl, 0), offset));
+                            plus_constant (addr_mode, XEXP (rtl, 0), offset));
        }
     }
   else if (TREE_CODE (decl) == VAR_DECL
@@ -14900,6 +15134,7 @@ rtl_for_decl_location (tree decl)
           && GET_MODE (rtl) != TYPE_MODE (TREE_TYPE (decl))
           && BYTES_BIG_ENDIAN)
     {
+      enum machine_mode addr_mode = get_address_mode (rtl);
       int rsize = GET_MODE_SIZE (GET_MODE (rtl));
       int dsize = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)));
 
@@ -14911,7 +15146,8 @@ rtl_for_decl_location (tree decl)
         else gdb will not be able to display it.  */
       if (rsize > dsize)
        rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
-                          plus_constant (XEXP (rtl, 0), rsize-dsize));
+                          plus_constant (addr_mode, XEXP (rtl, 0),
+                                         rsize - dsize));
     }
 
   /* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time constant,
@@ -14961,7 +15197,7 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
   enum machine_mode mode;
   HOST_WIDE_INT bitsize, bitpos;
   tree offset;
-  int volatilep = 0, unsignedp = 0;
+  int unsignedp, 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
@@ -15105,7 +15341,7 @@ defer_location (tree variable, dw_die_ref die)
   deferred_locations entry;
   entry.variable = variable;
   entry.die = die;
-  VEC_safe_push (deferred_locations, gc, deferred_locations_list, &entry);
+  vec_safe_push (deferred_locations_list, entry);
 }
 
 /* Helper function for tree_add_const_value_attribute.  Natively encode
@@ -15166,7 +15402,7 @@ native_encode_initializer (tree init, unsigned char *array, int size)
 
          min_index = tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0);
          memset (array, '\0', size);
-         FOR_EACH_VEC_ELT (constructor_elt, CONSTRUCTOR_ELTS (init), cnt, ce)
+         FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (init), cnt, ce)
            {
              tree val = ce->value;
              tree index = ce->index;
@@ -15212,7 +15448,7 @@ native_encode_initializer (tree init, unsigned char *array, int size)
          if (TREE_CODE (type) == RECORD_TYPE)
            field = TYPE_FIELDS (type);
 
-         FOR_EACH_VEC_ELT (constructor_elt, CONSTRUCTOR_ELTS (init), cnt, ce)
+         FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (init), cnt, ce)
            {
              tree val = ce->value;
              int pos, fieldsize;
@@ -15352,7 +15588,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
 
   /* ??? Bald assumption that the CIE opcode list does not contain
      advance opcodes.  */
-  FOR_EACH_VEC_ELT (dw_cfi_ref, cie_cfi_vec, ix, cfi)
+  FOR_EACH_VEC_ELT (*cie_cfi_vec, ix, cfi)
     lookup_cfa_1 (cfi, &next_cfa, &remember);
 
   last_cfa = next_cfa;
@@ -15368,7 +15604,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
       start_label = last_label = fde->dw_fde_second_begin;
     }
 
-  FOR_EACH_VEC_ELT (dw_cfi_ref, fde->dw_fde_cfi, ix, cfi)
+  FOR_EACH_VEC_SAFE_ELT (fde->dw_fde_cfi, ix, cfi)
     {
       switch (cfi->dw_cfi_opc)
        {
@@ -15452,7 +15688,9 @@ compute_frame_pointer_to_fb_displacement (HOST_WIDE_INT offset)
   offset += ARG_POINTER_CFA_OFFSET (current_function_decl);
 #endif
 
-  elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
+  elim = (ira_use_lra_p
+         ? lra_eliminate_regs (reg, VOIDmode, NULL_RTX)
+         : eliminate_regs (reg, VOIDmode, NULL_RTX));
   if (GET_CODE (elim) == PLUS)
     {
       offset += INTVAL (XEXP (elim, 1));
@@ -15765,6 +16003,7 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
 static void
 add_byte_size_attribute (dw_die_ref die, tree tree_node)
 {
+  dw_die_ref decl_die;
   unsigned size;
 
   switch (TREE_CODE (tree_node))
@@ -15776,6 +16015,12 @@ add_byte_size_attribute (dw_die_ref die, tree tree_node)
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
+      if (TREE_CODE (TYPE_SIZE_UNIT (tree_node)) == VAR_DECL
+         && (decl_die = lookup_decl_die (TYPE_SIZE_UNIT (tree_node))))
+       {
+         add_AT_die_ref (die, DW_AT_byte_size, decl_die);
+         return;
+       }
       size = int_size_in_bytes (tree_node);
       break;
     case FIELD_DECL:
@@ -15979,7 +16224,7 @@ add_src_coords_attributes (dw_die_ref die, tree decl)
 {
   expanded_location s;
 
-  if (DECL_SOURCE_LOCATION (decl) == UNKNOWN_LOCATION)
+  if (LOCATION_LOCUS (DECL_SOURCE_LOCATION (decl)) == UNKNOWN_LOCATION)
     return;
   s = expand_location (DECL_SOURCE_LOCATION (decl));
   add_AT_file (die, DW_AT_decl_file, lookup_filename (s.file));
@@ -16039,8 +16284,8 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
   if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
     {
       add_AT_addr (die, DW_AT_VMS_rtnbeg_pd_address,
-                  XEXP (DECL_RTL (decl), 0));
-      VEC_safe_push (rtx, gc, used_rtx_array, XEXP (DECL_RTL (decl), 0));
+                  XEXP (DECL_RTL (decl), 0), false);
+      vec_safe_push (used_rtx_array, XEXP (DECL_RTL (decl), 0));
     }
 #endif /* VMS_DEBUGGING_INFO */
 }
@@ -16082,7 +16327,7 @@ dwarf2out_vms_debug_main_pointer (void)
 static void
 push_decl_scope (tree scope)
 {
-  VEC_safe_push (tree, gc, decl_scope_table, scope);
+  vec_safe_push (decl_scope_table, scope);
 }
 
 /* Pop a declaration scope.  */
@@ -16090,7 +16335,7 @@ push_decl_scope (tree scope)
 static inline void
 pop_decl_scope (void)
 {
-  VEC_pop (tree, decl_scope_table);
+  decl_scope_table->pop ();
 }
 
 /* walk_tree helper function for uses_local_type, below.  */
@@ -16415,17 +16660,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
       return;
     }
 
-  /* ??? The SGI dwarf reader fails for array of array of enum types
-     (e.g. const enum machine_mode insn_operand_mode[2][10]) unless the inner
-     array type comes before the outer array type.  We thus call gen_type_die
-     before we new_die and must prevent nested array types collapsing for this
-     target.  */
-
-#ifdef MIPS_DEBUGGING_INFO
-  gen_type_die (TREE_TYPE (type), context_die);
-  collapse_nested_arrays = false;
-#endif
-
   array_die = new_die (DW_TAG_array_type, scope_die, type);
   add_name_attribute (array_die, type_tag (type));
   equate_type_number_to_die (type, array_die);
@@ -16451,14 +16685,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
   add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major);
 #endif
 
-#ifdef MIPS_DEBUGGING_INFO
-  /* The SGI compilers handle arrays of unknown bound by setting
-     AT_declaration and not emitting any subrange DIEs.  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && ! TYPE_DOMAIN (type))
-    add_AT_flag (array_die, DW_AT_declaration, 1);
-  else
-#endif
   if (TREE_CODE (type) == VECTOR_TYPE)
     {
       /* For VECTOR_TYPEs we use an array die with appropriate bounds.  */
@@ -16481,10 +16707,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
        element_type = TREE_TYPE (element_type);
       }
 
-#ifndef MIPS_DEBUGGING_INFO
-  gen_type_die (element_type, context_die);
-#endif
-
   add_type_attribute (array_die, element_type, 0, 0, context_die);
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
@@ -16686,10 +16908,9 @@ retry_incomplete_types (void)
 {
   int i;
 
-  for (i = VEC_length (tree, incomplete_types) - 1; i >= 0; i--)
-    if (should_emit_struct_debug (VEC_index (tree, incomplete_types, i),
-                                 DINFO_USAGE_DIR_USE))
-      gen_type_die (VEC_index (tree, incomplete_types, i), comp_unit_die ());
+  for (i = vec_safe_length (incomplete_types) - 1; i >= 0; i--)
+    if (should_emit_struct_debug ((*incomplete_types)[i], DINFO_USAGE_DIR_USE))
+      gen_type_die ((*incomplete_types)[i], comp_unit_die ());
 }
 
 /* Determine what tag to use for a record type.  */
@@ -16797,8 +17018,7 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
   else
     add_AT_flag (type_die, DW_AT_declaration, 1);
 
-  if (get_AT (type_die, DW_AT_name))
-    add_pubtype (type, type_die);
+  add_pubtype (type, type_die);
 
   return type_die;
 }
@@ -17030,7 +17250,136 @@ gen_type_die_for_member (tree type, tree member, dw_die_ref context_die)
       else
        gen_variable_die (member, NULL_TREE, type_die);
 
-      pop_decl_scope ();
+      pop_decl_scope ();
+    }
+}
+\f
+/* Forward declare these functions, because they are mutually recursive
+  with their set_block_* pairing functions.  */
+static void set_decl_origin_self (tree);
+static void set_decl_abstract_flags (tree, int);
+
+/* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the
+   given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so
+   that it points to the node itself, thus indicating that the node is its
+   own (abstract) origin.  Additionally, if the BLOCK_ABSTRACT_ORIGIN for
+   the given node is NULL, recursively descend the decl/block tree which
+   it is the root of, and for each other ..._DECL or BLOCK node contained
+   therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also
+   still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN
+   values to point to themselves.  */
+
+static void
+set_block_origin_self (tree stmt)
+{
+  if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE)
+    {
+      BLOCK_ABSTRACT_ORIGIN (stmt) = stmt;
+
+      {
+       tree local_decl;
+
+       for (local_decl = BLOCK_VARS (stmt);
+            local_decl != NULL_TREE;
+            local_decl = DECL_CHAIN (local_decl))
+         if (! DECL_EXTERNAL (local_decl))
+           set_decl_origin_self (local_decl);  /* Potential recursion.  */
+      }
+
+      {
+       tree subblock;
+
+       for (subblock = BLOCK_SUBBLOCKS (stmt);
+            subblock != NULL_TREE;
+            subblock = BLOCK_CHAIN (subblock))
+         set_block_origin_self (subblock);     /* Recurse.  */
+      }
+    }
+}
+
+/* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for
+   the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the
+   node to so that it points to the node itself, thus indicating that the
+   node represents its own (abstract) origin.  Additionally, if the
+   DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend
+   the decl/block tree of which the given node is the root of, and for
+   each other ..._DECL or BLOCK node contained therein whose
+   DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL,
+   set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to
+   point to themselves.  */
+
+static void
+set_decl_origin_self (tree decl)
+{
+  if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE)
+    {
+      DECL_ABSTRACT_ORIGIN (decl) = decl;
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       {
+         tree arg;
+
+         for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg))
+           DECL_ABSTRACT_ORIGIN (arg) = arg;
+         if (DECL_INITIAL (decl) != NULL_TREE
+             && DECL_INITIAL (decl) != error_mark_node)
+           set_block_origin_self (DECL_INITIAL (decl));
+       }
+    }
+}
+\f
+/* Given a pointer to some BLOCK node, and a boolean value to set the
+   "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for
+   the given block, and for all local decls and all local sub-blocks
+   (recursively) which are contained therein.  */
+
+static void
+set_block_abstract_flags (tree stmt, int setting)
+{
+  tree local_decl;
+  tree subblock;
+  unsigned int i;
+
+  BLOCK_ABSTRACT (stmt) = setting;
+
+  for (local_decl = BLOCK_VARS (stmt);
+       local_decl != NULL_TREE;
+       local_decl = DECL_CHAIN (local_decl))
+    if (! DECL_EXTERNAL (local_decl))
+      set_decl_abstract_flags (local_decl, setting);
+
+  for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
+    {
+      local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i);
+      if ((TREE_CODE (local_decl) == VAR_DECL && !TREE_STATIC (local_decl))
+         || TREE_CODE (local_decl) == PARM_DECL)
+       set_decl_abstract_flags (local_decl, setting);
+    }
+
+  for (subblock = BLOCK_SUBBLOCKS (stmt);
+       subblock != NULL_TREE;
+       subblock = BLOCK_CHAIN (subblock))
+    set_block_abstract_flags (subblock, setting);
+}
+
+/* Given a pointer to some ..._DECL node, and a boolean value to set the
+   "abstract" flags to, set that value into the DECL_ABSTRACT flag for the
+   given decl, and (in the case where the decl is a FUNCTION_DECL) also
+   set the abstract flags for all of the parameters, local vars, local
+   blocks and sub-blocks (recursively) to the same setting.  */
+
+static void
+set_decl_abstract_flags (tree decl, int setting)
+{
+  DECL_ABSTRACT (decl) = setting;
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      tree arg;
+
+      for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg))
+       DECL_ABSTRACT (arg) = setting;
+      if (DECL_INITIAL (decl) != NULL_TREE
+         && DECL_INITIAL (decl) != error_mark_node)
+       set_block_abstract_flags (DECL_INITIAL (decl), setting);
     }
 }
 
@@ -17084,7 +17433,6 @@ dwarf2out_abstract_function (tree decl)
   /* Pretend we've just finished compiling this function.  */
   save_fn = current_function_decl;
   current_function_decl = decl;
-  push_cfun (DECL_STRUCT_FUNCTION (decl));
 
   was_abstract = DECL_ABSTRACT (decl);
   set_decl_abstract_flags (decl, 1);
@@ -17098,7 +17446,6 @@ dwarf2out_abstract_function (tree decl)
   call_arg_locations = old_call_arg_locations;
   call_site_count = old_call_site_count;
   tail_call_site_count = old_tail_call_site_count;
-  pop_cfun ();
 }
 
 /* Helper function of premark_used_types() which gets called through
@@ -17143,7 +17490,7 @@ premark_types_used_by_global_vars_helper (void **slot,
       /* Ask cgraph if the global variable really is to be emitted.
          If yes, then we'll keep the DIE of ENTRY->TYPE.  */
       struct varpool_node *node = varpool_get_node (entry->var_decl);
-      if (node && node->needed)
+      if (node && node->analyzed)
        {
          die->die_perennial_p = 1;
          /* Keep the parent DIEs as well.  */
@@ -17157,10 +17504,10 @@ premark_types_used_by_global_vars_helper (void **slot,
 /* Mark all members of used_types_hash as perennial.  */
 
 static void
-premark_used_types (void)
+premark_used_types (struct function *fun)
 {
-  if (cfun && cfun->used_types_hash)
-    htab_traverse (cfun->used_types_hash, premark_used_types_helper, NULL);
+  if (fun && fun->used_types_hash)
+    htab_traverse (fun->used_types_hash, premark_used_types_helper, NULL);
 }
 
 /* Mark all members of types_used_by_vars_entry as perennial.  */
@@ -17187,8 +17534,8 @@ gen_call_site_die (tree decl, dw_die_ref subr_die,
         && block != DECL_INITIAL (decl)
         && TREE_CODE (block) == BLOCK)
     {
-      if (VEC_length (dw_die_ref, block_map) > BLOCK_NUMBER (block))
-       stmt_die = VEC_index (dw_die_ref, block_map, BLOCK_NUMBER (block));
+      if (block_map.length () > BLOCK_NUMBER (block))
+       stmt_die = block_map[BLOCK_NUMBER (block)];
       if (stmt_die)
        break;
       block = BLOCK_SUPERCONTEXT (block);
@@ -17205,7 +17552,7 @@ gen_call_site_die (tree decl, dw_die_ref subr_die,
       if (tdie)
        add_AT_die_ref (die, DW_AT_abstract_origin, tdie);
       else
-       add_AT_addr (die, DW_AT_abstract_origin, ca_loc->symbol_ref);
+        add_AT_addr (die, DW_AT_abstract_origin, ca_loc->symbol_ref, false);
     }
   return die;
 }
@@ -17223,7 +17570,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
   int declaration = (current_function_decl != decl
                     || class_or_namespace_scope_p (context_die));
 
-  premark_used_types ();
+  premark_used_types (DECL_STRUCT_FUNCTION (decl));
 
   /* It is possible to have both DECL_ABSTRACT and DECLARATION be true if we
      started to generate the abstract instance of an inline, decided to output
@@ -17308,6 +17655,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        {
          subr_die = new_die (DW_TAG_subprogram, context_die, decl);
          add_AT_specification (subr_die, old_die);
+          add_pubname (decl, subr_die);
          if (get_AT_file (old_die, DW_AT_decl_file) != file_index)
            add_AT_file (subr_die, DW_AT_decl_file, file_index);
          if (get_AT_unsigned (old_die, DW_AT_decl_line) != (unsigned) s.line)
@@ -17322,6 +17670,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        add_AT_flag (subr_die, DW_AT_external, 1);
 
       add_name_and_src_coords_attributes (subr_die, decl);
+      add_pubname (decl, subr_die);
       if (debug_info_level > DINFO_LEVEL_TERSE)
        {
          add_prototyped_attribute (subr_die, TREE_TYPE (decl));
@@ -17384,29 +17733,32 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
   else if (!DECL_EXTERNAL (decl))
     {
       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);
 
+      gcc_checking_assert (fun);
       if (!flag_reorder_blocks_and_partition)
        {
-         dw_fde_ref fde = cfun->fde;
+         dw_fde_ref fde = fun->fde;
          if (fde->dw_fde_begin)
            {
              /* We have already generated the labels.  */
-             add_AT_lbl_id (subr_die, DW_AT_low_pc, fde->dw_fde_begin);
-             add_AT_lbl_id (subr_die, DW_AT_high_pc, fde->dw_fde_end);
+             add_AT_low_high_pc (subr_die, fde->dw_fde_begin,
+                                 fde->dw_fde_end, false);
            }
          else
            {
              /* Create start/end labels and add the range.  */
-             char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
-             ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL,
+             char label_id_low[MAX_ARTIFICIAL_LABEL_BYTES];
+             char label_id_high[MAX_ARTIFICIAL_LABEL_BYTES];
+             ASM_GENERATE_INTERNAL_LABEL (label_id_low, FUNC_BEGIN_LABEL,
                                           current_function_funcdef_no);
-             add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id);
-             ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
+             ASM_GENERATE_INTERNAL_LABEL (label_id_high, FUNC_END_LABEL,
                                           current_function_funcdef_no);
-             add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id);
+             add_AT_low_high_pc (subr_die, label_id_low, label_id_high,
+                                 false);
            }
 
 #if VMS_DEBUGGING_INFO
@@ -17433,12 +17785,11 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       }
 #endif
 
-         add_pubname (decl, subr_die);
        }
       else
        {
          /* Generate pubnames entries for the split function code ranges.  */
-         dw_fde_ref fde = cfun->fde;
+         dw_fde_ref fde = fun->fde;
 
          if (fde->dw_fde_second_begin)
            {
@@ -17450,11 +17801,11 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                     alignment offset.  */
                  bool range_list_added = false;
                  add_ranges_by_labels (subr_die, fde->dw_fde_begin,
-                                       fde->dw_fde_end, &range_list_added);
+                                        fde->dw_fde_end, &range_list_added,
+                                        false);
                  add_ranges_by_labels (subr_die, fde->dw_fde_second_begin,
                                        fde->dw_fde_second_end,
-                                       &range_list_added);
-                 add_pubname (decl, subr_die);
+                                       &range_list_added, false);
                  if (range_list_added)
                    add_ranges (NULL);
                }
@@ -17472,12 +17823,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                  dw_die_ref seg_die;
 
                  /* Do the 'primary' section.   */
-                 add_AT_lbl_id (subr_die, DW_AT_low_pc,
-                                fde->dw_fde_begin);
-                 add_AT_lbl_id (subr_die, DW_AT_high_pc,
-                                fde->dw_fde_end);
-                 /* Add it.   */
-                 add_pubname (decl, subr_die);
+                 add_AT_low_high_pc (subr_die, fde->dw_fde_begin,
+                                      fde->dw_fde_end, false);
 
                  /* Build a minimal DIE for the secondary section.  */
                  seg_die = new_die (DW_TAG_subprogram,
@@ -17501,27 +17848,18 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                    add_AT_flag (seg_die, DW_AT_artificial, 1);
 
                  name = concat ("__second_sect_of_", name, NULL); 
-                 add_AT_lbl_id (seg_die, DW_AT_low_pc,
-                                fde->dw_fde_second_begin);
-                 add_AT_lbl_id (seg_die, DW_AT_high_pc,
-                                fde->dw_fde_second_end);
+                 add_AT_low_high_pc (seg_die, fde->dw_fde_second_begin,
+                                      fde->dw_fde_second_end, false);
                  add_name_attribute (seg_die, name);
-                 add_pubname_string (name, seg_die);
+                 if (want_pubnames ())
+                   add_pubname_string (name, seg_die);
                }
            }
          else
-           {
-             add_AT_lbl_id (subr_die, DW_AT_low_pc, fde->dw_fde_begin);
-             add_AT_lbl_id (subr_die, DW_AT_high_pc, fde->dw_fde_end);
-             add_pubname (decl, subr_die);
-           }
+           add_AT_low_high_pc (subr_die, fde->dw_fde_begin, fde->dw_fde_end,
+                               false);
        }
 
-#ifdef MIPS_DEBUGGING_INFO
-      /* Add a reference to the FDE for this routine.  */
-      add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, cfun->fde->fde_index);
-#endif
-
       cfa_fb_offset = CFA_FRAME_BASE_OFFSET (decl);
 
       /* We define the "frame base" as the function's CFA.  This is more
@@ -17532,7 +17870,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
         (3) We can at least reuse the code inspection and interpretation
         code that determines the CFA position at various points in the
         function.  */
-      if (dwarf_version >= 3)
+      if (dwarf_version >= 3 && targetm.debug_unwind_info () == UI_DWARF2)
        {
          dw_loc_descr_ref op = new_loc_descr (DW_OP_call_frame_cfa, 0, 0);
          add_AT_loc (subr_die, DW_AT_frame_base, op);
@@ -17548,14 +17886,14 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 
       /* Compute a displacement from the "steady-state frame pointer" to
         the CFA.  The former is what all stack slots and argument slots
-        will reference in the rtl; the later is what we've told the
+        will reference in the rtl; the latter is what we've told the
         debugger about.  We'll need to adjust all frame_base references
         by this displacement.  */
       compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
 
-      if (cfun->static_chain_decl)
+      if (fun->static_chain_decl)
        add_AT_location_description (subr_die, DW_AT_static_link,
-                loc_list_from_tree (cfun->static_chain_decl, 2));
+                loc_list_from_tree (fun->static_chain_decl, 2));
     }
 
   /* Generate child dies for template paramaters.  */
@@ -17664,7 +18002,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.  */
-  if (! declaration && TREE_CODE (outer_scope) != ERROR_MARK)
+  if (! declaration && outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
     {
       int call_site_note_count = 0;
       int tail_call_site_note_count = 0;
@@ -17856,7 +18194,7 @@ common_block_die_table_eq (const void *x, const void *y)
 static void
 gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
 {
-  HOST_WIDE_INT off;
+  HOST_WIDE_INT off = 0;
   tree com_decl;
   tree decl_or_origin = decl ? decl : origin;
   tree ultimate_origin;
@@ -17896,10 +18234,13 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
                          && loc->expr->dw_loc_next == NULL
                          && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr)
                             == SYMBOL_REF)
-                       loc->expr->dw_loc_oprnd1.v.val_addr
-                         = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
-                       else
-                         loc_list_plus_const (loc, off);
+                       {
+                         rtx x = loc->expr->dw_loc_oprnd1.v.val_addr;
+                         loc->expr->dw_loc_oprnd1.v.val_addr
+                           = plus_constant (GET_MODE (x), x , off);
+                       }
+                     else
+                       loc_list_plus_const (loc, off);
                    }
                  add_AT_location_description (var_die, DW_AT_location, loc);
                  remove_AT (var_die, DW_AT_declaration);
@@ -17934,7 +18275,8 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
            }
           else if (DECL_EXTERNAL (decl))
            add_AT_flag (com_die, DW_AT_declaration, 1);
-         add_pubname_string (cnam, com_die); /* ??? needed? */
+         if (want_pubnames ())
+           add_pubname_string (cnam, com_die); /* ??? needed? */
          com_die->decl_id = DECL_UID (com_decl);
          slot = htab_find_slot (common_block_die_table, com_die, INSERT);
          *slot = (void *) com_die;
@@ -17956,11 +18298,14 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
            {
              /* Optimize the common case.  */
              if (single_element_loc_list_p (loc)
-                 && loc->expr->dw_loc_opc == DW_OP_addr
+                  && loc->expr->dw_loc_opc == DW_OP_addr
                  && loc->expr->dw_loc_next == NULL
                  && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
-               loc->expr->dw_loc_oprnd1.v.val_addr
-                 = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
+               {
+                 rtx x = loc->expr->dw_loc_oprnd1.v.val_addr;
+                 loc->expr->dw_loc_oprnd1.v.val_addr
+                   = plus_constant (GET_MODE (x), x, off);
+               }
              else
                loc_list_plus_const (loc, off);
            }
@@ -18140,7 +18485,7 @@ gen_label_die (tree decl, dw_die_ref context_die)
          gcc_assert (!INSN_DELETED_P (insn));
 
          ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn));
-         add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
+          add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
        }
       else if (insn
               && NOTE_P (insn)
@@ -18148,7 +18493,7 @@ gen_label_die (tree decl, dw_die_ref context_die)
               && CODE_LABEL_NUMBER (insn) != -1)
        {
          ASM_GENERATE_INTERNAL_LABEL (label, "LDL", CODE_LABEL_NUMBER (insn));
-         add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
+          add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
        }
     }
 }
@@ -18181,16 +18526,69 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
   if (BLOCK_FRAGMENT_CHAIN (stmt)
       && (dwarf_version >= 3 || !dwarf_strict))
     {
-      tree chain;
+      tree chain, superblock = NULL_TREE;
+      dw_die_ref pdie;
+      dw_attr_ref attr = NULL;
 
       if (inlined_function_outer_scope_p (stmt))
        {
          ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
                                       BLOCK_NUMBER (stmt));
-         add_AT_lbl_id (die, DW_AT_entry_pc, label);
+          add_AT_lbl_id (die, DW_AT_entry_pc, label);
+       }
+
+      /* Optimize duplicate .debug_ranges lists or even tails of
+        lists.  If this BLOCK has same ranges as its supercontext,
+        lookup DW_AT_ranges attribute in the supercontext (and
+        recursively so), verify that the ranges_table contains the
+        right values and use it instead of adding a new .debug_range.  */
+      for (chain = stmt, pdie = die;
+          BLOCK_SAME_RANGE (chain);
+          chain = BLOCK_SUPERCONTEXT (chain))
+       {
+         dw_attr_ref new_attr;
+
+         pdie = pdie->die_parent;
+         if (pdie == NULL)
+           break;
+         if (BLOCK_SUPERCONTEXT (chain) == NULL_TREE)
+           break;
+         new_attr = get_AT (pdie, DW_AT_ranges);
+         if (new_attr == NULL
+             || new_attr->dw_attr_val.val_class != dw_val_class_range_list)
+           break;
+         attr = new_attr;
+         superblock = BLOCK_SUPERCONTEXT (chain);
+       }
+      if (attr != NULL
+         && (ranges_table[attr->dw_attr_val.v.val_offset
+                          / 2 / DWARF2_ADDR_SIZE].num
+             == BLOCK_NUMBER (superblock))
+         && BLOCK_FRAGMENT_CHAIN (superblock))
+       {
+         unsigned long off = attr->dw_attr_val.v.val_offset
+                             / 2 / DWARF2_ADDR_SIZE;
+         unsigned long supercnt = 0, thiscnt = 0;
+         for (chain = BLOCK_FRAGMENT_CHAIN (superblock);
+              chain; chain = BLOCK_FRAGMENT_CHAIN (chain))
+           {
+             ++supercnt;
+             gcc_checking_assert (ranges_table[off + supercnt].num
+                                  == BLOCK_NUMBER (chain));
+           }
+         gcc_checking_assert (ranges_table[off + supercnt + 1].num == 0);
+         for (chain = BLOCK_FRAGMENT_CHAIN (stmt);
+              chain; chain = BLOCK_FRAGMENT_CHAIN (chain))
+           ++thiscnt;
+         gcc_assert (supercnt >= thiscnt);
+         add_AT_range_list (die, DW_AT_ranges,
+                             ((off + supercnt - thiscnt)
+                              * 2 * DWARF2_ADDR_SIZE),
+                             false);
+         return;
        }
 
-      add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt));
+      add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt), false);
 
       chain = BLOCK_FRAGMENT_CHAIN (stmt);
       do
@@ -18203,12 +18601,12 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
     }
   else
     {
+      char label_high[MAX_ARTIFICIAL_LABEL_BYTES];
       ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
                                   BLOCK_NUMBER (stmt));
-      add_AT_lbl_id (die, DW_AT_low_pc, label);
-      ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL,
+      ASM_GENERATE_INTERNAL_LABEL (label_high, BLOCK_END_LABEL,
                                   BLOCK_NUMBER (stmt));
-      add_AT_lbl_id (die, DW_AT_high_pc, label);
+      add_AT_low_high_pc (die, label, label_high, false);
     }
 }
 
@@ -18221,10 +18619,9 @@ gen_lexical_block_die (tree stmt, dw_die_ref context_die, int depth)
 
   if (call_arg_locations)
     {
-      if (VEC_length (dw_die_ref, block_map) <= BLOCK_NUMBER (stmt))
-       VEC_safe_grow_cleared (dw_die_ref, heap, block_map,
-                              BLOCK_NUMBER (stmt) + 1);
-      VEC_replace (dw_die_ref, block_map, BLOCK_NUMBER (stmt), stmt_die);
+      if (block_map.length () <= BLOCK_NUMBER (stmt))
+       block_map.safe_grow_cleared (BLOCK_NUMBER (stmt) + 1);
+      block_map[BLOCK_NUMBER (stmt)] = stmt_die;
     }
 
   if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
@@ -18259,10 +18656,9 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die, int depth)
 
       if (call_arg_locations)
        {
-         if (VEC_length (dw_die_ref, block_map) <= BLOCK_NUMBER (stmt))
-           VEC_safe_grow_cleared (dw_die_ref, heap, block_map,
-                                  BLOCK_NUMBER (stmt) + 1);
-         VEC_replace (dw_die_ref, block_map, BLOCK_NUMBER (stmt), subr_die);
+         if (block_map.length () <= BLOCK_NUMBER (stmt))
+           block_map.safe_grow_cleared (BLOCK_NUMBER (stmt) + 1);
+         block_map[BLOCK_NUMBER (stmt)] = subr_die;
        }
       add_abstract_origin_attribute (subr_die, decl);
       if (TREE_ASM_WRITTEN (stmt))
@@ -18363,8 +18759,6 @@ gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
 }
 
 typedef const char *dchar_p; /* For DEF_VEC_P.  */
-DEF_VEC_P(dchar_p);
-DEF_VEC_ALLOC_P(dchar_p,heap);
 
 static char *producer_string;
 
@@ -18375,7 +18769,7 @@ static char *
 gen_producer_string (void)
 {
   size_t j;
-  VEC(dchar_p, heap) *switches = NULL;
+  vec<dchar_p> switches = vNULL;
   const char *language_string = lang_hooks.name;
   char *producer, *tail;
   const char *p;
@@ -18408,6 +18802,7 @@ gen_producer_string (void)
       case OPT__output_pch_:
       case OPT_fdiagnostics_show_location_:
       case OPT_fdiagnostics_show_option:
+      case OPT_fdiagnostics_show_caret:
       case OPT_fverbose_asm:
       case OPT____:
       case OPT__sysroot_:
@@ -18416,6 +18811,9 @@ gen_producer_string (void)
        /* Ignore these.  */
        continue;
       default:
+        if (cl_options[save_decoded_options[j].opt_index].flags
+           & CL_NO_DWARF_RECORD)
+         continue;
         gcc_checking_assert (save_decoded_options[j].canonical_option[0][0]
                             == '-');
         switch (save_decoded_options[j].canonical_option[0][1])
@@ -18432,8 +18830,7 @@ gen_producer_string (void)
          default:
            break;
          }
-       VEC_safe_push (dchar_p, heap, switches,
-                      save_decoded_options[j].orig_option_with_args_text);
+       switches.safe_push (save_decoded_options[j].orig_option_with_args_text);
        len += strlen (save_decoded_options[j].orig_option_with_args_text) + 1;
        break;
       }
@@ -18443,25 +18840,7 @@ gen_producer_string (void)
   sprintf (tail, "%s %s", language_string, version_string);
   tail += plen;
 
-  if (!dwarf_record_gcc_switches)
-    {
-#ifdef MIPS_DEBUGGING_INFO
-      /* The MIPS/SGI compilers place the 'cc' command line options in the
-        producer string.  The SGI debugger looks for -g, -g1, -g2, or -g3;
-        if they do not appear in the producer string, the debugger reaches
-        the conclusion that the object file is stripped and has no debugging
-        information.  To get the MIPS/SGI debugger to believe that there is
-        debugging information in the object file, we add a -g to the producer
-        string.  */
-      if (debug_info_level > DINFO_LEVEL_TERSE)
-       {
-         memcpy (tail, " -g", 3);
-         tail += 3;
-       }
-#endif
-    }
-
-  FOR_EACH_VEC_ELT (dchar_p, switches, j, p)
+  FOR_EACH_VEC_ELT (switches, j, p)
     {
       len = strlen (p);
       *tail = ' ';
@@ -18470,7 +18849,7 @@ gen_producer_string (void)
     }
 
   *tail = '\0';
-  VEC_free (dchar_p, heap, switches);
+  switches.release ();
   return producer;
 }
 
@@ -18493,9 +18872,7 @@ gen_compile_unit_die (const char *filename)
        add_comp_dir_attribute (die);
     }
 
-  if (producer_string == NULL)
-    producer_string = gen_producer_string ();
-  add_AT_string (die, DW_AT_producer, producer_string);
+  add_AT_string (die, DW_AT_producer, producer_string ? producer_string : "");
 
   /* If our producer is LTO try to figure out a common language to use
      from the global list of translation units.  */
@@ -18505,7 +18882,7 @@ gen_compile_unit_die (const char *filename)
       tree t;
       const char *common_lang = NULL;
 
-      FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
+      FOR_EACH_VEC_SAFE_ELT (all_translation_units, i, t)
        {
          if (!TRANSLATION_UNIT_LANGUAGE (t))
            continue;
@@ -18514,7 +18891,7 @@ gen_compile_unit_die (const char *filename)
          else if (strcmp (common_lang, TRANSLATION_UNIT_LANGUAGE (t)) == 0)
            ;
          else if (strncmp (common_lang, "GNU C", 5) == 0
-                  && strncmp (TRANSLATION_UNIT_LANGUAGE (t), "GNU C", 5) == 0)
+                   && strncmp(TRANSLATION_UNIT_LANGUAGE (t), "GNU C", 5) == 0)
            /* Mixing C and C++ is ok, use C++ in that case.  */
            common_lang = "GNU C++";
          else
@@ -18554,6 +18931,9 @@ gen_compile_unit_die (const char *filename)
            language = DW_LANG_Go;
        }
     }
+  /* Use a degraded Fortran setting in strict DWARF2 so is_fortran works.  */
+  else if (strcmp (language_string, "GNU Fortran") == 0)
+    language = DW_LANG_Fortran90;
 
   add_AT_unsigned (die, DW_AT_language, language);
 
@@ -18626,14 +19006,14 @@ gen_member_die (tree type, dw_die_ref context_die)
   /* First output info about the base classes.  */
   if (binfo)
     {
-      VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo);
+      vec<tree, va_gc> *accesses = BINFO_BASE_ACCESSES (binfo);
       int i;
       tree base;
 
       for (i = 0; BINFO_BASE_ITERATE (binfo, i, base); i++)
        gen_inheritance_die (base,
-                            (accesses ? VEC_index (tree, accesses, i)
-                             : access_public_node), context_die);
+                            (accesses ? (*accesses)[i] : access_public_node),
+                            context_die);
     }
 
   /* Now output info about the data members and type members.  */
@@ -18693,6 +19073,10 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
 
   scope_die = scope_die_for (type, context_die);
 
+  /* Generate child dies for template paramaters.  */
+  if (!type_die && debug_info_level > DINFO_LEVEL_TERSE)
+    schedule_generic_params_dies_gen (type);
+
   if (! type_die || (nested && is_cu_die (scope_die)))
     /* First occurrence of type or toplevel definition of nested class.  */
     {
@@ -18710,11 +19094,6 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
   else
     remove_AT (type_die, DW_AT_declaration);
 
-  /* Generate child dies for template paramaters.  */
-  if (debug_info_level > DINFO_LEVEL_TERSE
-      && COMPLETE_TYPE_P (type))
-    schedule_generic_params_dies_gen (type);
-
   /* If this type has been completed, then give it a byte_size attribute and
      then give a list of members.  */
   if (complete && !ns_decl)
@@ -18759,7 +19138,7 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
       /* We don't need to do this for function-local types.  */
       if (TYPE_STUB_DECL (type)
          && ! decl_function_context (TYPE_STUB_DECL (type)))
-       VEC_safe_push (tree, gc, incomplete_types, type);
+       vec_safe_push (incomplete_types, type);
     }
 
   if (get_AT (type_die, DW_AT_name))
@@ -19508,6 +19887,9 @@ gen_namespace_die (tree decl, dw_die_ref context_die)
       add_AT_die_ref (namespace_die, DW_AT_import, origin_die);
       equate_decl_number_to_die (decl, namespace_die);
     }
+  /* Bypass dwarf2_name's check for DECL_NAMELESS.  */
+  if (want_pubnames ())
+    add_pubname_string (lang_hooks.dwarf_name (decl, 1), namespace_die);
 }
 
 /* Generate Dwarf debug information for a decl described by DECL.
@@ -19906,8 +20288,14 @@ dwarf2out_decl (tree decl)
         inline" functions as DECL_EXTERNAL, but we need to generate DWARF for
         them anyway. Note that the C++ front-end also plays some similar games
         for inline function definitions appearing within include files which
-        also contain `#pragma interface' pragmas.  */
-      if (DECL_INITIAL (decl) == NULL_TREE)
+        also contain `#pragma interface' pragmas.
+
+        If we are called from dwarf2out_abstract_function output a DIE
+        anyway.  We can end up here this way with early inlining and LTO
+        where the inlined function is output in a different LTRANS unit
+        or not at all.  */
+      if (DECL_INITIAL (decl) == NULL_TREE
+         && ! DECL_ABSTRACT (decl))
        return;
 
       /* If we're a nested function, initially use a parent of NULL; if we're
@@ -19998,7 +20386,7 @@ dwarf2out_function_decl (tree decl)
   call_arg_loc_last = NULL;
   call_site_count = -1;
   tail_call_site_count = -1;
-  VEC_free (dw_die_ref, heap, block_map);
+  block_map.release ();
   htab_empty (decl_loc_table);
   htab_empty (cached_dw_loc_list_table);
 }
@@ -20149,14 +20537,11 @@ append_entry_to_tmpl_value_parm_die_table (dw_die_ref die, tree arg)
     return;
 
   if (!tmpl_value_parm_die_table)
-    tmpl_value_parm_die_table
-      = VEC_alloc (die_arg_entry, gc, 32);
+    vec_alloc (tmpl_value_parm_die_table, 32);
 
   entry.die = die;
   entry.arg = arg;
-  VEC_safe_push (die_arg_entry, gc,
-                tmpl_value_parm_die_table,
-                &entry);
+  vec_safe_push (tmpl_value_parm_die_table, entry);
 }
 
 /* Return TRUE if T is an instance of generic type, FALSE
@@ -20180,10 +20565,10 @@ schedule_generic_params_dies_gen (tree t)
   if (!generic_type_p (t))
     return;
 
-  if (generic_type_instances == NULL)
-    generic_type_instances = VEC_alloc (tree, gc, 256);
+  if (!generic_type_instances)
+    vec_alloc (generic_type_instances, 256);
 
-  VEC_safe_push (tree, gc, generic_type_instances, t);
+  vec_safe_push (generic_type_instances, t);
 }
 
 /* Add a DW_AT_const_value attribute to DIEs that were scheduled
@@ -20198,7 +20583,7 @@ gen_remaining_tmpl_value_param_die_attribute (void)
       unsigned i;
       die_arg_entry *e;
 
-      FOR_EACH_VEC_ELT (die_arg_entry, tmpl_value_parm_die_table, i, e)
+      FOR_EACH_VEC_ELT (*tmpl_value_parm_die_table, i, e)
        tree_add_const_value_attribute (e->die, e->arg);
     }
 }
@@ -20214,11 +20599,12 @@ gen_scheduled_generic_parms_dies (void)
   unsigned i;
   tree t;
 
-  if (generic_type_instances == NULL)
+  if (!generic_type_instances)
     return;
   
-  FOR_EACH_VEC_ELT (tree, generic_type_instances, i, t)
-    gen_generic_params_dies (t);
+  FOR_EACH_VEC_ELT (*generic_type_instances, i, t)
+    if (COMPLETE_TYPE_P (t))
+      gen_generic_params_dies (t);
 }
 
 
@@ -20253,6 +20639,14 @@ dwarf2out_set_name (tree decl, tree name)
     add_name_attribute (die, dname);
 }
 
+/* True if before or during processing of the first function being emitted.  */
+static bool in_first_function_p = true;
+/* True if loc_note during dwarf2out_var_location call might still be
+   before first real instruction at address equal to .Ltext0.  */
+static bool maybe_at_text_label_p = true;
+/* One above highest N where .LVLN label might be equal to .Ltext0 label.  */
+static unsigned int first_loclabel_num_not_at_text_label;
+
 /* Called by the final INSN scan whenever we see a var location.  We
    use it to drop labels in the right places, and throw the location in
    our lookup table.  */
@@ -20360,6 +20754,45 @@ dwarf2out_var_location (rtx loc_note)
       ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num);
       loclabel_num++;
       last_label = ggc_strdup (loclabel);
+      /* See if loclabel might be equal to .Ltext0.  If yes,
+        bump first_loclabel_num_not_at_text_label.  */
+      if (!have_multiple_function_sections
+         && in_first_function_p
+         && maybe_at_text_label_p)
+       {
+         static rtx last_start;
+         rtx insn;
+         for (insn = loc_note; insn; insn = previous_insn (insn))
+           if (insn == last_start)
+             break;
+           else if (!NONDEBUG_INSN_P (insn))
+             continue;
+           else
+             {
+               rtx body = PATTERN (insn);
+               if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
+                 continue;
+               /* Inline asm could occupy zero bytes.  */
+               else if (GET_CODE (body) == ASM_INPUT
+                        || asm_noperands (body) >= 0)
+                 continue;
+#ifdef HAVE_attr_length
+               else if (get_attr_min_length (insn) == 0)
+                 continue;
+#endif
+               else
+                 {
+                   /* Assume insn has non-zero length.  */
+                   maybe_at_text_label_p = false;
+                   break;
+                 }
+             }
+         if (maybe_at_text_label_p)
+           {
+             last_start = loc_note;
+             first_loclabel_num_not_at_text_label = loclabel_num;
+           }
+       }
     }
 
   if (!var_loc_p)
@@ -20378,12 +20811,8 @@ dwarf2out_var_location (rtx loc_note)
       if (!CALL_P (prev))
        prev = XVECEXP (PATTERN (prev), 0, 0);
       ca_loc->tail_call_p = SIBLING_CALL_P (prev);
-      x = PATTERN (prev);
-      if (GET_CODE (x) == PARALLEL)
-       x = XVECEXP (x, 0, 0);
-      if (GET_CODE (x) == SET)
-       x = SET_SRC (x);
-      if (GET_CODE (x) == CALL && MEM_P (XEXP (x, 0)))
+      x = get_call_rtx_from (PATTERN (prev));
+      if (x)
        {
          x = XEXP (XEXP (x, 0), 0);
          if (GET_CODE (x) == SYMBOL_REF
@@ -20493,7 +20922,7 @@ set_cur_line_info_table (section *sec)
       table = new_line_info_table ();
       table->end_label = end_label;
 
-      VEC_safe_push (dw_line_info_table_p, gc, separate_line_info, table);
+      vec_safe_push (separate_line_info, table);
     }
 
   if (DWARF2_ASM_LINE_DEBUG_INFO)
@@ -20533,6 +20962,59 @@ dwarf2out_begin_function (tree fun)
   set_cur_line_info_table (sec);
 }
 
+/* Helper function of dwarf2out_end_function, called only after emitting
+   the very first function into assembly.  Check if some .debug_loc range
+   might end with a .LVL* label that could be equal to .Ltext0.
+   In that case we must force using absolute addresses in .debug_loc ranges,
+   because this range could be .LVLN-.Ltext0 .. .LVLM-.Ltext0 for
+   .LVLN == .LVLM == .Ltext0, thus 0 .. 0, which is a .debug_loc
+   list terminator.
+   Set have_multiple_function_sections to true in that case and
+   terminate htab traversal.  */
+
+static int
+find_empty_loc_ranges_at_text_label (void **slot, void *)
+{
+  var_loc_list *entry;
+  struct var_loc_node *node;
+
+  entry = (var_loc_list *) *slot;
+  node = entry->first;
+  if (node && node->next && node->next->label)
+    {
+      unsigned int i;
+      const char *label = node->next->label;
+      char loclabel[MAX_ARTIFICIAL_LABEL_BYTES];
+
+      for (i = 0; i < first_loclabel_num_not_at_text_label; i++)
+       {
+         ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", i);
+         if (strcmp (label, loclabel) == 0)
+           {
+             have_multiple_function_sections = true;
+             return 0;
+           }
+       }
+    }
+  return 1;
+}
+
+/* Hook called after emitting a function into assembly.
+   This does something only for the very first function emitted.  */
+
+static void
+dwarf2out_end_function (unsigned int)
+{
+  if (in_first_function_p
+      && !have_multiple_function_sections
+      && first_loclabel_num_not_at_text_label
+      && decl_loc_table)
+    htab_traverse (decl_loc_table, find_empty_loc_ranges_at_text_label,
+                  NULL);
+  in_first_function_p = false;
+  maybe_at_text_label_p = false;
+}
+
 /* Add OPCODE+VAL as an entry at the end of the opcode array in TABLE.  */
 
 static void
@@ -20542,7 +21024,7 @@ push_dw_line_info_entry (dw_line_info_table *table,
   dw_line_info_entry e;
   e.opcode = opcode;
   e.val = val;
-  VEC_safe_push (dw_line_info_entry, gc, table->entries, &e);
+  vec_safe_push (table->entries, e);
 }
 
 /* Output a label to mark the beginning of a source code line entry
@@ -20577,7 +21059,7 @@ dwarf2out_source_line (unsigned int line, const char *filename,
   /* Recall that this end-of-prologue indication is *not* the same thing
      as the end_prologue debug hook.  The NOTE_INSN_PROLOGUE_END note,
      to which the hook corresponds, follows the last insn that was 
-     emitted by gen_prologue.  What we need is to preceed the first insn
+     emitted by gen_prologue.  What we need is to precede the first insn
      that had been emitted after NOTE_INSN_FUNCTION_BEG, i.e. the first
      insn that corresponds to something the user wrote.  These may be
      very different locations once scheduling is enabled.  */
@@ -20647,7 +21129,7 @@ dwarf2out_source_line (unsigned int line, const char *filename,
 static void
 dwarf2out_start_source_file (unsigned int lineno, const char *filename)
 {
-  if (flag_eliminate_dwarf2_dups && ! use_debug_types)
+  if (flag_eliminate_dwarf2_dups)
     {
       /* Record the beginning of the file for break_out_includes.  */
       dw_die_ref bincl_die;
@@ -20662,7 +21144,7 @@ dwarf2out_start_source_file (unsigned int lineno, const char *filename)
       e.code = DW_MACINFO_start_file;
       e.lineno = lineno;
       e.info = ggc_strdup (filename);
-      VEC_safe_push (macinfo_entry, gc, macinfo_table, &e);
+      vec_safe_push (macinfo_table, e);
     }
 }
 
@@ -20671,7 +21153,7 @@ dwarf2out_start_source_file (unsigned int lineno, const char *filename)
 static void
 dwarf2out_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
 {
-  if (flag_eliminate_dwarf2_dups && ! use_debug_types)
+  if (flag_eliminate_dwarf2_dups)
     /* Record the end of the file for break_out_includes.  */
     new_die (DW_TAG_GNU_EINCL, comp_unit_die (), NULL);
 
@@ -20681,7 +21163,7 @@ dwarf2out_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
       e.code = DW_MACINFO_end_file;
       e.lineno = lineno;
       e.info = NULL;
-      VEC_safe_push (macinfo_entry, gc, macinfo_table, &e);
+      vec_safe_push (macinfo_table, e);
     }
 }
 
@@ -20698,17 +21180,17 @@ dwarf2out_define (unsigned int lineno ATTRIBUTE_UNUSED,
       macinfo_entry e;
       /* Insert a dummy first entry to be able to optimize the whole
         predefined macro block using DW_MACRO_GNU_transparent_include.  */
-      if (VEC_empty (macinfo_entry, macinfo_table) && lineno <= 1)
+      if (macinfo_table->is_empty () && lineno <= 1)
        {
          e.code = 0;
          e.lineno = 0;
          e.info = NULL;
-         VEC_safe_push (macinfo_entry, gc, macinfo_table, &e);
+         vec_safe_push (macinfo_table, e);
        }
       e.code = DW_MACINFO_define;
       e.lineno = lineno;
       e.info = ggc_strdup (buffer);
-      VEC_safe_push (macinfo_entry, gc, macinfo_table, &e);
+      vec_safe_push (macinfo_table, e);
     }
 }
 
@@ -20725,17 +21207,17 @@ dwarf2out_undef (unsigned int lineno ATTRIBUTE_UNUSED,
       macinfo_entry e;
       /* Insert a dummy first entry to be able to optimize the whole
         predefined macro block using DW_MACRO_GNU_transparent_include.  */
-      if (VEC_empty (macinfo_entry, macinfo_table) && lineno <= 1)
+      if (macinfo_table->is_empty () && lineno <= 1)
        {
          e.code = 0;
          e.lineno = 0;
          e.info = NULL;
-         VEC_safe_push (macinfo_entry, gc, macinfo_table, &e);
+         vec_safe_push (macinfo_table, e);
        }
       e.code = DW_MACINFO_undef;
       e.lineno = lineno;
       e.info = ggc_strdup (buffer);
-      VEC_safe_push (macinfo_entry, gc, macinfo_table, &e);
+      vec_safe_push (macinfo_table, e);
     }
 }
 
@@ -20808,23 +21290,22 @@ output_macinfo_op (macinfo_entry *ref)
     case DW_MACRO_GNU_define_indirect:
     case DW_MACRO_GNU_undef_indirect:
       node = find_AT_string (ref->info);
-      if (node->form != DW_FORM_strp)
-       {
-         char label[32];
-         ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
-         ++dw2_string_counter;
-         node->label = xstrdup (label);
-         node->form = DW_FORM_strp;
-       }
+      gcc_assert (node
+                  && ((node->form == DW_FORM_strp)
+                      || (node->form == DW_FORM_GNU_str_index)));
       dw2_asm_output_data (1, ref->code,
                           ref->code == DW_MACRO_GNU_define_indirect
                           ? "Define macro indirect"
                           : "Undefine macro indirect");
       dw2_asm_output_data_uleb128 (ref->lineno, "At line number %lu",
                                   (unsigned long) ref->lineno);
-      dw2_asm_output_offset (DWARF_OFFSET_SIZE, node->label,
-                            debug_str_section, "The macro: \"%s\"",
-                            ref->info);
+      if (node->form == DW_FORM_strp)
+        dw2_asm_output_offset (DWARF_OFFSET_SIZE, node->label,
+                               debug_str_section, "The macro: \"%s\"",
+                               ref->info);
+      else
+        dw2_asm_output_data_uleb128 (node->index, "The macro: \"%s\"",
+                                     ref->info);
       break;
     case DW_MACRO_GNU_transparent_include:
       dw2_asm_output_data (1, ref->code, "Transparent include");
@@ -20847,7 +21328,7 @@ output_macinfo_op (macinfo_entry *ref)
    If the define/undef entry should be emitted normally, return 0.  */
 
 static unsigned
-optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
+optimize_macinfo_range (unsigned int idx, vec<macinfo_entry, va_gc> *files,
                        htab_t *macinfo_htab)
 {
   macinfo_entry *first, *second, *cur, *inc;
@@ -20859,8 +21340,8 @@ optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
   unsigned int i, count, encoded_filename_len, linebuf_len;
   void **slot;
 
-  first = VEC_index (macinfo_entry, macinfo_table, idx);
-  second = VEC_index (macinfo_entry, macinfo_table, idx + 1);
+  first = &(*macinfo_table)[idx];
+  second = &(*macinfo_table)[idx + 1];
 
   /* Optimize only if there are at least two consecutive define/undef ops,
      and either all of them are before first DW_MACINFO_start_file
@@ -20868,7 +21349,7 @@ optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
      in some included header file.  */
   if (second->code != DW_MACINFO_define && second->code != DW_MACINFO_undef)
     return 0;
-  if (VEC_empty (macinfo_entry, files))
+  if (vec_safe_is_empty (files))
     {
       if (first->lineno > 1 || second->lineno > 1)
        return 0;
@@ -20880,10 +21361,10 @@ optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
      with first and at the same time compute md5 checksum of their
      codes, linenumbers and strings.  */
   md5_init_ctx (&ctx);
-  for (i = idx; VEC_iterate (macinfo_entry, macinfo_table, i, cur); i++)
+  for (i = idx; macinfo_table->iterate (i, &cur); i++)
     if (cur->code != DW_MACINFO_define && cur->code != DW_MACINFO_undef)
       break;
-    else if (VEC_empty (macinfo_entry, files) && cur->lineno > 1)
+    else if (vec_safe_is_empty (files) && cur->lineno > 1)
       break;
     else
       {
@@ -20897,10 +21378,10 @@ optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
 
   /* From the containing include filename (if any) pick up just
      usable characters from its basename.  */
-  if (VEC_empty (macinfo_entry, files))
+  if (vec_safe_is_empty (files))
     base = "";
   else
-    base = lbasename (VEC_last (macinfo_entry, files)->info);
+    base = lbasename (files->last ().info);
   for (encoded_filename_len = 0, i = 0; base[i]; i++)
     if (ISIDNUM (base[i]) || base[i] == '.')
       encoded_filename_len++;
@@ -20931,7 +21412,7 @@ optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
 
   /* Construct a macinfo_entry for DW_MACRO_GNU_transparent_include
      in the empty vector entry before the first define/undef.  */
-  inc = VEC_index (macinfo_entry, macinfo_table, idx - 1);
+  inc = &(*macinfo_table)[idx - 1];
   inc->code = DW_MACRO_GNU_transparent_include;
   inc->lineno = 0;
   inc->info = ggc_strdup (grp_name);
@@ -20949,10 +21430,7 @@ optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
       output_macinfo_op (inc);
       /* And clear all macinfo_entry in the range to avoid emitting them
         in the second pass.  */
-      for (i = idx;
-          VEC_iterate (macinfo_entry, macinfo_table, i, cur)
-          && i < idx + count;
-          i++)
+      for (i = idx; macinfo_table->iterate (i, &cur) && i < idx + count; i++)
        {
          cur->code = 0;
          cur->info = NULL;
@@ -20967,15 +21445,51 @@ optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
   return count;
 }
 
+/* Save any strings needed by the macinfo table in the debug str
+   table.  All strings must be collected into the table by the time
+   index_string is called.  */
+
+static void
+save_macinfo_strings (void)
+{
+  unsigned len;
+  unsigned i;
+  macinfo_entry *ref;
+
+  for (i = 0; macinfo_table && macinfo_table->iterate (i, &ref); i++)
+    {
+      switch (ref->code)
+        {
+          /* Match the logic in output_macinfo_op to decide on
+             indirect strings.  */
+          case DW_MACINFO_define:
+          case DW_MACINFO_undef:
+            len = strlen (ref->info) + 1;
+            if (!dwarf_strict
+                && len > DWARF_OFFSET_SIZE
+                && !DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
+                && (debug_str_section->common.flags & SECTION_MERGE) != 0)
+              set_indirect_string (find_AT_string (ref->info));
+            break;
+          case DW_MACRO_GNU_define_indirect:
+          case DW_MACRO_GNU_undef_indirect:
+            set_indirect_string (find_AT_string (ref->info));
+            break;
+          default:
+            break;
+        }
+    }
+}
+
 /* Output macinfo section(s).  */
 
 static void
 output_macinfo (void)
 {
   unsigned i;
-  unsigned long length = VEC_length (macinfo_entry, macinfo_table);
+  unsigned long length = vec_safe_length (macinfo_table);
   macinfo_entry *ref;
-  VEC (macinfo_entry, gc) *files = NULL;
+  vec<macinfo_entry, va_gc> *files = NULL;
   htab_t macinfo_htab = NULL;
 
   if (! length)
@@ -20995,8 +21509,10 @@ output_macinfo (void)
        dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
       else
        dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
-      dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_line_section_label,
-                            debug_line_section, NULL);
+      dw2_asm_output_offset (DWARF_OFFSET_SIZE,
+                             (!dwarf_split_debug_info ? debug_line_section_label
+                              : debug_skeleton_line_section_label),
+                             debug_line_section, NULL);
     }
 
   /* In the first loop, it emits the primary .debug_macinfo section
@@ -21006,25 +21522,25 @@ output_macinfo (void)
      DW_MACRO_GNU_transparent_include op is emitted and kept in
      the vector before the first define/undef in the range and the
      whole range of define/undef ops is not emitted and kept.  */
-  for (i = 0; VEC_iterate (macinfo_entry, macinfo_table, i, ref); i++)
+  for (i = 0; macinfo_table->iterate (i, &ref); i++)
     {
       switch (ref->code)
        {
        case DW_MACINFO_start_file:
-         VEC_safe_push (macinfo_entry, gc, files, ref);
+         vec_safe_push (files, *ref);
          break;
        case DW_MACINFO_end_file:
-         if (!VEC_empty (macinfo_entry, files))
-           VEC_pop (macinfo_entry, files);
+         if (!vec_safe_is_empty (files))
+           files->pop ();
          break;
        case DW_MACINFO_define:
        case DW_MACINFO_undef:
          if (!dwarf_strict
              && HAVE_COMDAT_GROUP
-             && VEC_length (macinfo_entry, files) != 1
+             && vec_safe_length (files) != 1
              && i > 0
              && i + 1 < length
-             && VEC_index (macinfo_entry, macinfo_table, i - 1)->code == 0)
+             && (*macinfo_table)[i - 1].code == 0)
            {
              unsigned count = optimize_macinfo_range (i, files, &macinfo_htab);
              if (count)
@@ -21056,7 +21572,7 @@ output_macinfo (void)
      DW_MACRO_GNU_transparent_include entries terminate the
      current chain and switch to a new comdat .debug_macinfo
      section and emit the define/undef entries within it.  */
-  for (i = 0; VEC_iterate (macinfo_entry, macinfo_table, i, ref); i++)
+  for (i = 0; macinfo_table->iterate (i, &ref); i++)
     switch (ref->code)
       {
       case 0:
@@ -21118,7 +21634,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
                       cached_dw_loc_list_table_eq, NULL);
 
   /* Allocate the initial hunk of the decl_scope_table.  */
-  decl_scope_table = VEC_alloc (tree, gc, 256);
+  vec_alloc (decl_scope_table, 256);
 
   /* Allocate the initial hunk of the abbrev_die_table.  */
   abbrev_die_table = ggc_alloc_cleared_vec_dw_die_ref
@@ -21128,27 +21644,61 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   abbrev_die_table_in_use = 1;
 
   /* Allocate the pubtypes and pubnames vectors.  */
-  pubname_table = VEC_alloc (pubname_entry, gc, 32);
-  pubtype_table = VEC_alloc (pubname_entry, gc, 32);
+  vec_alloc (pubname_table, 32);
+  vec_alloc (pubtype_table, 32);
 
-  incomplete_types = VEC_alloc (tree, gc, 64);
+  vec_alloc (incomplete_types, 64);
 
-  used_rtx_array = VEC_alloc (rtx, gc, 32);
+  vec_alloc (used_rtx_array, 32);
 
-  debug_info_section = get_section (DEBUG_INFO_SECTION,
-                                   SECTION_DEBUG, NULL);
-  debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
-                                     SECTION_DEBUG, NULL);
+  if (!dwarf_split_debug_info)
+    {
+      debug_info_section = get_section (DEBUG_INFO_SECTION,
+                                        SECTION_DEBUG, NULL);
+      debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
+                                          SECTION_DEBUG, NULL);
+      debug_loc_section = get_section (DEBUG_LOC_SECTION,
+                                       SECTION_DEBUG, NULL);
+    }
+  else
+    {
+      debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
+                                        SECTION_DEBUG | SECTION_EXCLUDE, NULL);
+      debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
+                                          SECTION_DEBUG | SECTION_EXCLUDE,
+                                          NULL);
+      debug_addr_section = get_section (DEBUG_ADDR_SECTION,
+                                        SECTION_DEBUG, NULL);
+      debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
+                                                 SECTION_DEBUG, NULL);
+      debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
+                                                   SECTION_DEBUG, NULL);
+      ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
+                                  DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0);
+
+      /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
+         the main .o, but the skeleton_line goes into the split off dwo.  */
+      debug_skeleton_line_section
+          = get_section (DEBUG_DWO_LINE_SECTION,
+                         SECTION_DEBUG | SECTION_EXCLUDE, NULL);
+      ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
+                                   DEBUG_SKELETON_LINE_SECTION_LABEL, 0);
+      debug_str_offsets_section = get_section (DEBUG_STR_OFFSETS_SECTION,
+                                               SECTION_DEBUG | SECTION_EXCLUDE,
+                                               NULL);
+      ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
+                                   DEBUG_SKELETON_INFO_SECTION_LABEL, 0);
+      debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION,
+                                       SECTION_DEBUG | SECTION_EXCLUDE, NULL);
+    }
   debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
                                       SECTION_DEBUG, NULL);
   debug_macinfo_section = get_section (dwarf_strict
                                       ? DEBUG_MACINFO_SECTION
                                       : DEBUG_MACRO_SECTION,
-                                      SECTION_DEBUG, NULL);
+                                       DEBUG_MACRO_SECTION_FLAGS, NULL);
   debug_line_section = get_section (DEBUG_LINE_SECTION,
                                    SECTION_DEBUG, NULL);
-  debug_loc_section = get_section (DEBUG_LOC_SECTION,
-                                  SECTION_DEBUG, NULL);
   debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
                                        SECTION_DEBUG, NULL);
   debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
@@ -21174,13 +21724,16 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
                               DEBUG_LINE_SECTION_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
                               DEBUG_RANGES_SECTION_LABEL, 0);
+  ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
+                               DEBUG_ADDR_SECTION_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
                               dwarf_strict
                               ? DEBUG_MACINFO_SECTION_LABEL
                               : DEBUG_MACRO_SECTION_LABEL, 0);
+  ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0);
 
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
-    macinfo_table = VEC_alloc (macinfo_entry, gc, 64);
+    vec_alloc (macinfo_table, 64);
 
   switch_to_section (text_section);
   ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
@@ -21190,7 +21743,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   text_section_line_info->end_label = text_end_label;
 }
 
-/* Called before cgraph_optimize starts outputtting functions, variables
+/* Called before compile () starts outputtting functions, variables
    and toplevel asms into assembly.  */
 
 static void
@@ -21204,6 +21757,71 @@ dwarf2out_assembly_start (void)
 }
 
 /* A helper function for dwarf2out_finish called through
+   htab_traverse.  Assign a string its index.  All strings must be
+   collected into the table by the time index_string is called,
+   because the indexing code relies on htab_traverse to traverse nodes
+   in the same order for each run. */
+
+static int
+index_string (void **h, void *v)
+{
+  struct indirect_string_node *node = (struct indirect_string_node *) *h;
+  unsigned int *index = (unsigned int *) v;
+
+  find_string_form (node);
+  if (node->form == DW_FORM_GNU_str_index && node->refcount > 0)
+    {
+      gcc_assert(node->index == NO_INDEX_ASSIGNED);
+      node->index = *index;
+      *index += 1;
+    }
+  return 1;
+}
+
+/* A helper function for output_indirect_strings called through
+   htab_traverse.  Output the offset to a string and update the
+   current offset.  */
+
+static int
+output_index_string_offset (void **h, void *v)
+{
+  struct indirect_string_node *node = (struct indirect_string_node *) *h;
+  unsigned int *offset = (unsigned int *) v;
+
+  if (node->form == DW_FORM_GNU_str_index && node->refcount > 0)
+    {
+      /* Assert that this node has been assigned an index.  */
+      gcc_assert (node->index != NO_INDEX_ASSIGNED
+                  && node->index != NOT_INDEXED);
+      dw2_asm_output_data (DWARF_OFFSET_SIZE, *offset,
+                           "indexed string 0x%x: %s", node->index, node->str);
+      *offset += strlen (node->str) + 1;
+    }
+  return 1;
+}
+
+/* A helper function for dwarf2out_finish called through
+   htab_traverse.  Output the indexed string.  */
+
+static int
+output_index_string (void **h, void *v)
+{
+  struct indirect_string_node *node = (struct indirect_string_node *) *h;
+  unsigned int *cur_idx = (unsigned int *) v;
+
+  if (node->form == DW_FORM_GNU_str_index && node->refcount > 0)
+    {
+      /* Assert that the strings are output in the same order as their
+         indexes were assigned.  */
+      gcc_assert (*cur_idx == node->index);
+      ASM_OUTPUT_LABEL (asm_out_file, node->label);
+      assemble_string (node->str, strlen (node->str) + 1);
+      *cur_idx += 1;
+    }
+  return 1;
+}
+
+/* A helper function for dwarf2out_finish called through
    htab_traverse.  Emit one queued .debug_str string.  */
 
 static int
@@ -21211,9 +21829,8 @@ output_indirect_string (void **h, void *v ATTRIBUTE_UNUSED)
 {
   struct indirect_string_node *node = (struct indirect_string_node *) *h;
 
-  if (node->form == DW_FORM_strp)
+  if (node->form == DW_FORM_strp && node->refcount > 0)
     {
-      switch_to_section (debug_str_section);
       ASM_OUTPUT_LABEL (asm_out_file, node->label);
       assemble_string (node->str, strlen (node->str) + 1);
     }
@@ -21221,6 +21838,87 @@ output_indirect_string (void **h, void *v ATTRIBUTE_UNUSED)
   return 1;
 }
 
+/* Output the indexed string table.  */
+
+static void
+output_indirect_strings (void)
+{
+  if (!dwarf_split_debug_info)
+    {
+      switch_to_section (debug_str_section);
+      htab_traverse (debug_str_hash, output_indirect_string, NULL);
+    }
+  else
+    {
+      unsigned int offset = 0;
+      unsigned int cur_idx = 0;
+
+      switch_to_section (debug_str_offsets_section);
+      htab_traverse_noresize (debug_str_hash,
+                              output_index_string_offset,
+                              &offset);
+      switch_to_section (debug_str_section);
+      htab_traverse_noresize (debug_str_hash,
+                              output_index_string,
+                              &cur_idx);
+    }
+}
+
+/* Callback for htab_traverse to assign an index to an entry in the
+   table, and to write that entry to the .debug_addr section.  */
+
+static int
+output_addr_table_entry (void **slot, void *data)
+{
+  addr_table_entry *entry = (addr_table_entry *) *slot;
+  unsigned int *cur_index = (unsigned int *)data;
+
+  if (entry->refcount == 0)
+    {
+      gcc_assert (entry->index == NO_INDEX_ASSIGNED
+                  || entry->index == NOT_INDEXED);
+      return 1;
+    }
+
+  gcc_assert (entry->index == *cur_index);
+  (*cur_index)++;
+
+  switch (entry->kind)
+    {
+      case ate_kind_rtx:
+        dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, entry->addr.rtl,
+                                 "0x%x", entry->index);
+        break;
+      case ate_kind_rtx_dtprel:
+        gcc_assert (targetm.asm_out.output_dwarf_dtprel);
+        targetm.asm_out.output_dwarf_dtprel (asm_out_file,
+                                             DWARF2_ADDR_SIZE,
+                                             entry->addr.rtl);
+        fputc ('\n', asm_out_file);
+        break;
+      case ate_kind_label:
+        dw2_asm_output_addr (DWARF2_ADDR_SIZE, entry->addr.label,
+                                 "0x%x", entry->index);
+        break;
+      default:
+        gcc_unreachable ();
+    }
+  return 1;
+}
+
+/* Produce the .debug_addr section.  */
+
+static void
+output_addr_table (void)
+{
+  unsigned int index = 0;
+  if (addr_index_table == NULL || htab_size (addr_index_table) == 0)
+    return;
+
+  switch_to_section (debug_addr_section);
+  htab_traverse_noresize (addr_index_table, output_addr_table_entry, &index);
+}
+
 #if ENABLE_ASSERT_CHECKING
 /* Verify that all marks are clear.  */
 
@@ -21256,16 +21954,15 @@ prune_unused_types_walk_attribs (dw_die_ref die)
   dw_attr_ref a;
   unsigned ix;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     {
       if (a->dw_attr_val.val_class == dw_val_class_die_ref)
        {
          /* A reference to another DIE.
             Make sure that it will get emitted.
             If it was broken out into a comdat group, don't follow it.  */
-          if (! use_debug_types
-              || a->dw_attr == DW_AT_specification
-              || a->dw_attr_val.v.val_die_ref.die->die_id.die_type_node == NULL)
+          if (! AT_ref (a)->comdat_type_p
+              || a->dw_attr == DW_AT_specification)
            prune_unused_types_mark (a->dw_attr_val.v.val_die_ref.die, 1);
        }
       /* Set the string's refcount to 0 so that prune_unused_types_mark
@@ -21320,9 +22017,11 @@ prune_unused_types_mark (dw_die_ref die, int dokids)
       prune_unused_types_mark_generic_parms_dies (die);
 
       /* We also have to mark its parents as used.
-        (But we don't want to mark our parents' kids due to this.)  */
+        (But we don't want to mark our parent's kids due to this,
+        unless it is a class.)  */
       if (die->die_parent)
-       prune_unused_types_mark (die->die_parent, 0);
+       prune_unused_types_mark (die->die_parent,
+                                class_scope_p (die->die_parent));
 
       /* Mark any referenced nodes.  */
       prune_unused_types_walk_attribs (die);
@@ -21471,7 +22170,7 @@ prune_unused_types_update_strings (dw_die_ref die)
   dw_attr_ref a;
   unsigned ix;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (AT_class (a) == dw_val_class_str)
       {
        struct indirect_string_node *s = a->dw_attr_val.v.val_str;
@@ -21561,11 +22260,14 @@ prune_unused_types (void)
       prune_unused_types_mark (ctnode->type_die, 1);
     }
 
-  /* Also set the mark on nodes referenced from the
-     pubname_table.  */
-  FOR_EACH_VEC_ELT (pubname_entry, pubname_table, i, pub)
-    prune_unused_types_mark (pub->die, 1);
-  for (i = 0; VEC_iterate (dw_die_ref, base_types, i, base_type); i++)
+  /* Also set the mark on nodes referenced from the pubname_table.  Enumerators
+     are unusual in that they are pubnames that are the children of pubtypes.
+     They should only be marked via their parent DW_TAG_enumeration_type die,
+     not as roots in themselves.  */
+  FOR_EACH_VEC_ELT (*pubname_table, i, pub)
+    if (pub->die->die_tag != DW_TAG_enumerator)
+      prune_unused_types_mark (pub->die, 1);
+  for (i = 0; base_types.iterate (i, &base_type); i++)
     prune_unused_types_mark (base_type, 1);
 
   if (debug_str_hash)
@@ -21631,24 +22333,24 @@ htab_ct_eq (const void *of1, const void *of2)
 static inline void
 move_linkage_attr (dw_die_ref die)
 {
-  unsigned ix = VEC_length (dw_attr_node, die->die_attr);
-  dw_attr_node linkage = *VEC_index (dw_attr_node, die->die_attr, ix - 1);
+  unsigned ix = vec_safe_length (die->die_attr);
+  dw_attr_node linkage = (*die->die_attr)[ix - 1];
 
   gcc_assert (linkage.dw_attr == DW_AT_linkage_name
              || linkage.dw_attr == DW_AT_MIPS_linkage_name);
 
   while (--ix > 0)
     {
-      dw_attr_node *prev = VEC_index (dw_attr_node, die->die_attr, ix - 1);
+      dw_attr_node *prev = &(*die->die_attr)[ix - 1];
 
       if (prev->dw_attr == DW_AT_decl_line || prev->dw_attr == DW_AT_name)
        break;
     }
 
-  if (ix != VEC_length (dw_attr_node, die->die_attr) - 1)
+  if (ix != vec_safe_length (die->die_attr) - 1)
     {
-      VEC_pop (dw_attr_node, die->die_attr);
-      VEC_quick_insert (dw_attr_node, die->die_attr, ix, &linkage);
+      die->die_attr->pop ();
+      die->die_attr->quick_insert (ix, linkage);
     }
 }
 
@@ -21687,7 +22389,7 @@ mark_base_types (dw_loc_descr_ref loc)
        base_type->die_mark++;
       else
        {
-         VEC_safe_push (dw_die_ref, heap, base_types, base_type);
+         base_types.safe_push (base_type);
          base_type->die_mark = 1;
        }
     }
@@ -21733,12 +22435,12 @@ move_marked_base_types (void)
   unsigned int i;
   dw_die_ref base_type, die, c;
 
-  if (VEC_empty (dw_die_ref, base_types))
+  if (base_types.is_empty ())
     return;
 
   /* Sort by decreasing usage count, they will be added again in that
      order later on.  */
-  VEC_qsort (dw_die_ref, base_types, base_type_cmp);
+  base_types.qsort (base_type_cmp);
   die = comp_unit_die ();
   c = die->die_child;
   do
@@ -21757,7 +22459,7 @@ move_marked_base_types (void)
   while (c != die->die_child);
   gcc_assert (die->die_child);
   c = die->die_child;
-  for (i = 0; VEC_iterate (dw_die_ref, base_types, i, base_type); i++)
+  for (i = 0; base_types.iterate (i, &base_type); i++)
     {
       base_type->die_mark = 0;
       base_type->die_sib = c->die_sib;
@@ -21786,7 +22488,7 @@ resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED)
       if (!rtl || !MEM_P (rtl))
        return 1;
       rtl = XEXP (rtl, 0);
-      VEC_safe_push (rtx, gc, used_rtx_array, rtl);
+      vec_safe_push (used_rtx_array, rtl);
       *addr = rtl;
       return 0;
     }
@@ -21825,6 +22527,16 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
        if (resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL))
          return false;
        break;
+      case DW_OP_GNU_addr_index:
+      case DW_OP_GNU_const_index:
+        {
+          if ((loc->dw_loc_opc == DW_OP_GNU_addr_index
+               || (loc->dw_loc_opc == DW_OP_GNU_const_index && loc->dtprel))
+              && resolve_one_addr (&loc->dw_loc_oprnd1.val_entry->addr.rtl,
+                                   NULL))
+            return false;
+        }
+       break;
       case DW_OP_const4u:
       case DW_OP_const8u:
        if (loc->dtprel
@@ -21934,7 +22646,7 @@ resolve_addr (dw_die_ref die)
   dw_loc_list_ref *curr, *start, loc;
   unsigned ix;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     switch (AT_class (a))
       {
       case dw_val_class_loc_list:
@@ -21959,11 +22671,15 @@ resolve_addr (dw_die_ref die)
                if (!resolve_addr_in_expr ((*curr)->expr))
                  {
                    dw_loc_list_ref next = (*curr)->dw_loc_next;
+                    dw_loc_descr_ref l = (*curr)->expr;
+
                    if (next && (*curr)->ll_symbol)
                      {
                        gcc_assert (!next->ll_symbol);
                        next->ll_symbol = (*curr)->ll_symbol;
                      }
+                    if (dwarf_split_debug_info)
+                      remove_loc_list_addr_table_entries (l);
                    *curr = next;
                  }
                else
@@ -22001,6 +22717,8 @@ resolve_addr (dw_die_ref die)
               || l->dw_loc_next != NULL)
              && !resolve_addr_in_expr (l))
            {
+              if (dwarf_split_debug_info)
+                remove_loc_list_addr_table_entries (l);
              remove_AT (die, a->dw_attr);
              ix--;
            }
@@ -22012,6 +22730,8 @@ resolve_addr (dw_die_ref die)
        if (a->dw_attr == DW_AT_const_value
            && resolve_one_addr (&a->dw_attr_val.v.val_addr, NULL))
          {
+            if (AT_index (a) != NOT_INDEXED)
+              remove_addr_table_entry (a->dw_attr_val.val_entry);
            remove_AT (die, a->dw_attr);
            ix--;
          }
@@ -22035,6 +22755,8 @@ resolve_addr (dw_die_ref die)
              }
            else
              {
+                if (AT_index (a) != NOT_INDEXED)
+                  remove_addr_table_entry (a->dw_attr_val.val_entry);
                remove_AT (die, a->dw_attr);
                ix--;
              }
@@ -22168,6 +22890,17 @@ hash_loc_operands (dw_loc_descr_ref loc, hashval_t hash)
        }
       hash = iterative_hash_rtx (val1->v.val_addr, hash);
       break;
+    case DW_OP_GNU_addr_index:
+    case DW_OP_GNU_const_index:
+      {
+        if (loc->dtprel)
+          {
+            unsigned char dtprel = 0xd1;
+            hash = iterative_hash_object (dtprel, hash);
+          }
+        hash = iterative_hash_rtx (val1->val_entry->addr.rtl, hash);
+      }
+      break;
     case DW_OP_GNU_implicit_pointer:
       hash = iterative_hash_object (val2->v.val_int, hash);
       break;
@@ -22349,9 +23082,12 @@ compare_loc_operands (dw_loc_descr_ref x, dw_loc_descr_ref y)
       return valx1->v.val_int == valy1->v.val_int;
     case DW_OP_skip:
     case DW_OP_bra:
+      /* If splitting debug info, the use of DW_OP_GNU_addr_index
+        can cause irrelevant differences in dw_loc_addr.  */
       gcc_assert (valx1->val_class == dw_val_class_loc
                  && valy1->val_class == dw_val_class_loc
-                 && x->dw_loc_addr == y->dw_loc_addr);
+                  && (dwarf_split_debug_info
+                      || x->dw_loc_addr == y->dw_loc_addr));
       return valx1->v.val_loc->dw_loc_addr == valy1->v.val_loc->dw_loc_addr;
     case DW_OP_implicit_value:
       if (valx1->v.val_unsigned != valy1->v.val_unsigned
@@ -22382,6 +23118,13 @@ compare_loc_operands (dw_loc_descr_ref x, dw_loc_descr_ref y)
     case DW_OP_addr:
     hash_addr:
       return rtx_equal_p (valx1->v.val_addr, valy1->v.val_addr);
+    case DW_OP_GNU_addr_index:
+    case DW_OP_GNU_const_index:
+      {
+        rtx ax1 = valx1->val_entry->addr.rtl;
+        rtx ay1 = valy1->val_entry->addr.rtl;
+        return rtx_equal_p (ax1, ay1);
+      }
     case DW_OP_GNU_implicit_pointer:
       return valx1->val_class == dw_val_class_die_ref
             && valx1->val_class == valy1->val_class
@@ -22483,7 +23226,7 @@ optimize_location_lists_1 (dw_die_ref die, htab_t htab)
   unsigned ix;
   void **slot;
 
-  FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (AT_class (a) == dw_val_class_loc_list)
       {
        dw_loc_list_ref list = AT_loc_list (a);
@@ -22495,12 +23238,45 @@ optimize_location_lists_1 (dw_die_ref die, htab_t htab)
        if (*slot == NULL)
          *slot = (void *) list;
        else
-         a->dw_attr_val.v.val_loc_list = (dw_loc_list_ref) *slot;
+          a->dw_attr_val.v.val_loc_list = (dw_loc_list_ref) *slot;
       }
 
   FOR_EACH_CHILD (die, c, optimize_location_lists_1 (c, htab));
 }
 
+
+/* Recursively assign each location list a unique index into the debug_addr
+   section.  */
+
+static void
+index_location_lists (dw_die_ref die)
+{
+  dw_die_ref c;
+  dw_attr_ref a;
+  unsigned ix;
+
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+    if (AT_class (a) == dw_val_class_loc_list)
+      {
+        dw_loc_list_ref list = AT_loc_list (a);
+        dw_loc_list_ref curr;
+        for (curr = list; curr != NULL; curr = curr->dw_loc_next)
+          {
+            /* Don't index an entry that has already been indexed
+               or won't be output.  */
+            if (curr->begin_entry != NULL
+                || (strcmp (curr->begin, curr->end) == 0 && !curr->force))
+              continue;
+
+            curr->begin_entry
+                = add_addr_table_entry (xstrdup (curr->begin),
+                                        ate_kind_label);
+          }
+      }
+
+  FOR_EACH_CHILD (die, c, index_location_lists (c));
+}
+
 /* Optimize location lists referenced from DIE
    children and share them whenever possible.  */
 
@@ -22522,15 +23298,15 @@ dwarf2out_finish (const char *filename)
   comdat_type_node *ctnode;
   htab_t comdat_type_table;
   unsigned int i;
+  dw_die_ref main_comp_unit_die;
 
   /* PCH might result in DW_AT_producer string being restored from the
-     header compilation, fix it up if needed.  */
+     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);
-  if (strcmp (AT_string (producer), producer_string) != 0)
-    {
-      struct indirect_string_node *node = find_AT_string (producer_string);
-      producer->dw_attr_val.v.val_str = node;
-    }
+  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 ();
@@ -22538,7 +23314,7 @@ dwarf2out_finish (const char *filename)
   /* Add the name for the main input file now.  We delayed this from
      dwarf2out_init to avoid complications with PCH.  */
   add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
-  if (!IS_ABSOLUTE_PATH (filename))
+  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)
     {
@@ -22548,14 +23324,15 @@ dwarf2out_finish (const char *filename)
        add_comp_dir_attribute (comp_unit_die ());
     }
 
-  for (i = 0; i < VEC_length (deferred_locations, deferred_locations_list); i++)
-    {
-      add_location_or_const_value_attribute (
-        VEC_index (deferred_locations, deferred_locations_list, i)->die,
-        VEC_index (deferred_locations, deferred_locations_list, i)->variable,
-       false,
-       DW_AT_location);
-    }
+  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
@@ -22638,11 +23415,6 @@ dwarf2out_finish (const char *filename)
   if (flag_eliminate_unused_debug_types)
     prune_unused_types ();
 
-  /* Generate separate CUs for each of the include files we've seen.
-     They will go into limbo_die_list.  */
-  if (flag_eliminate_dwarf2_dups && ! use_debug_types)
-    break_out_includes (comp_unit_die ());
-
   /* Generate separate COMDAT sections for type DIEs. */
   if (use_debug_types)
     {
@@ -22666,6 +23438,11 @@ dwarf2out_finish (const char *filename)
       prune_unused_types ();
     }
 
+  /* Generate separate CUs for each of the include files we've seen.
+     They will go into limbo_die_list.  */
+  if (flag_eliminate_dwarf2_dups)
+    break_out_includes (comp_unit_die ());
+
   /* Traverse the DIE's and add add sibling attributes to those DIE's
      that have children.  */
   add_sibling_attributes (comp_unit_die ());
@@ -22674,6 +23451,14 @@ dwarf2out_finish (const char *filename)
   for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
     add_sibling_attributes (ctnode->root_die);
 
+  /* When splitting DWARF info, we put some attributes in the
+     skeleton compile_unit DIE that remains in the .o, while
+     most attributes go in the DWO compile_unit_die.  */
+  if (dwarf_split_debug_info)
+    main_comp_unit_die = gen_compile_unit_die (NULL);
+  else
+    main_comp_unit_die = comp_unit_die ();
+
   /* Output a terminator label for the .text section.  */
   switch_to_section (text_section);
   targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
@@ -22690,10 +23475,8 @@ dwarf2out_finish (const char *filename)
     {
       /* Don't add if the CU has no associated code.  */
       if (text_section_used)
-       {
-         add_AT_lbl_id (comp_unit_die (), DW_AT_low_pc, text_section_label);
-         add_AT_lbl_id (comp_unit_die (), DW_AT_high_pc, text_end_label);
-       }
+        add_AT_low_high_pc (main_comp_unit_die, text_section_label,
+                            text_end_label, true);
     }
   else
     {
@@ -22702,20 +23485,24 @@ dwarf2out_finish (const char *filename)
       bool range_list_added = false;
 
       if (text_section_used)
-       add_ranges_by_labels (comp_unit_die (), text_section_label,
-                             text_end_label, &range_list_added);
+        add_ranges_by_labels (main_comp_unit_die, text_section_label,
+                              text_end_label, &range_list_added, true);
       if (cold_text_section_used)
-       add_ranges_by_labels (comp_unit_die (), cold_text_section_label,
-                             cold_end_label, &range_list_added);
+        add_ranges_by_labels (main_comp_unit_die, cold_text_section_label,
+                              cold_end_label, &range_list_added, true);
 
-      FOR_EACH_VEC_ELT (dw_fde_ref, fde_vec, fde_idx, fde)
+      FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde)
        {
+         if (DECL_IGNORED_P (fde->decl))
+           continue;
          if (!fde->in_std_section)
-           add_ranges_by_labels (comp_unit_die (), fde->dw_fde_begin,
-                                 fde->dw_fde_end, &range_list_added);
+            add_ranges_by_labels (main_comp_unit_die, fde->dw_fde_begin,
+                                  fde->dw_fde_end, &range_list_added,
+                                  true);
          if (fde->dw_fde_second_begin && !fde->second_in_std_section)
-           add_ranges_by_labels (comp_unit_die (), fde->dw_fde_second_begin,
-                                 fde->dw_fde_second_end, &range_list_added);
+            add_ranges_by_labels (main_comp_unit_die, fde->dw_fde_second_begin,
+                                  fde->dw_fde_second_end, &range_list_added,
+                                  true);
        }
 
       if (range_list_added)
@@ -22725,16 +23512,16 @@ dwarf2out_finish (const char *filename)
             absolute.  Historically, we've emitted the unexpected
             DW_AT_entry_pc instead of DW_AT_low_pc for this purpose.
             Emit both to give time for other tools to adapt.  */
-         add_AT_addr (comp_unit_die (), DW_AT_low_pc, const0_rtx);
+          add_AT_addr (main_comp_unit_die, DW_AT_low_pc, const0_rtx, true);
          if (! dwarf_strict && dwarf_version < 4)
-           add_AT_addr (comp_unit_die (), DW_AT_entry_pc, const0_rtx);
+            add_AT_addr (main_comp_unit_die, DW_AT_entry_pc, const0_rtx, true);
 
          add_ranges (NULL);
        }
     }
 
   if (debug_info_level >= DINFO_LEVEL_NORMAL)
-    add_AT_lineptr (comp_unit_die (), DW_AT_stmt_list,
+    add_AT_lineptr (main_comp_unit_die, DW_AT_stmt_list,
                    debug_line_section_label);
 
   if (have_macinfo)
@@ -22742,9 +23529,28 @@ dwarf2out_finish (const char *filename)
                   dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
                   macinfo_section_label);
 
+  if (dwarf_split_debug_info && addr_index_table != NULL)
+    {
+      /* optimize_location_lists calculates the size of the lists,
+         so index them first, and assign indices to the entries.
+         Although optimize_location_lists will remove entries from
+         the table, it only does so for duplicates, and therefore
+         only reduces ref_counts to 1.  */
+      unsigned int index = 0;
+      index_location_lists (comp_unit_die ());
+      htab_traverse_noresize (addr_index_table,
+                              index_addr_table_entry, &index);
+    }
   if (have_location_lists)
     optimize_location_lists (comp_unit_die ());
 
+  save_macinfo_strings ();
+  if (dwarf_split_debug_info)
+    {
+      unsigned int index = 0;
+      htab_traverse_noresize (debug_str_hash, index_string, &index);
+    }
+
   /* Output all of the compilation units.  We put the main one last so that
      the offsets are available to output_pubnames.  */
   for (node = limbo_die_list; node; node = node->next)
@@ -22764,17 +23570,58 @@ dwarf2out_finish (const char *filename)
          attributes.  */
       if (debug_info_level >= DINFO_LEVEL_NORMAL)
         add_AT_lineptr (ctnode->root_die, DW_AT_stmt_list,
-                       debug_line_section_label);
+                        (!dwarf_split_debug_info
+                         ? debug_line_section_label
+                         : debug_skeleton_line_section_label));
 
       output_comdat_type_unit (ctnode);
       *slot = ctnode;
     }
   htab_delete (comdat_type_table);
 
+  /* The AT_pubnames attribute needs to go in all skeleton dies, including
+     both the main_cu and all skeleton TUs.  Making this call unconditional
+     would end up either adding a second copy of the AT_pubnames attribute, or
+     requiring a special case in add_top_level_skeleton_die_attrs.  */
+  if (!dwarf_split_debug_info)
+    add_AT_pubnames (comp_unit_die ());
+
+  if (dwarf_split_debug_info)
+    {
+      int mark;
+      unsigned char checksum[16];
+      struct md5_ctx ctx;
+
+      /* Compute a checksum of the comp_unit to use as the dwo_id.  */
+      md5_init_ctx (&ctx);
+      mark = 0;
+      die_checksum (comp_unit_die (), &ctx, &mark);
+      unmark_all_dies (comp_unit_die ());
+      md5_finish_ctx (&ctx, checksum);
+
+      /* Use the first 8 bytes of the checksum as the dwo_id,
+        and add it to both comp-unit DIEs.  */
+      add_AT_data8 (main_comp_unit_die, DW_AT_GNU_dwo_id, checksum);
+      add_AT_data8 (comp_unit_die (), DW_AT_GNU_dwo_id, checksum);
+
+      /* Add the base offset of the ranges table to the skeleton
+        comp-unit DIE.  */
+      if (ranges_table_in_use)
+        add_AT_lineptr (main_comp_unit_die, DW_AT_GNU_ranges_base,
+                        ranges_section_label);
+
+      switch_to_section (debug_addr_section);
+      ASM_OUTPUT_LABEL (asm_out_file, debug_addr_section_label);
+      output_addr_table ();
+    }
+
   /* Output the main compilation unit if non-empty or if .debug_macinfo
      or .debug_macro will be emitted.  */
   output_comp_unit (comp_unit_die (), have_macinfo);
 
+  if (dwarf_split_debug_info && info_section_emitted)
+    output_skeleton_debug_sections (main_comp_unit_die);
+
   /* Output the abbreviation table.  */
   if (abbrev_die_table_in_use != 1)
     {
@@ -22788,48 +23635,16 @@ dwarf2out_finish (const char *filename)
     {
       /* Output the location lists info.  */
       switch_to_section (debug_loc_section);
-      ASM_GENERATE_INTERNAL_LABEL (loc_section_label,
-                                  DEBUG_LOC_SECTION_LABEL, 0);
       ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
       output_location_lists (comp_unit_die ());
     }
 
-  /* Output public names table if necessary.  */
-  if (!VEC_empty (pubname_entry, pubname_table))
-    {
-      gcc_assert (info_section_emitted);
-      switch_to_section (debug_pubnames_section);
-      output_pubnames (pubname_table);
-    }
-
-  /* Output public types table if necessary.  */
+  /* Output public names and types tables if necessary.  */
+  output_pubnames (pubname_table);
   /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2.
      It shouldn't hurt to emit it always, since pure DWARF2 consumers
      simply won't look for the section.  */
-  if (!VEC_empty (pubname_entry, pubtype_table))
-    {
-      bool empty = false;
-      
-      if (flag_eliminate_unused_debug_types)
-       {
-         /* The pubtypes table might be emptied by pruning unused items.  */
-         unsigned i;
-         pubname_ref p;
-         empty = true;
-         FOR_EACH_VEC_ELT (pubname_entry, pubtype_table, i, p)
-           if (p->die->die_offset != 0)
-             {
-               empty = false;
-               break;
-             }
-       }
-      if (!empty)
-       {
-         gcc_assert (info_section_emitted);
-         switch_to_section (debug_pubtypes_section);
-         output_pubnames (pubtype_table);
-       }
-    }
+  output_pubnames (pubtype_table);
 
   /* Output the address range information if a CU (.debug_info section)
      was emitted.  We output an empty table even if we had no functions
@@ -22870,12 +23685,18 @@ dwarf2out_finish (const char *filename)
   switch_to_section (debug_line_section);
   ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label);
   if (! DWARF2_ASM_LINE_DEBUG_INFO)
-    output_line_info ();
+    output_line_info (false);
+
+  if (dwarf_split_debug_info && info_section_emitted)
+    {
+      switch_to_section (debug_skeleton_line_section);
+      ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_line_section_label);
+      output_line_info (true);
+    }
 
-  /* If we emitted any DW_FORM_strp form attribute, output the string
-     table too.  */
+  /* If we emitted any indirect strings, output the string table too.  */
   if (debug_str_hash)
-    htab_traverse (debug_str_hash, output_indirect_string, NULL);
+    output_indirect_strings ();
 }
 
 #include "gt-dwarf2out.h"