dwarf2out.c (build_abbrev_table): Guard lookup_external_ref call with is_type_die.
[gcc.git] / gcc / dwarf2out.c
index 8377cbc5dd1a97cf6a6759d5b52d29b49011845f..8b478aa265fd83f0d4faf8c0f360356734128ab5 100644 (file)
@@ -102,6 +102,7 @@ static void dwarf2out_source_line (unsigned int, unsigned int, const char *,
 static rtx_insn *last_var_location_insn;
 static rtx_insn *cached_next_real_insn;
 static void dwarf2out_decl (tree);
+static bool is_redundant_typedef (const_tree);
 
 #ifndef XCOFF_DEBUGGING_INFO
 #define XCOFF_DEBUGGING_INFO 0
@@ -297,6 +298,10 @@ static unsigned int rnglist_idx;
 #define FUNC_BEGIN_LABEL       "LFB"
 #endif
 
+#ifndef FUNC_SECOND_SECT_LABEL
+#define FUNC_SECOND_SECT_LABEL "LFSB"
+#endif
+
 #ifndef FUNC_END_LABEL
 #define FUNC_END_LABEL         "LFE"
 #endif
@@ -1212,21 +1217,24 @@ static void set_cur_line_info_table (section *);
 void
 dwarf2out_switch_text_section (void)
 {
+  char label[MAX_ARTIFICIAL_LABEL_BYTES];
   section *sect;
   dw_fde_ref fde = cfun->fde;
 
   gcc_assert (cfun && fde && fde->dw_fde_second_begin == NULL);
 
+  ASM_GENERATE_INTERNAL_LABEL (label, FUNC_SECOND_SECT_LABEL,
+                              current_function_funcdef_no);
+
+  fde->dw_fde_second_begin = ggc_strdup (label);
   if (!in_cold_section_p)
     {
       fde->dw_fde_end = crtl->subsections.cold_section_end_label;
-      fde->dw_fde_second_begin = crtl->subsections.hot_section_label;
       fde->dw_fde_second_end = crtl->subsections.hot_section_end_label;
     }
   else
     {
       fde->dw_fde_end = crtl->subsections.hot_section_end_label;
-      fde->dw_fde_second_begin = crtl->subsections.cold_section_label;
       fde->dw_fde_second_end = crtl->subsections.cold_section_end_label;
     }
   have_multiple_function_sections = true;
@@ -3641,7 +3649,6 @@ static void add_AT_specification (dw_die_ref, dw_die_ref);
 static inline dw_die_ref AT_ref (dw_attr_node *);
 static inline int AT_ref_external (dw_attr_node *);
 static inline void set_AT_ref_external (dw_attr_node *, int);
-static void add_AT_fde_ref (dw_die_ref, enum dwarf_attribute, unsigned);
 static void add_AT_loc (dw_die_ref, enum dwarf_attribute, dw_loc_descr_ref);
 static inline dw_loc_descr_ref AT_loc (dw_attr_node *);
 static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute,
@@ -3657,20 +3664,16 @@ static void add_AT_symview (dw_die_ref, enum dwarf_attribute, const char *);
 static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *);
 static void add_AT_lineptr (dw_die_ref, enum dwarf_attribute, const char *);
 static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *);
-static void add_AT_loclistsptr (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, bool);
 static inline const char *AT_lbl (dw_attr_node *);
 static dw_attr_node *get_AT (dw_die_ref, enum dwarf_attribute);
 static const char *get_AT_low_pc (dw_die_ref);
-static const char *get_AT_hi_pc (dw_die_ref);
 static const char *get_AT_string (dw_die_ref, enum dwarf_attribute);
 static int get_AT_flag (dw_die_ref, enum dwarf_attribute);
 static unsigned get_AT_unsigned (dw_die_ref, enum dwarf_attribute);
 static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
+static bool is_c (void);
 static bool is_cxx (void);
 static bool is_cxx (const_tree);
 static bool is_fortran (void);
@@ -3707,7 +3710,6 @@ static int same_dw_val_p (const dw_val_node *, const dw_val_node *, int *);
 static int same_attr_p (dw_attr_node *, dw_attr_node *, int *);
 static int same_die_p (dw_die_ref, dw_die_ref, int *);
 static int is_type_die (dw_die_ref);
-static int is_comdat_die (dw_die_ref);
 static inline bool is_template_instantiation (dw_die_ref);
 static int is_declaration_die (dw_die_ref);
 static int should_move_die_to_comdat (dw_die_ref);
@@ -3764,7 +3766,6 @@ static int decl_quals (const_tree);
 static dw_die_ref modified_type_die (tree, int, bool, dw_die_ref);
 static dw_die_ref generic_parameter_die (tree, tree, bool, dw_die_ref);
 static dw_die_ref template_parameter_pack_die (tree, tree, dw_die_ref);
-static int type_is_enum (const_tree);
 static unsigned int dbx_reg_number (const_rtx);
 static void add_loc_descr_op_piece (dw_loc_descr_ref *, int);
 static dw_loc_descr_ref reg_loc_descriptor (rtx, enum var_init_status);
@@ -3787,7 +3788,6 @@ static dw_loc_list_ref loc_list_from_tree (tree, int,
                                           struct loc_descr_context *);
 static dw_loc_descr_ref loc_descriptor_from_tree (tree, int,
                                                  struct loc_descr_context *);
-static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
 static tree field_type (const_tree);
 static unsigned int simple_type_align_in_bits (const_tree);
 static unsigned int simple_decl_align_in_bits (const_tree);
@@ -3808,6 +3808,7 @@ static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool);
 static bool tree_add_const_value_attribute (dw_die_ref, tree);
 static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
+static void add_desc_attribute (dw_die_ref, tree);
 static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref);
 static void add_comp_dir_attribute (dw_die_ref);
 static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int,
@@ -3821,7 +3822,7 @@ static inline void add_bit_offset_attribute (dw_die_ref, tree,
                                             struct vlr_context *);
 static void add_bit_size_attribute (dw_die_ref, tree);
 static void add_prototyped_attribute (dw_die_ref, tree);
-static dw_die_ref add_abstract_origin_attribute (dw_die_ref, tree);
+static void add_abstract_origin_attribute (dw_die_ref, tree);
 static void add_pure_or_virtual_attribute (dw_die_ref, tree);
 static void add_src_coords_attributes (dw_die_ref, tree);
 static void add_name_and_src_coords_attributes (dw_die_ref, tree, bool = false);
@@ -3866,7 +3867,7 @@ static void gen_subroutine_type_die (tree, dw_die_ref);
 static void gen_typedef_die (tree, dw_die_ref);
 static void gen_type_die (tree, dw_die_ref);
 static void gen_block_die (tree, dw_die_ref);
-static void decls_for_scope (tree, dw_die_ref);
+static void decls_for_scope (tree, dw_die_ref, bool = true);
 static bool is_naming_typedef_decl (const_tree);
 static inline dw_die_ref get_context_die (tree);
 static void gen_namespace_die (tree, dw_die_ref);
@@ -3900,8 +3901,6 @@ static void prune_unused_types (void);
 static int maybe_emit_file (struct dwarf_file_data *fd);
 static inline const char *AT_vms_delta1 (dw_attr_node *);
 static inline const char *AT_vms_delta2 (dw_attr_node *);
-static inline void add_AT_vms_delta (dw_die_ref, enum dwarf_attribute,
-                                    const char *, const char *);
 static void append_entry_to_tmpl_value_parm_die_table (dw_die_ref, tree);
 static void gen_remaining_tmpl_value_param_die_attribute (void);
 static bool generic_type_p (tree);
@@ -4826,20 +4825,6 @@ set_AT_ref_external (dw_attr_node *a, int i)
   a->dw_attr_val.v.val_die_ref.external = i;
 }
 
-/* Add an FDE reference attribute value to a DIE.  */
-
-static inline void
-add_AT_fde_ref (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int targ_fde)
-{
-  dw_attr_node attr;
-
-  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);
-}
-
 /* Add a location description attribute value to a DIE.  */
 
 static inline void
@@ -5150,22 +5135,6 @@ AT_file (dw_attr_node *a)
   return a->dw_attr_val.v.val_file;
 }
 
-/* Add a vms delta attribute value to a DIE.  */
-
-static inline void
-add_AT_vms_delta (dw_die_ref die, enum dwarf_attribute attr_kind,
-                 const char *lbl1, const char *lbl2)
-{
-  dw_attr_node attr;
-
-  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);
-}
-
 /* Add a symbolic view identifier attribute value to a DIE.  */
 
 static inline void
@@ -5216,22 +5185,6 @@ add_AT_lineptr (dw_die_ref die, enum dwarf_attribute attr_kind,
   add_dwarf_attr (die, &attr);
 }
 
-/* Add a section offset attribute value to a DIE, an offset into the
-   debug_loclists section.  */
-
-static inline void
-add_AT_loclistsptr (dw_die_ref die, enum dwarf_attribute attr_kind,
-                   const char *label)
-{
-  dw_attr_node attr;
-
-  attr.dw_attr = attr_kind;
-  attr.dw_attr_val.val_class = dw_val_class_loclistsptr;
-  attr.dw_attr_val.val_entry = NULL;
-  attr.dw_attr_val.v.val_lbl_id = xstrdup (label);
-  add_dwarf_attr (die, &attr);
-}
-
 /* Add a section offset attribute value to a DIE, an offset into the
    debug_macinfo section.  */
 
@@ -5248,21 +5201,6 @@ add_AT_macptr (dw_die_ref die, enum dwarf_attribute attr_kind,
   add_dwarf_attr (die, &attr);
 }
 
-/* Add an offset attribute value to a DIE.  */
-
-static inline void
-add_AT_offset (dw_die_ref die, enum dwarf_attribute attr_kind,
-              unsigned HOST_WIDE_INT offset)
-{
-  dw_attr_node attr;
-
-  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 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
@@ -5373,18 +5311,6 @@ get_AT_low_pc (dw_die_ref die)
   return a ? AT_lbl (a) : NULL;
 }
 
-/* Return the "high pc" attribute value, typically associated with a subprogram
-   DIE.  Return null if the "high pc" attribute is either not present, or if it
-   cannot be represented as an assembler label identifier.  */
-
-static inline const char *
-get_AT_hi_pc (dw_die_ref die)
-{
-  dw_attr_node *a = get_AT (die, DW_AT_high_pc);
-
-  return a ? AT_lbl (a) : NULL;
-}
-
 /* Return the value of the string attribute designated by ATTR_KIND, or
    NULL if it is not present.  */
 
@@ -5434,6 +5360,19 @@ get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind)
   return a ? AT_file (a) : NULL;
 }
 
+/* Return TRUE if the language is C.  */
+
+static inline bool
+is_c (void)
+{
+  unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
+
+  return (lang == DW_LANG_C || lang == DW_LANG_C89 || lang == DW_LANG_C99
+         || lang == DW_LANG_C11 || lang == DW_LANG_ObjC);
+
+
+}
+
 /* Return TRUE if the language is C++.  */
 
 static inline bool
@@ -5498,6 +5437,16 @@ is_ada (void)
   return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
 }
 
+/* Return TRUE if the language is D.  */
+
+static inline bool
+is_dlang (void)
+{
+  unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
+
+  return lang == DW_LANG_D;
+}
+
 /* Remove the specified attribute if present.  Return TRUE if removal
    was successful.  */
 
@@ -5807,6 +5756,14 @@ equate_type_number_to_die (tree type, dw_die_ref type_die)
   TYPE_SYMTAB_DIE (type) = type_die;
 }
 
+static dw_die_ref maybe_create_die_with_external_ref (tree);
+struct GTY(()) sym_off_pair 
+{
+  const char * GTY((skip)) sym;
+  unsigned HOST_WIDE_INT off;
+};
+static GTY(()) hash_map<tree, sym_off_pair> *external_die_map;
+
 /* Returns a hash value for X (which really is a die_struct).  */
 
 inline hashval_t
@@ -5831,7 +5788,11 @@ lookup_decl_die (tree decl)
   dw_die_ref *die = decl_die_table->find_slot_with_hash (decl, DECL_UID (decl),
                                                         NO_INSERT);
   if (!die)
-    return NULL;
+    {
+      if (in_lto_p)
+       return maybe_create_die_with_external_ref (decl);
+      return NULL;
+    }
   if ((*die)->removed)
     {
       decl_die_table->clear_slot (die);
@@ -5841,6 +5802,27 @@ lookup_decl_die (tree decl)
 }
 
 
+/* Return the DIE associated with BLOCK.  */
+
+static inline dw_die_ref
+lookup_block_die (tree block)
+{
+  dw_die_ref die = BLOCK_DIE (block);
+  if (!die && in_lto_p)
+    return maybe_create_die_with_external_ref (block);
+  return die;
+}
+
+/* Associate DIE with BLOCK.  */
+
+static inline void
+equate_block_to_die (tree block, dw_die_ref die)
+{
+  BLOCK_DIE (block) = die;
+}
+#undef BLOCK_DIE
+
+
 /* For DECL which might have early dwarf output query a SYMBOL + OFFSET
    style reference.  Return true if we found one refering to a DIE for
    DECL, otherwise return false.  */
@@ -5851,32 +5833,27 @@ dwarf2out_die_ref_for_decl (tree decl, const char **sym,
 {
   dw_die_ref die;
 
-  if (in_lto_p && !decl_die_table)
-    return false;
+  if (in_lto_p)
+    {
+      /* During WPA stage and incremental linking we use a hash-map
+        to store the decl <-> label + offset map.  */
+      if (!external_die_map)
+       return false;
+      sym_off_pair *desc = external_die_map->get (decl);
+      if (!desc)
+       return false;
+      *sym = desc->sym;
+      *off = desc->off;
+      return true;
+    }
 
   if (TREE_CODE (decl) == BLOCK)
-    die = BLOCK_DIE (decl);
+    die = lookup_block_die (decl);
   else
     die = lookup_decl_die (decl);
   if (!die)
     return false;
 
-  /* During WPA stage and incremental linking we currently use DIEs
-     to store the decl <-> label + offset map.  That's quite inefficient
-     but it works for now.  */
-  if (in_lto_p)
-    {
-      dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
-      if (!ref)
-       {
-         gcc_assert (die == comp_unit_die ());
-         return false;
-       }
-      *off = ref->die_offset;
-      *sym = ref->die_id.die_symbol;
-      return true;
-    }
-
   /* Similar to get_ref_die_offset_label, but using the "correct"
      label.  */
   *off = die->die_offset;
@@ -5898,8 +5875,10 @@ add_AT_external_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind,
 {
   /* Create a fake DIE that contains the reference.  Don't use
      new_die because we don't want to end up in the limbo list.  */
+  /* ???  We probably want to share these, thus put a ref to the DIE
+     we create here to the external_die_map entry.  */
   dw_die_ref ref = new_die_raw (die->die_tag);
-  ref->die_id.die_symbol = IDENTIFIER_POINTER (get_identifier (symbol));
+  ref->die_id.die_symbol = symbol;
   ref->die_offset = offset;
   ref->with_offset = 1;
   add_AT_die_ref (die, attr_kind, ref);
@@ -5915,13 +5894,33 @@ dwarf2out_register_external_die (tree decl, const char *sym,
   if (debug_info_level == DINFO_LEVEL_NONE)
     return;
 
-  if ((flag_wpa
-       || flag_incremental_link == INCREMENTAL_LINK_LTO) && !decl_die_table)
-    decl_die_table = hash_table<decl_die_hasher>::create_ggc (1000);
+  if (!external_die_map)
+    external_die_map = hash_map<tree, sym_off_pair>::create_ggc (1000);
+  gcc_checking_assert (!external_die_map->get (decl));
+  sym_off_pair p = { IDENTIFIER_POINTER (get_identifier (sym)), off };
+  external_die_map->put (decl, p);
+}
+
+/* If we have a registered external DIE for DECL return a new DIE for
+   the concrete instance with an appropriate abstract origin.  */
+
+static dw_die_ref
+maybe_create_die_with_external_ref (tree decl)
+{
+  if (!external_die_map)
+    return NULL;
+  sym_off_pair *desc = external_die_map->get (decl);
+  if (!desc)
+    return NULL;
+
+  const char *sym = desc->sym;
+  unsigned HOST_WIDE_INT off = desc->off;
 
-  dw_die_ref die
-    = TREE_CODE (decl) == BLOCK ? BLOCK_DIE (decl) : lookup_decl_die (decl);
+  in_lto_p = false;
+  dw_die_ref die = (TREE_CODE (decl) == BLOCK
+                   ? lookup_block_die (decl) : lookup_decl_die (decl));
   gcc_assert (!die);
+  in_lto_p = true;
 
   tree ctx;
   dw_die_ref parent = NULL;
@@ -5933,7 +5932,7 @@ dwarf2out_register_external_die (tree decl, const char *sym,
       /* ???  We do not output DIEs for all scopes thus skip as
         many DIEs as needed.  */
       while (TREE_CODE (ctx) == BLOCK
-            && !BLOCK_DIE (ctx))
+            && !lookup_block_die (ctx))
        ctx = BLOCK_SUPERCONTEXT (ctx);
     }
   else
@@ -5948,7 +5947,7 @@ dwarf2out_register_external_die (tree decl, const char *sym,
   if (ctx)
     {
       if (TREE_CODE (ctx) == BLOCK)
-       parent = BLOCK_DIE (ctx);
+       parent = lookup_block_die (ctx);
       else if (TREE_CODE (ctx) == TRANSLATION_UNIT_DECL
               /* Keep the 1:1 association during WPA.  */
               && !flag_wpa
@@ -5975,18 +5974,12 @@ dwarf2out_register_external_die (tree decl, const char *sym,
   switch (TREE_CODE (decl))
     {
     case TRANSLATION_UNIT_DECL:
-      if (! flag_wpa && flag_incremental_link != INCREMENTAL_LINK_LTO)
-       {
-         die = comp_unit_die ();
-         dw_die_ref import = new_die (DW_TAG_imported_unit, die, NULL_TREE);
-         add_AT_external_die_ref (import, DW_AT_import, sym, off);
-         /* We re-target all CU decls to the LTRANS CU DIE, so no need
-            to create a DIE for the original CUs.  */
-         return;
-       }
-      /* Keep the 1:1 association during WPA.  */
-      die = new_die (DW_TAG_compile_unit, NULL, decl);
-      break;
+      {
+       die = comp_unit_die ();
+       /* We re-target all CU decls to the LTRANS CU DIE, so no need
+          to create a DIE for the original CUs.  */
+       return die;
+      }
     case NAMESPACE_DECL:
       if (is_fortran (decl))
        die = new_die (DW_TAG_module, parent, decl);
@@ -6018,12 +6011,16 @@ dwarf2out_register_external_die (tree decl, const char *sym,
       gcc_unreachable ();
     }
   if (TREE_CODE (decl) == BLOCK)
-    BLOCK_DIE (decl) = die;
+    equate_block_to_die (decl, die);
   else
     equate_decl_number_to_die (decl, die);
 
+  add_desc_attribute (die, decl);
+
   /* Add a reference to the DIE providing early debug at $sym + off.  */
   add_AT_external_die_ref (die, DW_AT_abstract_origin, sym, off);
+
+  return die;
 }
 
 /* Returns a hash value for X (which really is a var_loc_list).  */
@@ -6455,7 +6452,12 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
          print_indent -= 4;
        }
       else
-       fprintf (outfile, " (%p)\n", (void *) val->v.val_loc);
+       {
+         if (flag_dump_noaddr || flag_dump_unnumbered)
+           fprintf (outfile, " #\n");
+         else
+           fprintf (outfile, " (%p)\n", (void *) val->v.val_loc);
+       }
       break;
     case dw_val_class_loc_list:
       fprintf (outfile, "location list -> label:%s",
@@ -6524,7 +6526,10 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
            }
          else
            fprintf (outfile, "die -> %ld", die->die_offset);
-         fprintf (outfile, " (%p)", (void *) die);
+         if (flag_dump_noaddr || flag_dump_unnumbered)
+           fprintf (outfile, " #");
+         else
+           fprintf (outfile, " (%p)", (void *) die);
        }
       else
        fprintf (outfile, "die -> <null>");
@@ -6614,8 +6619,11 @@ print_loc_descr (dw_loc_descr_ref loc, FILE *outfile)
   for (l = loc; l != NULL; l = l->dw_loc_next)
     {
       print_spaces (outfile);
-      fprintf (outfile, "(%p) %s",
-              (void *) l,
+      if (flag_dump_noaddr || flag_dump_unnumbered)
+       fprintf (outfile, "#");
+      else
+       fprintf (outfile, "(%p)", (void *) l);
+      fprintf (outfile, " %s",
               dwarf_stack_op_name (l->dw_loc_opc));
       if (l->dw_loc_oprnd1.val_class != dw_val_class_none)
        {
@@ -6642,9 +6650,12 @@ print_die (dw_die_ref die, FILE *outfile)
   unsigned ix;
 
   print_spaces (outfile);
-  fprintf (outfile, "DIE %4ld: %s (%p)\n",
-          die->die_offset, dwarf_tag_name (die->die_tag),
-          (void*) die);
+  fprintf (outfile, "DIE %4ld: %s ",
+          die->die_offset, dwarf_tag_name (die->die_tag));
+  if (flag_dump_noaddr || flag_dump_unnumbered)
+    fprintf (outfile, "#\n");
+  else
+    fprintf (outfile, "(%p)\n", (void*) die);
   print_spaces (outfile);
   fprintf (outfile, "  abbrev id: %lu", die->die_abbrev);
   fprintf (outfile, " offset: %ld", die->die_offset);
@@ -7868,36 +7879,6 @@ is_type_die (dw_die_ref die)
     }
 }
 
-/* Returns 1 iff C is the sort of DIE that should go into a COMDAT CU.
-   Basically, we want to choose the bits that are likely to be shared between
-   compilations (types) and leave out the bits that are specific to individual
-   compilations (functions).  */
-
-static int
-is_comdat_die (dw_die_ref c)
-{
-  /* I think we want to leave base types and __vtbl_ptr_type in the main CU, as
-     we do for stabs.  The advantage is a greater likelihood of sharing between
-     objects that don't include headers in the same order (and therefore would
-     put the base types in a different comdat).  jason 8/28/00 */
-
-  if (c->die_tag == DW_TAG_base_type)
-    return 0;
-
-  if (c->die_tag == DW_TAG_pointer_type
-      || c->die_tag == DW_TAG_reference_type
-      || c->die_tag == DW_TAG_rvalue_reference_type
-      || c->die_tag == DW_TAG_const_type
-      || c->die_tag == DW_TAG_volatile_type)
-    {
-      dw_die_ref t = get_AT_ref (c, DW_AT_type);
-
-      return t ? is_comdat_die (t) : 0;
-    }
-
-  return is_type_die (c);
-}
-
 /* Returns true iff C is a compile-unit DIE.  */
 
 static inline bool
@@ -7926,15 +7907,6 @@ 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);
-}
-
 /* Return non-zero if this DIE is a template parameter.  */
 
 static inline bool
@@ -9051,8 +9023,9 @@ build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
        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)
+       if (is_type_die (c)
+           && (ref_p = lookup_external_ref (extern_map, c))
+           && 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.  */
@@ -13664,15 +13637,6 @@ template_parameter_pack_die (tree parm_pack,
   return die;
 }
 
-/* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is
-   an enumerated type.  */
-
-static inline int
-type_is_enum (const_tree type)
-{
-  return TREE_CODE (type) == ENUMERAL_TYPE;
-}
-
 /* Return the DBX register number described by a given RTL node.  */
 
 static unsigned int
@@ -14303,13 +14267,13 @@ based_loc_descr (rtx reg, poly_int64 offset,
 
       if (elim != reg)
        {
+         /* Allow hard frame pointer here even if frame pointer
+           isn't used since hard frame pointer is encoded with
+           DW_OP_fbreg which uses the DW_AT_frame_base attribute,
+           not hard frame pointer directly.  */
          elim = strip_offset_and_add (elim, &offset);
-         gcc_assert ((SUPPORTS_STACK_ALIGNMENT
-                      && (elim == hard_frame_pointer_rtx
-                          || elim == stack_pointer_rtx))
-                     || elim == (frame_pointer_needed
-                                 ? hard_frame_pointer_rtx
-                                 : stack_pointer_rtx));
+         gcc_assert (elim == hard_frame_pointer_rtx
+                     || elim == stack_pointer_rtx);
 
          /* If drap register is used to align stack, use frame
             pointer + offset to access stack variables.  If stack
@@ -15476,7 +15440,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 
          if (dwarf_strict && dwarf_version < 5)
            break;
-         if (REGNO (rtl) > FIRST_PSEUDO_REGISTER)
+         if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
            break;
          type_die = base_type_for_mode (mode, SCALAR_INT_MODE_P (mode));
          if (type_die == NULL)
@@ -16321,6 +16285,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
     case CONST_FIXED:
     case CLRSB:
     case CLOBBER:
+    case CLOBBER_HIGH:
       /* 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.  */
@@ -18893,15 +18858,6 @@ loc_descriptor_from_tree (tree loc, int want_address,
   return ret->expr;
 }
 
-/* Given a value, round it up to the lowest multiple of `boundary'
-   which is not less than the value itself.  */
-
-static inline HOST_WIDE_INT
-ceiling (HOST_WIDE_INT value, unsigned int boundary)
-{
-  return (((value + boundary - 1) / boundary) * boundary);
-}
-
 /* Given a pointer to what is assumed to be a FIELD_DECL node, return a
    pointer to the declared type for the relevant field variable, or return
    `integer_type_node' if the given node turns out to be an
@@ -20489,14 +20445,13 @@ compute_frame_pointer_to_fb_displacement (poly_int64 offset)
      in which to eliminate.  This is because it's stack pointer isn't 
      directly accessible as a register within the ISA.  To work around
      this, assume that while we cannot provide a proper value for
-     frame_pointer_fb_offset, we won't need one either.  */
+     frame_pointer_fb_offset, we won't need one either.  We can use
+     hard frame pointer in debug info even if frame pointer isn't used
+     since hard frame pointer in debug info is encoded with DW_OP_fbreg
+     which uses the DW_AT_frame_base attribute, not hard frame pointer
+     directly.  */
   frame_pointer_fb_offset_valid
-    = ((SUPPORTS_STACK_ALIGNMENT
-       && (elim == hard_frame_pointer_rtx
-           || elim == stack_pointer_rtx))
-       || elim == (frame_pointer_needed
-                  ? hard_frame_pointer_rtx
-                  : stack_pointer_rtx));
+    = (elim == hard_frame_pointer_rtx || elim == stack_pointer_rtx);
 }
 
 /* Generate a DW_AT_name attribute given some string value to be included as
@@ -20514,6 +20469,52 @@ add_name_attribute (dw_die_ref die, const char *name_string)
     }
 }
 
+/* Generate a DW_AT_description attribute given some string value to be included
+   as the value of the attribute.  */
+
+static void
+add_desc_attribute (dw_die_ref die, const char *name_string)
+{
+  if (!flag_describe_dies || (dwarf_version < 3 && dwarf_strict))
+    return;
+
+  if (name_string == NULL || *name_string == 0)
+    return;
+
+  if (demangle_name_func)
+    name_string = (*demangle_name_func) (name_string);
+
+  add_AT_string (die, DW_AT_description, name_string);
+}
+
+/* Generate a DW_AT_description attribute given some decl to be included
+   as the value of the attribute.  */
+
+static void
+add_desc_attribute (dw_die_ref die, tree decl)
+{
+  tree decl_name;
+
+  if (!flag_describe_dies || (dwarf_version < 3 && dwarf_strict))
+    return;
+
+  if (decl == NULL_TREE || !DECL_P (decl))
+    return;
+  decl_name = DECL_NAME (decl);
+
+  if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL)
+    {
+      const char *name = dwarf2_name (decl, 0);
+      add_desc_attribute (die, name ? name : IDENTIFIER_POINTER (decl_name));
+    }
+  else
+    {
+      char *desc = print_generic_expr_to_str (decl);
+      add_desc_attribute (die, desc);
+      free (desc);
+    }
+}
+
 /* Retrieve the descriptive type of TYPE, if any, make sure it has a
    DIE and attach a DW_AT_GNAT_descriptive_type attribute to the DIE
    of TYPE accordingly.
@@ -20597,7 +20598,7 @@ static void
 add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
                 int forms, struct loc_descr_context *context)
 {
-  dw_die_ref context_die, decl_die;
+  dw_die_ref context_die, decl_die = NULL;
   dw_loc_list_ref list;
   bool strip_conversions = true;
   bool placeholder_seen = false;
@@ -20674,7 +20675,7 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
 
       if (decl != NULL_TREE)
        {
-         dw_die_ref decl_die = lookup_decl_die (decl);
+         decl_die = lookup_decl_die (decl);
 
          /* ??? Can this happen, or should the variable have been bound
             first?  Probably it can, since I imagine that we try to create
@@ -20683,8 +20684,12 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
             later parameter.  */
          if (decl_die != NULL)
            {
-             add_AT_die_ref (die, attr, decl_die);
-             return;
+             if (get_AT (decl_die, DW_AT_location)
+                 || get_AT (decl_die, DW_AT_const_value))
+               {
+                 add_AT_die_ref (die, attr, decl_die);
+                 return;
+               }
            }
        }
     }
@@ -20728,15 +20733,19 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
       || placeholder_seen)
     return;
 
-  if (current_function_decl == 0)
-    context_die = comp_unit_die ();
-  else
-    context_die = lookup_decl_die (current_function_decl);
+  if (!decl_die)
+    {
+      if (current_function_decl == 0)
+       context_die = comp_unit_die ();
+      else
+       context_die = lookup_decl_die (current_function_decl);
+
+      decl_die = new_die (DW_TAG_variable, context_die, value);
+      add_AT_flag (decl_die, DW_AT_artificial, 1);
+      add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, false,
+                         context_die);
+    }
 
-  decl_die = new_die (DW_TAG_variable, context_die, value);
-  add_AT_flag (decl_die, DW_AT_artificial, 1);
-  add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, false,
-                     context_die);
   add_AT_location_description (decl_die, DW_AT_location, list);
   add_AT_die_ref (die, attr, decl_die);
 }
@@ -20921,8 +20930,16 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
 
          if (!get_AT (subrange_die, DW_AT_lower_bound))
            add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
-         if (upper && !get_AT (subrange_die, DW_AT_upper_bound))
-           add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL);
+         if (!get_AT (subrange_die, DW_AT_upper_bound)
+             && !get_AT (subrange_die, DW_AT_count))
+           {
+             if (upper)
+               add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL);
+             else if ((is_c () || is_cxx ()) && COMPLETE_TYPE_P (type))
+               /* Zero-length array.  */
+               add_bound_info (subrange_die, DW_AT_count,
+                               build_int_cst (TREE_TYPE (lower), 0), NULL);
+           }
        }
 
       /* Otherwise we have an array type with an unspecified length.  The
@@ -21121,28 +21138,30 @@ add_prototyped_attribute (dw_die_ref die, tree func_type)
    by looking in the type declaration, the object declaration equate table or
    the block mapping.  */
 
-static inline dw_die_ref
+static inline void
 add_abstract_origin_attribute (dw_die_ref die, tree origin)
 {
   dw_die_ref origin_die = NULL;
 
-  if (DECL_P (origin))
+  /* For late LTO debug output we want to refer directly to the abstract
+     DIE in the early debug rather to the possibly existing concrete
+     instance and avoid creating that just for this purpose.  */
+  sym_off_pair *desc;
+  if (in_lto_p
+      && external_die_map
+      && (desc = external_die_map->get (origin)))
     {
-      dw_die_ref c;
-      origin_die = lookup_decl_die (origin);
-      /* "Unwrap" the decls DIE which we put in the imported unit context.
-         We are looking for the abstract copy here.  */
-      if (in_lto_p
-         && origin_die
-         && (c = get_AT_ref (origin_die, DW_AT_abstract_origin))
-         /* ???  Identify this better.  */
-         && c->with_offset)
-       origin_die = c;
+      add_AT_external_die_ref (die, DW_AT_abstract_origin,
+                              desc->sym, desc->off);
+      return;
     }
+
+  if (DECL_P (origin))
+    origin_die = lookup_decl_die (origin);
   else if (TYPE_P (origin))
     origin_die = lookup_type_die (origin);
   else if (TREE_CODE (origin) == BLOCK)
-    origin_die = BLOCK_DIE (origin);
+    origin_die = lookup_block_die (origin);
 
   /* XXX: Functions that are never lowered don't always have correct block
      trees (in the case of java, they simply have no block tree, in some other
@@ -21155,7 +21174,6 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
 
   if (origin_die)
     add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
-  return origin_die;
 }
 
 /* We do not currently support the pure_virtual attribute.  */
@@ -21264,12 +21282,17 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl,
       const char *name = dwarf2_name (decl, 0);
       if (name)
        add_name_attribute (die, name);
+      else
+       add_desc_attribute (die, decl);
+
       if (! DECL_ARTIFICIAL (decl))
        add_src_coords_attributes (die, decl);
 
       if (!no_linkage_name)
        add_linkage_name (die, decl);
     }
+  else
+    add_desc_attribute (die, decl);
 
 #ifdef VMS_DEBUGGING_INFO
   /* Get the function's name, as described by its RTL.  This may be different
@@ -22446,14 +22469,15 @@ dwarf2out_abstract_function (tree decl)
   if (DECL_IGNORED_P (decl))
     return;
 
-  old_die = lookup_decl_die (decl);
-  /* With early debug we always have an old DIE unless we are in LTO
-     and the user did not compile but only link with debug.  */
-  if (in_lto_p && ! old_die)
+  /* In LTO we're all set.  We already created abstract instances
+     early and we want to avoid creating a concrete instance of that
+     if we don't output it.  */
+  if (in_lto_p)
     return;
+
+  old_die = lookup_decl_die (decl);
   gcc_assert (old_die != NULL);
-  if (get_AT (old_die, DW_AT_inline)
-      || get_AT (old_die, DW_AT_abstract_origin))
+  if (get_AT (old_die, DW_AT_inline))
     /* We've already generated the abstract instance.  */
     return;
 
@@ -22564,7 +22588,7 @@ gen_call_site_die (tree decl, dw_die_ref subr_die,
         && block != DECL_INITIAL (decl)
         && TREE_CODE (block) == BLOCK)
     {
-      stmt_die = BLOCK_DIE (block);
+      stmt_die = lookup_block_die (block);
       if (stmt_die)
        break;
       block = BLOCK_SUPERCONTEXT (block);
@@ -22766,6 +22790,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
             */
            || (old_die->die_parent
                && old_die->die_parent->die_tag == DW_TAG_module)
+           || local_scope_p (old_die->die_parent)
            || context_die == NULL)
           && (DECL_ARTIFICIAL (decl)
               || (get_AT_file (old_die, DW_AT_decl_file) == file_index
@@ -23241,6 +23266,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
              dw_die_ref die = NULL;
              rtx tloc = NULL_RTX, tlocc = NULL_RTX;
              rtx arg, next_arg;
+             tree arg_decl = NULL_TREE;
 
              for (arg = (ca_loc->call_arg_loc_note != NULL_RTX
                          ? XEXP (ca_loc->call_arg_loc_note, 0)
@@ -23305,6 +23331,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                      tdie = lookup_decl_die (tdecl);
                      if (tdie == NULL)
                        continue;
+                     arg_decl = tdecl;
                    }
                  else
                    continue;
@@ -23321,6 +23348,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                    die = gen_call_site_die (decl, subr_die, ca_loc);
                  cdie = new_die (dwarf_TAG (DW_TAG_call_site_parameter), die,
                                  NULL_TREE);
+                 add_desc_attribute (cdie, arg_decl);
                  if (reg != NULL)
                    add_AT_loc (cdie, DW_AT_location, reg);
                  else if (tdie != NULL)
@@ -23890,6 +23918,10 @@ gen_label_die (tree decl, dw_die_ref context_die)
 static inline void
 add_call_src_coords_attributes (tree stmt, dw_die_ref die)
 {
+  /* We can end up with BUILTINS_LOCATION here.  */
+  if (RESERVED_LOCATION_P (BLOCK_SOURCE_LOCATION (stmt)))
+    return;
+
   expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (stmt));
 
   if (dwarf_version >= 3 || !dwarf_strict)
@@ -23988,7 +24020,7 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
        }
       if (attr != NULL
          && ((*ranges_table)[attr->dw_attr_val.v.val_offset].num
-             == BLOCK_NUMBER (superblock))
+             == (int)BLOCK_NUMBER (superblock))
          && BLOCK_FRAGMENT_CHAIN (superblock))
        {
          unsigned long off = attr->dw_attr_val.v.val_offset;
@@ -23998,7 +24030,7 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
            {
              ++supercnt;
              gcc_checking_assert ((*ranges_table)[off + supercnt].num
-                                  == BLOCK_NUMBER (chain));
+                                  == (int)BLOCK_NUMBER (chain));
            }
          gcc_checking_assert ((*ranges_table)[off + supercnt + 1].num == 0);
          for (chain = BLOCK_FRAGMENT_CHAIN (stmt);
@@ -24042,46 +24074,26 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
 static void
 gen_lexical_block_die (tree stmt, dw_die_ref context_die)
 {
-  dw_die_ref old_die = BLOCK_DIE (stmt);
+  dw_die_ref old_die = lookup_block_die (stmt);
   dw_die_ref stmt_die = NULL;
   if (!old_die)
     {
       stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
-      BLOCK_DIE (stmt) = stmt_die;
+      equate_block_to_die (stmt, stmt_die);
     }
 
-  if (BLOCK_ABSTRACT (stmt))
-    {
-      if (old_die)
-       {
-         /* This must have been generated early and it won't even
-            need location information since it's a DW_AT_inline
-            function.  */
-         if (flag_checking)
-           for (dw_die_ref c = context_die; c; c = c->die_parent)
-             if (c->die_tag == DW_TAG_inlined_subroutine
-                 || c->die_tag == DW_TAG_subprogram)
-               {
-                 gcc_assert (get_AT (c, DW_AT_inline));
-                 break;
-               }
-         return;
-       }
-    }
-  else if (BLOCK_ABSTRACT_ORIGIN (stmt))
+  if (BLOCK_ABSTRACT_ORIGIN (stmt))
     {
-      /* If this is an inlined instance, create a new lexical die for
-        anything below to attach DW_AT_abstract_origin to.  */
+      /* If this is an inlined or conrecte instance, create a new lexical
+        die for anything below to attach DW_AT_abstract_origin to.  */
       if (old_die)
-       {
-         stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
-         BLOCK_DIE (stmt) = stmt_die;
-         old_die = NULL;
-       }
+       stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
 
       tree origin = block_ultimate_origin (stmt);
-      if (origin != NULL_TREE && origin != stmt)
+      if (origin != NULL_TREE && (origin != stmt || old_die))
        add_abstract_origin_attribute (stmt_die, origin);
+
+      old_die = NULL;
     }
 
   if (old_die)
@@ -24090,7 +24102,7 @@ gen_lexical_block_die (tree stmt, dw_die_ref context_die)
   /* A non abstract block whose blocks have already been reordered
      should have the instruction range for this block.  If so, set the
      high/low attributes.  */
-  if (!early_dwarf && !BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
+  if (!early_dwarf && TREE_ASM_WRITTEN (stmt))
     {
       gcc_assert (stmt_die);
       add_high_low_attributes (stmt, stmt_die);
@@ -24104,32 +24116,38 @@ gen_lexical_block_die (tree stmt, dw_die_ref context_die)
 static void
 gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die)
 {
-  tree decl;
-
-  /* The instance of function that is effectively being inlined shall not
-     be abstract.  */
-  gcc_assert (! BLOCK_ABSTRACT (stmt));
-
-  decl = block_ultimate_origin (stmt);
+  tree decl = block_ultimate_origin (stmt);
 
   /* Make sure any inlined functions are known to be inlineable.  */
   gcc_checking_assert (DECL_ABSTRACT_P (decl)
                       || cgraph_function_possibly_inlined_p (decl));
 
-  if (! BLOCK_ABSTRACT (stmt))
-    {
-      dw_die_ref subr_die
-       = new_die (DW_TAG_inlined_subroutine, context_die, stmt);
+  dw_die_ref subr_die = new_die (DW_TAG_inlined_subroutine, context_die, stmt);
 
-      if (call_arg_locations || debug_inline_points)
-       BLOCK_DIE (stmt) = subr_die;
-      add_abstract_origin_attribute (subr_die, decl);
-      if (TREE_ASM_WRITTEN (stmt))
-        add_high_low_attributes (stmt, subr_die);
-      add_call_src_coords_attributes (stmt, subr_die);
+  if (call_arg_locations || debug_inline_points)
+    equate_block_to_die (stmt, subr_die);
+  add_abstract_origin_attribute (subr_die, decl);
+  if (TREE_ASM_WRITTEN (stmt))
+    add_high_low_attributes (stmt, subr_die);
+  add_call_src_coords_attributes (stmt, subr_die);
 
-      decls_for_scope (stmt, subr_die);
+  /* The inliner creates an extra BLOCK for the parameter setup,
+     we want to merge that with the actual outermost BLOCK of the
+     inlined function to avoid duplicate locals in consumers.
+     Do that by doing the recursion to subblocks on the single subblock
+     of STMT.  */
+  bool unwrap_one = false;
+  if (BLOCK_SUBBLOCKS (stmt) && !BLOCK_CHAIN (BLOCK_SUBBLOCKS (stmt)))
+    {
+      tree origin = block_ultimate_origin (BLOCK_SUBBLOCKS (stmt));
+      if (origin
+         && TREE_CODE (origin) == BLOCK
+         && BLOCK_SUPERCONTEXT (origin) == decl)
+       unwrap_one = true;
     }
+  decls_for_scope (stmt, subr_die, !unwrap_one);
+  if (unwrap_one)
+    decls_for_scope (BLOCK_SUBBLOCKS (stmt), subr_die);
 }
 
 /* Generate a DIE for a field in a record, or structure.  CTX is required: see
@@ -24238,6 +24256,7 @@ gen_producer_string (void)
       case OPT_U:
       case OPT_SPECIAL_unknown:
       case OPT_SPECIAL_ignore:
+      case OPT_SPECIAL_deprecated:
       case OPT_SPECIAL_program_name:
       case OPT_SPECIAL_input_file:
       case OPT_grecord_gcc_switches:
@@ -24245,6 +24264,8 @@ gen_producer_string (void)
       case OPT_fdiagnostics_show_location_:
       case OPT_fdiagnostics_show_option:
       case OPT_fdiagnostics_show_caret:
+      case OPT_fdiagnostics_show_labels:
+      case OPT_fdiagnostics_show_line_numbers:
       case OPT_fdiagnostics_color_:
       case OPT_fverbose_asm:
       case OPT____:
@@ -24319,6 +24340,8 @@ highest_c_language (const char *lang1, const char *lang2)
   if (strcmp ("GNU C++98", lang1) == 0 || strcmp ("GNU C++98", lang2) == 0)
     return "GNU C++98";
 
+  if (strcmp ("GNU C2X", lang1) == 0 || strcmp ("GNU C2X", lang2) == 0)
+    return "GNU C2X";
   if (strcmp ("GNU C17", lang1) == 0 || strcmp ("GNU C17", lang2) == 0)
     return "GNU C17";
   if (strcmp ("GNU C11", lang1) == 0 || strcmp ("GNU C11", lang2) == 0)
@@ -24398,7 +24421,8 @@ gen_compile_unit_die (const char *filename)
 
          if (dwarf_version >= 5 /* || !dwarf_strict */)
            if (strcmp (language_string, "GNU C11") == 0
-               || strcmp (language_string, "GNU C17") == 0)
+               || strcmp (language_string, "GNU C17") == 0
+               || strcmp (language_string, "GNU C2X"))
              language = DW_LANG_C11;
        }
     }
@@ -24437,6 +24461,8 @@ gen_compile_unit_die (const char *filename)
        language = DW_LANG_ObjC;
       else if (strcmp (language_string, "GNU Objective-C++") == 0)
        language = DW_LANG_ObjC_plus_plus;
+      else if (strcmp (language_string, "GNU D") == 0)
+       language = DW_LANG_D;
       else if (dwarf_version >= 5 || !dwarf_strict)
        {
          if (strcmp (language_string, "GNU Go") == 0)
@@ -25619,14 +25645,13 @@ gen_block_die (tree stmt, dw_die_ref context_die)
     /* The outer scopes for inlinings *must* always be represented.  We
        generate DW_TAG_inlined_subroutine DIEs for them.  (See below.) */
     must_output_die = 1;
-  else if (BLOCK_DIE (stmt))
+  else if (lookup_block_die (stmt))
     /* If we already have a DIE then it was filled early.  Meanwhile
        we might have pruned all BLOCK_VARS as optimized out but we
        still want to generate high/low PC attributes so output it.  */
     must_output_die = 1;
   else if (TREE_USED (stmt)
-          || TREE_ASM_WRITTEN (stmt)
-          || BLOCK_ABSTRACT (stmt))
+          || TREE_ASM_WRITTEN (stmt))
     {
       /* Determine if this block directly contains any "significant"
         local declarations which we will need to output DIEs for.  */
@@ -25659,23 +25684,7 @@ gen_block_die (tree stmt, dw_die_ref context_die)
   if (must_output_die)
     {
       if (inlined_func)
-       {
-         /* If STMT block is abstract, that means we have been called
-            indirectly from dwarf2out_abstract_function.
-            That function rightfully marks the descendent blocks (of
-            the abstract function it is dealing with) as being abstract,
-            precisely to prevent us from emitting any
-            DW_TAG_inlined_subroutine DIE as a descendent
-            of an abstract function instance. So in that case, we should
-            not call gen_inlined_subroutine_die.
-
-            Later though, when cgraph asks dwarf2out to emit info
-            for the concrete instance of the function decl into which
-            the concrete instance of STMT got inlined, the later will lead
-            to the generation of a DW_TAG_inlined_subroutine DIE.  */
-         if (! BLOCK_ABSTRACT (stmt))
-           gen_inlined_subroutine_die (stmt, context_die);
-       }
+       gen_inlined_subroutine_die (stmt, context_die);
       else
        gen_lexical_block_die (stmt, context_die);
     }
@@ -25753,7 +25762,7 @@ process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die)
    all of its sub-blocks.  */
 
 static void
-decls_for_scope (tree stmt, dw_die_ref context_die)
+decls_for_scope (tree stmt, dw_die_ref context_die, bool recurse)
 {
   tree decl;
   unsigned int i;
@@ -25796,15 +25805,16 @@ decls_for_scope (tree stmt, dw_die_ref context_die)
 
   /* Output the DIEs to represent all sub-blocks (and the items declared
      therein) of this block.  */
-  for (subblocks = BLOCK_SUBBLOCKS (stmt);
-       subblocks != NULL;
-       subblocks = BLOCK_CHAIN (subblocks))
-    gen_block_die (subblocks, context_die);
+  if (recurse)
+    for (subblocks = BLOCK_SUBBLOCKS (stmt);
+        subblocks != NULL;
+        subblocks = BLOCK_CHAIN (subblocks))
+      gen_block_die (subblocks, context_die);
 }
 
 /* Is this a typedef we can avoid emitting?  */
 
-bool
+static bool
 is_redundant_typedef (const_tree decl)
 {
   if (TYPE_DECL_IS_STUB (decl))
@@ -26037,7 +26047,7 @@ declare_in_namespace (tree thing, dw_die_ref context_die)
 
   if (ns_context != context_die)
     {
-      if (is_fortran ())
+      if (is_fortran () || is_dlang ())
        return ns_context;
       if (DECL_P (thing))
        gen_decl_die (thing, NULL, NULL, ns_context);
@@ -26060,7 +26070,7 @@ gen_namespace_die (tree decl, dw_die_ref context_die)
     {
       /* Output a real namespace or module.  */
       context_die = setup_namespace_context (decl, comp_unit_die ());
-      namespace_die = new_die (is_fortran ()
+      namespace_die = new_die (is_fortran () || is_dlang ()
                               ? DW_TAG_module : DW_TAG_namespace,
                               context_die, decl);
       /* For Fortran modules defined in different CU don't add src coords.  */
@@ -26126,7 +26136,7 @@ gen_decl_die (tree decl, tree origin, struct vlr_context *ctx,
       break;
 
     case CONST_DECL:
-      if (!is_fortran () && !is_ada ())
+      if (!is_fortran () && !is_ada () && !is_dlang ())
        {
          /* The individual enumerators of an enum type get output when we output
             the Dwarf representation of the relevant enum type itself.  */
@@ -26702,8 +26712,11 @@ dwarf2out_decl (tree decl)
     case FUNCTION_DECL:
       /* If we're a nested function, initially use a parent of NULL; if we're
         a plain function, this will be fixed up in decls_for_scope.  If
-        we're a method, it will be ignored, since we already have a DIE.  */
-      if (decl_function_context (decl)
+        we're a method, it will be ignored, since we already have a DIE.
+        Avoid doing this late though since clones of class methods may
+        otherwise end up in limbo and create type DIEs late.  */
+      if (early_dwarf
+         && decl_function_context (decl)
          /* But if we're in terse mode, we don't care about scope.  */
          && debug_info_level > DINFO_LEVEL_TERSE)
        context_die = NULL;
@@ -26723,7 +26736,7 @@ dwarf2out_decl (tree decl)
     case CONST_DECL:
       if (debug_info_level <= DINFO_LEVEL_TERSE)
        return;
-      if (!is_fortran () && !is_ada ())
+      if (!is_fortran () && !is_ada () && !is_dlang ())
        return;
       if (TREE_STATIC (decl) && decl_function_context (decl))
        context_die = lookup_decl_die (DECL_CONTEXT (decl));
@@ -27447,7 +27460,7 @@ dwarf2out_inline_entry (tree block)
                                      true));
 
   gcc_assert (inlined_function_outer_scope_p (block));
-  gcc_assert (!BLOCK_DIE (block));
+  gcc_assert (!lookup_block_die (block));
 
   if (BLOCK_FRAGMENT_ORIGIN (block))
     block = BLOCK_FRAGMENT_ORIGIN (block);
@@ -27815,8 +27828,10 @@ dwarf2out_source_line (unsigned int line, unsigned int column,
 
       if (is_stmt != table->is_stmt)
        {
+#if HAVE_GAS_LOC_STMT
          fputs (" is_stmt ", asm_out_file);
          putc (is_stmt ? '1' : '0', asm_out_file);
+#endif
        }
       if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
        {
@@ -28249,6 +28264,12 @@ save_macinfo_strings (void)
                 && (debug_str_section->common.flags & SECTION_MERGE) != 0)
               set_indirect_string (find_AT_string (ref->info));
             break;
+         case DW_MACINFO_start_file:
+           /* -gsplit-dwarf -g3 will also output filename as indirect
+              string.  */
+           if (!dwarf_split_debug_info)
+             break;
+           /* Fall through. */
          case DW_MACRO_define_strp:
          case DW_MACRO_undef_strp:
             set_indirect_string (find_AT_string (ref->info));
@@ -29118,6 +29139,7 @@ prune_unused_types_walk_local_classes (dw_die_ref die)
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
     case DW_TAG_class_type:
+    case DW_TAG_interface_type:
       break;
 
     case DW_TAG_subprogram:
@@ -29151,6 +29173,7 @@ prune_unused_types_walk (dw_die_ref die)
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
     case DW_TAG_class_type:
+    case DW_TAG_interface_type:
       if (die->die_perennial_p)
        break;
 
@@ -29177,7 +29200,6 @@ prune_unused_types_walk (dw_die_ref die)
     case DW_TAG_volatile_type:
     case DW_TAG_typedef:
     case DW_TAG_array_type:
-    case DW_TAG_interface_type:
     case DW_TAG_friend:
     case DW_TAG_enumeration_type:
     case DW_TAG_subroutine_type:
@@ -31082,7 +31104,7 @@ reset_dies (dw_die_ref die)
    and generate the DWARF-2 debugging info.  */
 
 static void
-dwarf2out_finish (const char *)
+dwarf2out_finish (const char *filename)
 {
   comdat_type_node *ctnode;
   dw_die_ref main_comp_unit_die;
@@ -31163,6 +31185,12 @@ dwarf2out_finish (const char *)
   resolve_addr (comp_unit_die ());
   move_marked_base_types ();
 
+  if (dump_file)
+    {
+      fprintf (dump_file, "DWARF for %s\n", filename);
+      print_die (comp_unit_die (), dump_file);
+    }
+
   /* Initialize sections and labels used for actual assembler output.  */
   unsigned generation = init_sections_and_labels (false);
 
@@ -31857,7 +31885,30 @@ dwarf2out_early_finish (const char *filename)
      sure to adjust the phase after annotating the LTRANS CU DIE.  */
   if (in_lto_p)
     {
+      /* Force DW_TAG_imported_unit to be created now, otherwise
+        we might end up without it or ordered after DW_TAG_inlined_subroutine
+        referencing DIEs from it.  */
+      if (! flag_wpa && flag_incremental_link != INCREMENTAL_LINK_LTO)
+       {
+         unsigned i;
+         tree tu;
+         if (external_die_map)
+           FOR_EACH_VEC_SAFE_ELT (all_translation_units, i, tu)
+             if (sym_off_pair *desc = external_die_map->get (tu))
+               {
+                 dw_die_ref import = new_die (DW_TAG_imported_unit,
+                                              comp_unit_die (), NULL_TREE);
+                 add_AT_external_die_ref (import, DW_AT_import,
+                                          desc->sym, desc->off);
+               }
+       }
+
       early_dwarf_finished = true;
+      if (dump_file)
+       {
+         fprintf (dump_file, "LTO EARLY DWARF for %s\n", filename);
+         print_die (comp_unit_die (), dump_file);
+       }
       return;
     }
 
@@ -31935,13 +31986,18 @@ dwarf2out_early_finish (const char *filename)
 
   /* The early debug phase is now finished.  */
   early_dwarf_finished = true;
+  if (dump_file)
+    {
+      fprintf (dump_file, "EARLY DWARF for %s\n", filename);
+      print_die (comp_unit_die (), dump_file);
+    }
 
   /* Do not generate DWARF assembler now when not producing LTO bytecode.  */
   if ((!flag_generate_lto && !flag_generate_offload)
-      /* FIXME: Disable debug info generation for PE-COFF targets since the
+      /* FIXME: Disable debug info generation for (PE-)COFF targets since the
         copy_lto_debug_sections operation of the simple object support in
         libiberty is not implemented for them yet.  */
-      || TARGET_PECOFF)
+      || TARGET_PECOFF || TARGET_COFF)
     return;
 
   /* Now as we are going to output for LTO initialize sections and labels