dwarf2out.c (gen_remaining_tmpl_value_param_die_attributes): Only add locations in...
[gcc.git] / gcc / dwarf2out.c
index db82710ecfb368534db8969a1293fe060c602e1f..45eb684e2a279735525ed22d38ec722fce1d1551 100644 (file)
@@ -1,5 +1,5 @@
 /* Output Dwarf2 format symbol table information from GCC.
-   Copyright (C) 1992-2015 Free Software Foundation, Inc.
+   Copyright (C) 1992-2016 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).
@@ -58,62 +58,33 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "target.h"
+#include "function.h"
 #include "rtl.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "vec.h"
-#include "double-int.h"
-#include "input.h"
-#include "alias.h"
-#include "symtab.h"
-#include "wide-int.h"
-#include "inchash.h"
-#include "real.h"
 #include "tree.h"
-#include "fold-const.h"
+#include "tm_p.h"
 #include "stringpool.h"
+#include "insn-config.h"
+#include "ira.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "fold-const.h"
 #include "stor-layout.h"
 #include "varasm.h"
-#include "hashtab.h"
-#include "hard-reg-set.h"
-#include "function.h"
-#include "emit-rtl.h"
-#include "hash-table.h"
 #include "version.h"
 #include "flags.h"
-#include "regs.h"
 #include "rtlhash.h"
-#include "insn-config.h"
 #include "reload.h"
 #include "output.h"
-#include "statistics.h"
-#include "fixed-value.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "stmt.h"
 #include "expr.h"
-#include "except.h"
-#include "dwarf2.h"
 #include "dwarf2out.h"
 #include "dwarf2asm.h"
 #include "toplev.h"
 #include "md5.h"
-#include "tm_p.h"
-#include "diagnostic.h"
 #include "tree-pretty-print.h"
 #include "debug.h"
-#include "target.h"
 #include "common/common-target.h"
 #include "langhooks.h"
-#include "hash-map.h"
-#include "is-a.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
-#include "cgraph.h"
-#include "ira.h"
 #include "lra.h"
 #include "dumpfile.h"
 #include "opts.h"
@@ -126,6 +97,14 @@ static rtx_insn *last_var_location_insn;
 static rtx_insn *cached_next_real_insn;
 static void dwarf2out_decl (tree);
 
+#ifndef XCOFF_DEBUGGING_INFO
+#define XCOFF_DEBUGGING_INFO 0
+#endif
+
+#ifndef HAVE_XCOFF_DWARF_EXTRAS
+#define HAVE_XCOFF_DWARF_EXTRAS 0
+#endif
+
 #ifdef VMS_DEBUGGING_INFO
 int vms_file_stats_name (const char *, long long *, long *, char *, int *);
 
@@ -234,7 +213,7 @@ struct GTY((for_user)) indirect_string_node {
   unsigned int index;
 };
 
-struct indirect_string_hasher : ggc_hasher<indirect_string_node *>
+struct indirect_string_hasher : ggc_ptr_hash<indirect_string_node>
 {
   typedef const char *compare_type;
 
@@ -389,12 +368,14 @@ dump_struct_debug (tree type, enum debug_info_usage usage,
 #endif
 
 /* Get the number of HOST_WIDE_INTs needed to represent the precision
-   of the number.  */
+   of the number.  Some constants have a large uniform precision, so
+   we get the precision needed for the actual value of the number.  */
 
 static unsigned int
 get_full_len (const wide_int &op)
 {
-  return ((op.get_precision () + HOST_BITS_PER_WIDE_INT - 1)
+  int prec = wi::min_precision (op, UNSIGNED);
+  return ((prec + HOST_BITS_PER_WIDE_INT - 1)
          / HOST_BITS_PER_WIDE_INT);
 }
 
@@ -452,11 +433,8 @@ stripattributes (const char *s)
    for collect2 the first time around.  */
 
 static void
-switch_to_eh_frame_section (bool back)
+switch_to_eh_frame_section (bool back ATTRIBUTE_UNUSED)
 {
-  tree label;
-
-#ifdef EH_FRAME_SECTION_NAME
   if (eh_frame_section == 0)
     {
       int flags;
@@ -484,27 +462,29 @@ switch_to_eh_frame_section (bool back)
        }
       else
        flags = SECTION_WRITE;
+
+#ifdef EH_FRAME_SECTION_NAME
       eh_frame_section = get_section (EH_FRAME_SECTION_NAME, flags, NULL);
-    }
+#else
+      eh_frame_section = ((flags == SECTION_WRITE)
+                         ? data_section : readonly_data_section);
 #endif /* EH_FRAME_SECTION_NAME */
+    }
 
-  if (eh_frame_section)
-    switch_to_section (eh_frame_section);
-  else
-    {
-      /* We have no special eh_frame section.  Put the information in
-        the data section and emit special labels to guide collect2.  */
-      switch_to_section (data_section);
+  switch_to_section (eh_frame_section);
 
-      if (!back)
-       {
-         label = get_file_function_name ("F");
-         ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
-         targetm.asm_out.globalize_label (asm_out_file,
-                                          IDENTIFIER_POINTER (label));
-         ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
-       }
+#ifdef EH_FRAME_THROUGH_COLLECT2
+  /* We have no special eh_frame section.  Emit special labels to guide
+     collect2.  */
+  if (!back)
+    {
+      tree label = get_file_function_name ("F");
+      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
+      targetm.asm_out.globalize_label (asm_out_file,
+                                       IDENTIFIER_POINTER (label));
+      ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
     }
+#endif
 }
 
 /* Switch [BACK] to the eh or debug frame table section, depending on
@@ -613,11 +593,14 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
                                  for_eh + j);
   ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + j);
   ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + j);
-  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
-    dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
-                        " indicating 64-bit DWARF extension");
-  dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
-                       "FDE Length");
+  if (!XCOFF_DEBUGGING_INFO || for_eh)
+    {
+      if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
+       dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
+                            " indicating 64-bit DWARF extension");
+      dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
+                           "FDE Length");
+    }
   ASM_OUTPUT_LABEL (asm_out_file, l1);
 
   if (for_eh)
@@ -813,11 +796,14 @@ output_call_frame_info (int for_eh)
   /* Output the CIE.  */
   ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
   ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
-  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
-    dw2_asm_output_data (4, 0xffffffff,
-      "Initial length escape value indicating 64-bit DWARF extension");
-  dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
-                       "Length of Common Information Entry");
+  if (!XCOFF_DEBUGGING_INFO || for_eh)
+    {
+      if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
+       dw2_asm_output_data (4, 0xffffffff,
+         "Initial length escape value indicating 64-bit DWARF extension");
+      dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
+                           "Length of Common Information Entry");
+    }
   ASM_OUTPUT_LABEL (asm_out_file, l1);
 
   /* Now that the CIE pointer is PC-relative for EH,
@@ -1268,16 +1254,6 @@ struct GTY((for_user)) dwarf_file_data {
   int emitted_number;
 };
 
-typedef struct GTY(()) deferred_locations_struct
-{
-  tree variable;
-  dw_die_ref die;
-} deferred_locations;
-
-
-static GTY(()) vec<deferred_locations, va_gc> *deferred_locations_list;
-
-
 /* Describe an entry into the .debug_addr section.  */
 
 enum ate_kind {
@@ -1286,7 +1262,7 @@ enum ate_kind {
   ate_kind_label
 };
 
-typedef struct GTY((for_user)) addr_table_entry_struct {
+struct GTY((for_user)) addr_table_entry {
   enum ate_kind kind;
   unsigned int refcount;
   unsigned int index;
@@ -1296,8 +1272,7 @@ typedef struct GTY((for_user)) addr_table_entry_struct {
       char * GTY ((tag ("1"))) label;
     }
   GTY ((desc ("%1.kind"))) addr;
-}
-addr_table_entry;
+};
 
 /* Location lists are ranges + location descriptions for that range,
    so you can track variables that are in different places over
@@ -1324,6 +1299,7 @@ typedef struct GTY(()) dw_loc_list_struct {
 } dw_loc_list_node;
 
 static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
+static dw_loc_descr_ref uint_loc_descriptor (unsigned HOST_WIDE_INT);
 
 /* Convert a DWARF stack opcode into its string name.  */
 
@@ -1451,6 +1427,13 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b)
     case dw_val_class_vms_delta:
       return (!strcmp (a->v.val_vms_delta.lbl1, b->v.val_vms_delta.lbl1)
               && !strcmp (a->v.val_vms_delta.lbl1, b->v.val_vms_delta.lbl1));
+
+    case dw_val_class_discr_value:
+      return (a->v.val_discr_value.pos == b->v.val_discr_value.pos
+             && a->v.val_discr_value.v.uval == b->v.val_discr_value.v.uval);
+    case dw_val_class_discr_list:
+      /* It makes no sense comparing two discriminant value lists.  */
+      return false;
     }
   gcc_unreachable ();
 }
@@ -1765,6 +1748,39 @@ size_of_locs (dw_loc_descr_ref loc)
   return size;
 }
 
+/* Return the size of the value in a DW_AT_discr_value attribute.  */
+
+static int
+size_of_discr_value (dw_discr_value *discr_value)
+{
+  if (discr_value->pos)
+    return size_of_uleb128 (discr_value->v.uval);
+  else
+    return size_of_sleb128 (discr_value->v.sval);
+}
+
+/* Return the size of the value in a DW_discr_list attribute.  */
+
+static int
+size_of_discr_list (dw_discr_list_ref discr_list)
+{
+  int size = 0;
+
+  for (dw_discr_list_ref list = discr_list;
+       list != NULL;
+       list = list->dw_discr_next)
+    {
+      /* One byte for the discriminant value descriptor, and then one or two
+        LEB128 numbers, depending on whether it's a single case label or a
+        range label.  */
+      size += 1;
+      size += size_of_discr_value (&list->dw_discr_lower_bound);
+      if (list->dw_discr_range != 0)
+       size += size_of_discr_value (&list->dw_discr_upper_bound);
+    }
+  return size;
+}
+
 static HOST_WIDE_INT extract_int (const unsigned char *, unsigned);
 static void get_ref_die_offset_label (char *, dw_die_ref);
 static unsigned long int get_ref_die_offset (dw_die_ref);
@@ -2027,6 +2043,22 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
                                    "(index into .debug_addr)");
       break;
 
+    case DW_OP_call2:
+    case DW_OP_call4:
+      {
+       unsigned long die_offset
+         = get_ref_die_offset (val1->v.val_die_ref.die);
+       /* Make sure the offset has been computed and that we can encode it as
+          an operand.  */
+       gcc_assert (die_offset > 0
+                   && die_offset <= (loc->dw_loc_opc == DW_OP_call2)
+                                    ? 0xffff
+                                    : 0xffffffff);
+       dw2_asm_output_data ((loc->dw_loc_opc == DW_OP_call2) ? 2 : 4,
+                            die_offset, NULL);
+      }
+      break;
+
     case DW_OP_GNU_implicit_pointer:
       {
        char label[MAX_ARTIFICIAL_LABEL_BYTES
@@ -2448,6 +2480,7 @@ build_cfa_aligned_loc (dw_cfa_location *cfa,
 
 static void dwarf2out_init (const char *);
 static void dwarf2out_finish (const char *);
+static void dwarf2out_early_finish (void);
 static void dwarf2out_assembly_start (void);
 static void dwarf2out_define (unsigned int, const char *);
 static void dwarf2out_undef (unsigned int, const char *);
@@ -2457,15 +2490,18 @@ static void dwarf2out_function_decl (tree);
 static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
 static bool dwarf2out_ignore_block (const_tree);
-static void dwarf2out_global_decl (tree);
+static void dwarf2out_early_global_decl (tree);
+static void dwarf2out_late_global_decl (tree);
 static void dwarf2out_type_decl (tree, int);
 static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
 static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
                                                 dw_die_ref);
 static void dwarf2out_abstract_function (tree);
 static void dwarf2out_var_location (rtx_insn *);
+static void dwarf2out_size_function (tree);
 static void dwarf2out_begin_function (tree);
 static void dwarf2out_end_function (unsigned int);
+static void dwarf2out_register_main_translation_unit (tree unit);
 static void dwarf2out_set_name (tree, tree);
 
 /* The debug hooks structure.  */
@@ -2474,6 +2510,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
 {
   dwarf2out_init,
   dwarf2out_finish,
+  dwarf2out_early_finish,
   dwarf2out_assembly_start,
   dwarf2out_define,
   dwarf2out_undef,
@@ -2494,8 +2531,10 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   dwarf2out_end_epilogue,
   dwarf2out_begin_function,
   dwarf2out_end_function,      /* end_function */
+  dwarf2out_register_main_translation_unit,
   dwarf2out_function_decl,     /* function_decl */
-  dwarf2out_global_decl,
+  dwarf2out_early_global_decl,
+  dwarf2out_late_global_decl,
   dwarf2out_type_decl,         /* type_decl */
   dwarf2out_imported_module_or_decl,
   debug_nothing_tree,          /* deferred_inline_function */
@@ -2506,11 +2545,50 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   debug_nothing_rtx_code_label,        /* label */
   debug_nothing_int,           /* handle_pch */
   dwarf2out_var_location,
+  dwarf2out_size_function,     /* size_function */
   dwarf2out_switch_text_section,
   dwarf2out_set_name,
   1,                            /* start_end_main_source_file */
   TYPE_SYMTAB_IS_DIE            /* tree_type_symtab_field */
 };
+
+const struct gcc_debug_hooks dwarf2_lineno_debug_hooks =
+{
+  dwarf2out_init,
+  debug_nothing_charstar,
+  debug_nothing_void,
+  debug_nothing_void,
+  debug_nothing_int_charstar,
+  debug_nothing_int_charstar,
+  debug_nothing_int_charstar,
+  debug_nothing_int,
+  debug_nothing_int_int,                /* begin_block */
+  debug_nothing_int_int,                /* end_block */
+  debug_true_const_tree,                /* ignore_block */
+  dwarf2out_source_line,        /* source_line */
+  debug_nothing_int_charstar,           /* begin_prologue */
+  debug_nothing_int_charstar,           /* end_prologue */
+  debug_nothing_int_charstar,           /* begin_epilogue */
+  debug_nothing_int_charstar,           /* end_epilogue */
+  debug_nothing_tree,                   /* begin_function */
+  debug_nothing_int,                    /* end_function */
+  debug_nothing_tree,                   /* register_main_translation_unit */
+  debug_nothing_tree,                   /* function_decl */
+  debug_nothing_tree,                   /* early_global_decl */
+  debug_nothing_tree,                   /* late_global_decl */
+  debug_nothing_tree_int,               /* type_decl */
+  debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
+  debug_nothing_tree,                   /* deferred_inline_function */
+  debug_nothing_tree,                   /* outlining_inline_function */
+  debug_nothing_rtx_code_label,                 /* label */
+  debug_nothing_int,                    /* handle_pch */
+  debug_nothing_rtx_insn,               /* var_location */
+  debug_nothing_tree,                   /* size_function */
+  debug_nothing_void,                    /* switch_text_section */
+  debug_nothing_tree_tree,              /* set_name */
+  0,                                     /* start_end_main_source_file */
+  TYPE_SYMTAB_IS_ADDRESS                 /* tree_type_symtab_field */
+};
 \f
 /* NOTE: In the comments in this file, many references are made to
    "Debugging Information Entries".  This term is abbreviated as `DIE'
@@ -2536,14 +2614,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
 
 typedef long int dw_offset;
 
-/* Define typedefs here to avoid circular dependencies.  */
-
-typedef struct dw_attr_struct *dw_attr_ref;
-typedef struct dw_line_info_struct *dw_line_info_ref;
-typedef struct pubname_struct *pubname_ref;
-typedef struct dw_ranges_struct *dw_ranges_ref;
-typedef struct dw_ranges_by_label_struct *dw_ranges_by_label_ref;
-typedef struct comdat_type_struct *comdat_type_node_ref;
+struct comdat_type_node;
 
 /* The entries in the line_info table more-or-less mirror the opcodes
    that are used in the real dwarf line table.  Arrays of these entries
@@ -2582,7 +2653,7 @@ typedef struct GTY(()) dw_line_info_struct {
 } dw_line_info_entry;
 
 
-typedef struct GTY(()) dw_line_info_table_struct {
+struct GTY(()) dw_line_info_table {
   /* The label that marks the end of this section.  */
   const char *end_label;
 
@@ -2596,9 +2667,7 @@ typedef struct GTY(()) dw_line_info_table_struct {
   bool in_use;
 
   vec<dw_line_info_entry, va_gc> *entries;
-} dw_line_info_table;
-
-typedef dw_line_info_table *dw_line_info_table_p;
+};
 
 
 /* Each DIE attribute has a field specifying the attribute kind,
@@ -2620,7 +2689,7 @@ typedef struct GTY((chain_circular ("%h.die_sib"), for_user)) die_struct {
   union die_symbol_or_type_node
     {
       const char * GTY ((tag ("0"))) die_symbol;
-      comdat_type_node_ref GTY ((tag ("1"))) die_type_node;
+      comdat_type_node *GTY ((tag ("1"))) die_type_node;
     }
   GTY ((desc ("%0.comdat_type_p"))) die_id;
   vec<dw_attr_node, va_gc> *die_attr;
@@ -2640,6 +2709,14 @@ typedef struct GTY((chain_circular ("%h.die_sib"), for_user)) die_struct {
 }
 die_node;
 
+/* Set to TRUE while dwarf2out_early_global_decl is running.  */
+static bool early_dwarf;
+struct set_early_dwarf {
+  bool saved;
+  set_early_dwarf () : saved(early_dwarf) { early_dwarf = true; }
+  ~set_early_dwarf () { early_dwarf = saved; }
+};
+
 /* Evaluate 'expr' while 'c' is set to each child of DIE in order.  */
 #define FOR_EACH_CHILD(die, c, expr) do {      \
   c = die->die_child;                          \
@@ -2658,7 +2735,7 @@ typedef struct GTY(()) pubname_struct {
 pubname_entry;
 
 
-struct GTY(()) dw_ranges_struct {
+struct GTY(()) dw_ranges {
   /* If this is positive, it's a block number, otherwise it's a
      bitwise-negated index into dw_ranges_by_label.  */
   int num;
@@ -2674,25 +2751,28 @@ typedef struct GTY(()) macinfo_struct {
 macinfo_entry;
 
 
-struct GTY(()) dw_ranges_by_label_struct {
+struct GTY(()) dw_ranges_by_label {
   const char *begin;
   const char *end;
 };
 
 /* The comdat type node structure.  */
-typedef struct GTY(()) comdat_type_struct
+struct GTY(()) comdat_type_node
 {
   dw_die_ref root_die;
   dw_die_ref type_die;
   dw_die_ref skeleton_die;
   char signature[DWARF_TYPE_SIGNATURE_SIZE];
-  struct comdat_type_struct *next;
-}
-comdat_type_node;
+  comdat_type_node *next;
+};
 
-/* The limbo die list structure.  */
+/* A list of DIEs for which we can't determine ancestry (parent_die
+   field) just yet.  Later in dwarf2out_finish we will fill in the
+   missing bits.  */
 typedef struct GTY(()) limbo_die_struct {
   dw_die_ref die;
+  /* The tree for which this DIE was created.  We use this to
+     determine ancestry later.  */
   tree created_for;
   struct limbo_die_struct *next;
 }
@@ -2802,7 +2882,7 @@ static GTY(()) limbo_die_node *limbo_die_list;
    DW_AT_{,MIPS_}linkage_name once their DECL_ASSEMBLER_NAMEs are set.  */
 static GTY(()) limbo_die_node *deferred_asm_name;
 
-struct dwarf_file_hasher : ggc_hasher<dwarf_file_data *>
+struct dwarf_file_hasher : ggc_ptr_hash<dwarf_file_data>
 {
   typedef const char *compare_type;
 
@@ -2813,7 +2893,7 @@ struct dwarf_file_hasher : ggc_hasher<dwarf_file_data *>
 /* Filenames referenced by this compilation unit.  */
 static GTY(()) hash_table<dwarf_file_hasher> *file_table;
 
-struct decl_die_hasher : ggc_hasher<die_node *>
+struct decl_die_hasher : ggc_ptr_hash<die_node>
 {
   typedef tree compare_type;
 
@@ -2824,7 +2904,7 @@ struct decl_die_hasher : ggc_hasher<die_node *>
    The key is a DECL_UID() which is a unique number identifying each decl.  */
 static GTY (()) hash_table<decl_die_hasher> *decl_die_table;
 
-struct block_die_hasher : ggc_hasher<die_struct *>
+struct block_die_hasher : ggc_ptr_hash<die_struct>
 {
   static hashval_t hash (die_struct *);
   static bool equal (die_struct *, die_struct *);
@@ -2888,7 +2968,7 @@ struct GTY ((chain_next ("%h.next"))) call_arg_loc_node {
 };
 
 
-struct decl_loc_hasher : ggc_hasher<var_loc_list *>
+struct decl_loc_hasher : ggc_ptr_hash<var_loc_list>
 {
   typedef const_tree compare_type;
 
@@ -2908,10 +2988,6 @@ static int call_site_count = -1;
 /* Number of tail call sites in the current function.  */
 static int tail_call_site_count = -1;
 
-/* Vector mapping block numbers to DW_TAG_{lexical_block,inlined_subroutine}
-   DIEs.  */
-static vec<dw_die_ref> block_map;
-
 /* A cached location list.  */
 struct GTY ((for_user)) cached_dw_loc_list_def {
   /* The DECL_UID of the decl that this entry describes.  */
@@ -2922,7 +2998,7 @@ struct GTY ((for_user)) cached_dw_loc_list_def {
 };
 typedef struct cached_dw_loc_list_def cached_dw_loc_list;
 
-struct dw_loc_list_hasher : ggc_hasher<cached_dw_loc_list *>
+struct dw_loc_list_hasher : ggc_ptr_hash<cached_dw_loc_list>
 {
 
   typedef const_tree compare_type;
@@ -2943,9 +3019,15 @@ static GTY((length ("abbrev_die_table_allocated")))
 /* Number of elements currently allocated for abbrev_die_table.  */
 static GTY(()) unsigned abbrev_die_table_allocated;
 
-/* Number of elements in type_die_table currently in use.  */
+/* Number of elements in abbrev_die_table currently in use.  */
 static GTY(()) unsigned abbrev_die_table_in_use;
 
+/* A hash map to remember the stack usage for DWARF procedures.  The value
+   stored is the stack size difference between before the DWARF procedure
+   invokation and after it returned.  In other words, for a DWARF procedure
+   that consumes N stack slots and that pushes M ones, this stores M - N.  */
+static hash_map<dw_die_ref, int> *dwarf_proc_stack_usage_map;
+
 /* Size (in elements) of increments by which we may expand the
    abbrev_die_table.  */
 #define ABBREV_DIE_TABLE_INCREMENT 256
@@ -2956,14 +3038,14 @@ static unsigned int line_info_label_num;
 /* The current table to which we should emit line number information
    for the current function.  This will be set up at the beginning of
    assembly for the function.  */
-static dw_line_info_table *cur_line_info_table;
+static GTY(()) dw_line_info_table *cur_line_info_table;
 
 /* The two default tables of line number info.  */
 static GTY(()) dw_line_info_table *text_section_line_info;
 static GTY(()) dw_line_info_table *cold_text_section_line_info;
 
 /* The set of all non-default tables of line number info.  */
-static GTY(()) vec<dw_line_info_table_p, va_gc> *separate_line_info;
+static GTY(()) vec<dw_line_info_table *, va_gc> *separate_line_info;
 
 /* A flag to tell pubnames/types export if there is an info section to
    refer to.  */
@@ -2984,11 +3066,12 @@ static GTY (()) vec<macinfo_entry, va_gc> *macinfo_table;
 /* True if .debug_macinfo or .debug_macros section is going to be
    emitted.  */
 #define have_macinfo \
-  (debug_info_level >= DINFO_LEVEL_VERBOSE \
+  ((!XCOFF_DEBUGGING_INFO || HAVE_XCOFF_DWARF_EXTRAS) \
+   && debug_info_level >= DINFO_LEVEL_VERBOSE \
    && !macinfo_table->is_empty ())
 
 /* Array of dies for which we should generate .debug_ranges info.  */
-static GTY ((length ("ranges_table_allocated"))) dw_ranges_ref ranges_table;
+static GTY ((length ("ranges_table_allocated"))) dw_ranges *ranges_table;
 
 /* Number of elements currently allocated for ranges_table.  */
 static GTY(()) unsigned ranges_table_allocated;
@@ -2998,7 +3081,7 @@ static GTY(()) unsigned ranges_table_in_use;
 
 /* Array of pairs of labels referenced in ranges_table.  */
 static GTY ((length ("ranges_by_label_allocated")))
-     dw_ranges_by_label_ref ranges_by_label;
+     dw_ranges_by_label *ranges_by_label;
 
 /* Number of elements currently allocated for ranges_by_label.  */
 static GTY(()) unsigned ranges_by_label_allocated;
@@ -3025,9 +3108,6 @@ static GTY(()) struct dwarf_file_data * last_emitted_file;
 /* Number of internal labels generated by gen_internal_sym().  */
 static GTY(()) int label_num;
 
-/* Cached result of previous call to lookup_filename.  */
-static GTY(()) struct dwarf_file_data * file_table_last_lookup;
-
 static GTY(()) vec<die_arg_entry, va_gc> *tmpl_value_parm_die_table;
 
 /* Instances of generic types for which we need to generate debug
@@ -3043,6 +3123,10 @@ static bool frame_pointer_fb_offset_valid;
 
 static vec<dw_die_ref> base_types;
 
+/* Pointer to vector of DW_TAG_string_type DIEs that need finalization
+   once all arguments are parsed.  */
+static vec<dw_die_ref> *string_types;
+
 /* Flags to represent a set of attribute classes for attributes that represent
    a scalar value (bounds, pointers, ...).  */
 enum dw_scalar_form
@@ -3062,38 +3146,38 @@ static const char *dwarf_attr_name (unsigned);
 static const char *dwarf_form_name (unsigned);
 static tree decl_ultimate_origin (const_tree);
 static tree decl_class_context (tree);
-static void add_dwarf_attr (dw_die_ref, dw_attr_ref);
-static inline enum dw_val_class AT_class (dw_attr_ref);
-static inline unsigned int AT_index (dw_attr_ref);
+static void add_dwarf_attr (dw_die_ref, dw_attr_node *);
+static inline enum dw_val_class AT_class (dw_attr_node *);
+static inline unsigned int AT_index (dw_attr_node *);
 static void add_AT_flag (dw_die_ref, enum dwarf_attribute, unsigned);
-static inline unsigned AT_flag (dw_attr_ref);
+static inline unsigned AT_flag (dw_attr_node *);
 static void add_AT_int (dw_die_ref, enum dwarf_attribute, HOST_WIDE_INT);
-static inline HOST_WIDE_INT AT_int (dw_attr_ref);
+static inline HOST_WIDE_INT AT_int (dw_attr_node *);
 static void add_AT_unsigned (dw_die_ref, enum dwarf_attribute, unsigned HOST_WIDE_INT);
-static inline unsigned HOST_WIDE_INT AT_unsigned (dw_attr_ref);
+static inline unsigned HOST_WIDE_INT AT_unsigned (dw_attr_node *);
 static void add_AT_double (dw_die_ref, enum dwarf_attribute,
                           HOST_WIDE_INT, unsigned HOST_WIDE_INT);
 static inline void add_AT_vec (dw_die_ref, enum dwarf_attribute, unsigned int,
                               unsigned int, unsigned char *);
 static void add_AT_data8 (dw_die_ref, enum dwarf_attribute, unsigned char *);
 static void add_AT_string (dw_die_ref, enum dwarf_attribute, const char *);
-static inline const char *AT_string (dw_attr_ref);
-static enum dwarf_form AT_string_form (dw_attr_ref);
+static inline const char *AT_string (dw_attr_node *);
+static enum dwarf_form AT_string_form (dw_attr_node *);
 static void add_AT_die_ref (dw_die_ref, enum dwarf_attribute, dw_die_ref);
 static void add_AT_specification (dw_die_ref, dw_die_ref);
-static inline dw_die_ref AT_ref (dw_attr_ref);
-static inline int AT_ref_external (dw_attr_ref);
-static inline void set_AT_ref_external (dw_attr_ref, int);
+static inline dw_die_ref AT_ref (dw_attr_node *);
+static inline int AT_ref_external (dw_attr_node *);
+static inline void set_AT_ref_external (dw_attr_node *, int);
 static void add_AT_fde_ref (dw_die_ref, enum dwarf_attribute, unsigned);
 static void add_AT_loc (dw_die_ref, enum dwarf_attribute, dw_loc_descr_ref);
-static inline dw_loc_descr_ref AT_loc (dw_attr_ref);
+static inline dw_loc_descr_ref AT_loc (dw_attr_node *);
 static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute,
                             dw_loc_list_ref);
-static inline dw_loc_list_ref AT_loc_list (dw_attr_ref);
+static inline dw_loc_list_ref AT_loc_list (dw_attr_node *);
 static addr_table_entry *add_addr_table_entry (void *, enum ate_kind);
 static void remove_addr_table_entry (addr_table_entry *);
 static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx, bool);
-static inline rtx AT_addr (dw_attr_ref);
+static inline rtx AT_addr (dw_attr_node *);
 static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *);
 static void add_AT_lineptr (dw_die_ref, enum dwarf_attribute, const char *);
 static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *);
@@ -3101,8 +3185,8 @@ static void add_AT_offset (dw_die_ref, enum dwarf_attribute,
                           unsigned HOST_WIDE_INT);
 static void add_AT_range_list (dw_die_ref, enum dwarf_attribute,
                                unsigned long, bool);
-static inline const char *AT_lbl (dw_attr_ref);
-static dw_attr_ref get_AT (dw_die_ref, enum dwarf_attribute);
+static inline const char *AT_lbl (dw_attr_node *);
+static dw_attr_node *get_AT (dw_die_ref, enum dwarf_attribute);
 static const char *get_AT_low_pc (dw_die_ref);
 static const char *get_AT_hi_pc (dw_die_ref);
 static const char *get_AT_string (dw_die_ref, enum dwarf_attribute);
@@ -3112,7 +3196,7 @@ static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
 static bool is_cxx (void);
 static bool is_fortran (void);
 static bool is_ada (void);
-static void remove_AT (dw_die_ref, enum dwarf_attribute);
+static bool remove_AT (dw_die_ref, enum dwarf_attribute);
 static void remove_child_TAG (dw_die_ref, enum dwarf_tag);
 static void add_child_die (dw_die_ref, dw_die_ref);
 static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
@@ -3129,12 +3213,12 @@ static void print_die (dw_die_ref, FILE *);
 static dw_die_ref push_new_compile_unit (dw_die_ref, dw_die_ref);
 static dw_die_ref pop_compile_unit (dw_die_ref);
 static void loc_checksum (dw_loc_descr_ref, struct md5_ctx *);
-static void attr_checksum (dw_attr_ref, struct md5_ctx *, int *);
+static void attr_checksum (dw_attr_node *, struct md5_ctx *, int *);
 static void die_checksum (dw_die_ref, struct md5_ctx *, int *);
 static void checksum_sleb128 (HOST_WIDE_INT, struct md5_ctx *);
 static void checksum_uleb128 (unsigned HOST_WIDE_INT, struct md5_ctx *);
 static void loc_checksum_ordered (dw_loc_descr_ref, struct md5_ctx *);
-static void attr_checksum_ordered (enum dwarf_tag, dw_attr_ref,
+static void attr_checksum_ordered (enum dwarf_tag, dw_attr_node *,
                                   struct md5_ctx *, int *);
 struct checksum_attributes;
 static void collect_checksum_attributes (struct checksum_attributes *, dw_die_ref);
@@ -3143,7 +3227,7 @@ static void checksum_die_context (dw_die_ref, struct md5_ctx *);
 static void generate_type_signature (dw_die_ref, comdat_type_node *);
 static int same_loc_p (dw_loc_descr_ref, dw_loc_descr_ref, int *);
 static int same_dw_val_p (const dw_val_node *, const dw_val_node *, int *);
-static int same_attr_p (dw_attr_ref, dw_attr_ref, int *);
+static int same_attr_p (dw_attr_node *, dw_attr_node *, int *);
 static int same_die_p (dw_die_ref, dw_die_ref, int *);
 static int same_die_p_wrap (dw_die_ref, dw_die_ref);
 static void compute_section_prefix (dw_die_ref);
@@ -3179,8 +3263,8 @@ static void unmark_dies (dw_die_ref);
 static void unmark_all_dies (dw_die_ref);
 static unsigned long size_of_pubnames (vec<pubname_entry, va_gc> *);
 static unsigned long size_of_aranges (void);
-static enum dwarf_form value_format (dw_attr_ref);
-static void output_value_format (dw_attr_ref);
+static enum dwarf_form value_format (dw_attr_node *);
+static void output_value_format (dw_attr_node *);
 static void output_abbrev_section (void);
 static void output_die_abbrevs (unsigned long, dw_die_ref);
 static void output_die_symbol (dw_die_ref);
@@ -3194,7 +3278,7 @@ static void add_enumerator_pubname (const char *, dw_die_ref);
 static void add_pubname_string (const char *, dw_die_ref);
 static void add_pubtype (tree, dw_die_ref);
 static void output_pubnames (vec<pubname_entry, va_gc> *);
-static void output_aranges (unsigned long);
+static void output_aranges (void);
 static unsigned int add_ranges_num (int);
 static unsigned int add_ranges (const_tree);
 static void add_ranges_by_labels (dw_die_ref, const char *, const char *,
@@ -3203,11 +3287,11 @@ static void output_ranges (void);
 static dw_line_info_table *new_line_info_table (void);
 static void output_line_info (bool);
 static void output_file_names (void);
-static dw_die_ref base_type_die (tree);
+static dw_die_ref base_type_die (tree, bool);
 static int is_base_type (tree);
-static dw_die_ref subrange_type_die (tree, tree, tree, dw_die_ref);
+static dw_die_ref subrange_type_die (tree, tree, tree, tree, dw_die_ref);
 static int decl_quals (const_tree);
-static dw_die_ref modified_type_die (tree, int, dw_die_ref);
+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);
@@ -3227,6 +3311,8 @@ static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx,
 static dw_loc_descr_ref loc_descriptor (rtx, machine_mode mode,
                                        enum var_init_status);
 struct loc_descr_context;
+static void add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref);
+static void add_loc_list (dw_loc_list_ref *ret, dw_loc_list_ref list);
 static dw_loc_list_ref loc_list_from_tree (tree, int,
                                           const struct loc_descr_context *);
 static dw_loc_descr_ref loc_descriptor_from_tree (tree, int,
@@ -3236,17 +3322,19 @@ 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);
 static unsigned HOST_WIDE_INT simple_type_size_in_bits (const_tree);
-static HOST_WIDE_INT field_byte_offset (const_tree);
+struct vlr_context;
+static dw_loc_descr_ref field_byte_offset (const_tree, struct vlr_context *,
+                                          HOST_WIDE_INT *);
 static void add_AT_location_description        (dw_die_ref, enum dwarf_attribute,
                                         dw_loc_list_ref);
-static void add_data_member_location_attribute (dw_die_ref, tree);
+static void add_data_member_location_attribute (dw_die_ref, tree,
+                                               struct vlr_context *);
 static bool add_const_value_attribute (dw_die_ref, rtx);
 static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
 static void insert_wide_int (const wide_int &, unsigned char *, int);
 static void insert_float (const_rtx, unsigned char *);
 static rtx rtl_for_decl_location (tree);
-static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool,
-                                                  enum dwarf_attribute);
+static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool);
 static bool tree_add_const_value_attribute (dw_die_ref, tree);
 static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
@@ -3258,20 +3346,24 @@ static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree,
                            const struct loc_descr_context *);
 static void add_subscript_info (dw_die_ref, tree, bool);
 static void add_byte_size_attribute (dw_die_ref, tree);
-static void add_bit_offset_attribute (dw_die_ref, tree);
+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_pure_or_virtual_attribute (dw_die_ref, tree);
 static void add_src_coords_attributes (dw_die_ref, tree);
 static void add_name_and_src_coords_attributes (dw_die_ref, tree);
+static void add_discr_value (dw_die_ref, dw_discr_value *);
+static void add_discr_list (dw_die_ref, dw_discr_list_ref);
+static inline dw_discr_list_ref AT_discr_list (dw_attr_node *);
 static void push_decl_scope (tree);
 static void pop_decl_scope (void);
 static dw_die_ref scope_die_for (tree, dw_die_ref);
 static inline int local_scope_p (dw_die_ref);
 static inline int class_scope_p (dw_die_ref);
 static inline int class_or_namespace_scope_p (dw_die_ref);
-static void add_type_attribute (dw_die_ref, tree, int, dw_die_ref);
+static void add_type_attribute (dw_die_ref, tree, int, bool, dw_die_ref);
 static void add_calling_convention_attribute (dw_die_ref, tree);
 static const char *type_tag (const_tree);
 static tree member_declared_type (const_tree);
@@ -3294,10 +3386,10 @@ static void gen_const_die (tree, dw_die_ref);
 static void gen_label_die (tree, dw_die_ref);
 static void gen_lexical_block_die (tree, dw_die_ref);
 static void gen_inlined_subroutine_die (tree, dw_die_ref);
-static void gen_field_die (tree, dw_die_ref);
+static void gen_field_die (tree, struct vlr_context *, dw_die_ref);
 static void gen_ptr_to_mbr_type_die (tree, dw_die_ref);
 static dw_die_ref gen_compile_unit_die (const char *);
-static void gen_inheritance_die (tree, tree, dw_die_ref);
+static void gen_inheritance_die (tree, tree, tree, dw_die_ref);
 static void gen_member_die (tree, dw_die_ref);
 static void gen_struct_or_union_type_die (tree, dw_die_ref,
                                                enum debug_info_usage);
@@ -3306,12 +3398,11 @@ 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 inline int is_redundant_typedef (const_tree);
 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);
 static dw_die_ref gen_namelist_decl (tree, dw_die_ref, tree);
-static dw_die_ref gen_decl_die (tree, tree, dw_die_ref);
+static dw_die_ref gen_decl_die (tree, tree, struct vlr_context *, dw_die_ref);
 static dw_die_ref force_decl_die (tree);
 static dw_die_ref force_type_die (tree);
 static dw_die_ref setup_namespace_context (tree, dw_die_ref);
@@ -3338,8 +3429,8 @@ static void prune_unused_types_walk_attribs (dw_die_ref);
 static void prune_unused_types_prune (dw_die_ref);
 static void prune_unused_types (void);
 static int maybe_emit_file (struct dwarf_file_data *fd);
-static inline const char *AT_vms_delta1 (dw_attr_ref);
-static inline const char *AT_vms_delta2 (dw_attr_ref);
+static inline const char *AT_vms_delta1 (dw_attr_node *);
+static inline const char *AT_vms_delta2 (dw_attr_node *);
 static inline void add_AT_vms_delta (dw_die_ref, enum dwarf_attribute,
                                     const char *, const char *);
 static void append_entry_to_tmpl_value_parm_die_table (dw_die_ref, tree);
@@ -3781,7 +3872,7 @@ decl_class_context (tree decl)
 /* Add an attribute/value pair to a DIE.  */
 
 static inline void
-add_dwarf_attr (dw_die_ref die, dw_attr_ref attr)
+add_dwarf_attr (dw_die_ref die, dw_attr_node *attr)
 {
   /* Maybe this should be an assert?  */
   if (die == NULL)
@@ -3792,7 +3883,7 @@ add_dwarf_attr (dw_die_ref die, dw_attr_ref attr)
 }
 
 static inline enum dw_val_class
-AT_class (dw_attr_ref a)
+AT_class (dw_attr_node *a)
 {
   return a->dw_attr_val.val_class;
 }
@@ -3803,7 +3894,7 @@ AT_class (dw_attr_ref a)
    pruning.  */
 
 static inline unsigned int
-AT_index (dw_attr_ref a)
+AT_index (dw_attr_node *a)
 {
   if (AT_class (a) == dw_val_class_str)
     return a->dw_attr_val.v.val_str->index;
@@ -3827,7 +3918,7 @@ add_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int flag)
 }
 
 static inline unsigned
-AT_flag (dw_attr_ref a)
+AT_flag (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_flag);
   return a->dw_attr_val.v.val_flag;
@@ -3848,7 +3939,7 @@ add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, HOST_WIDE_INT int_va
 }
 
 static inline HOST_WIDE_INT
-AT_int (dw_attr_ref a)
+AT_int (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_const);
   return a->dw_attr_val.v.val_int;
@@ -3870,7 +3961,7 @@ add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind,
 }
 
 static inline unsigned HOST_WIDE_INT
-AT_unsigned (dw_attr_ref a)
+AT_unsigned (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_unsigned_const);
   return a->dw_attr_val.v.val_unsigned;
@@ -3886,6 +3977,7 @@ add_AT_wide (dw_die_ref die, enum dwarf_attribute attr_kind,
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_wide_int;
+  attr.dw_attr_val.val_entry = NULL;
   attr.dw_attr_val.v.val_wide = ggc_alloc<wide_int> ();
   *attr.dw_attr_val.v.val_wide = w;
   add_dwarf_attr (die, &attr);
@@ -4044,7 +4136,7 @@ add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str)
 }
 
 static inline const char *
-AT_string (dw_attr_ref a)
+AT_string (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_str);
   return a->dw_attr_val.v.val_str->str;
@@ -4114,7 +4206,7 @@ find_string_form (struct indirect_string_node *node)
    output inline in DIE or out-of-line in .debug_str section.  */
 
 static enum dwarf_form
-AT_string_form (dw_attr_ref a)
+AT_string_form (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_str);
   return find_string_form (a->dw_attr_val.v.val_str);
@@ -4126,15 +4218,12 @@ static inline void
 add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_die)
 {
   dw_attr_node attr;
+  gcc_checking_assert (targ_die != NULL);
 
-#ifdef ENABLE_CHECKING
-  gcc_assert (targ_die != NULL);
-#else
   /* With LTO we can end up trying to reference something we didn't create
      a DIE for.  Avoid crashing later on a NULL referenced DIE.  */
   if (targ_die == NULL)
     return;
-#endif
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_die_ref;
@@ -4147,7 +4236,7 @@ add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_
 /* Change DIE reference REF to point to NEW_DIE instead.  */
 
 static inline void
-change_AT_die_ref (dw_attr_ref ref, dw_die_ref new_die)
+change_AT_die_ref (dw_attr_node *ref, dw_die_ref new_die)
 {
   gcc_assert (ref->dw_attr_val.val_class == dw_val_class_die_ref);
   ref->dw_attr_val.v.val_die_ref.die = new_die;
@@ -4166,14 +4255,14 @@ add_AT_specification (dw_die_ref die, dw_die_ref targ_die)
 }
 
 static inline dw_die_ref
-AT_ref (dw_attr_ref a)
+AT_ref (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_die_ref);
   return a->dw_attr_val.v.val_die_ref.die;
 }
 
 static inline int
-AT_ref_external (dw_attr_ref a)
+AT_ref_external (dw_attr_node *a)
 {
   if (a && AT_class (a) == dw_val_class_die_ref)
     return a->dw_attr_val.v.val_die_ref.external;
@@ -4182,7 +4271,7 @@ AT_ref_external (dw_attr_ref a)
 }
 
 static inline void
-set_AT_ref_external (dw_attr_ref a, int i)
+set_AT_ref_external (dw_attr_node *a, int i)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_die_ref);
   a->dw_attr_val.v.val_die_ref.external = i;
@@ -4217,7 +4306,7 @@ add_AT_loc (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_descr_ref loc
 }
 
 static inline dw_loc_descr_ref
-AT_loc (dw_attr_ref a)
+AT_loc (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_loc);
   return a->dw_attr_val.v.val_loc;
@@ -4228,6 +4317,9 @@ add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref
 {
   dw_attr_node attr;
 
+  if (XCOFF_DEBUGGING_INFO && !HAVE_XCOFF_DWARF_EXTRAS)
+    return;
+
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_loc_list;
   attr.dw_attr_val.val_entry = NULL;
@@ -4237,20 +4329,20 @@ add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref
 }
 
 static inline dw_loc_list_ref
-AT_loc_list (dw_attr_ref a)
+AT_loc_list (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_loc_list);
   return a->dw_attr_val.v.val_loc_list;
 }
 
 static inline dw_loc_list_ref *
-AT_loc_list_ptr (dw_attr_ref a)
+AT_loc_list_ptr (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_loc_list);
   return &a->dw_attr_val.v.val_loc_list;
 }
 
-struct addr_hasher : ggc_hasher<addr_table_entry *>
+struct addr_hasher : ggc_ptr_hash<addr_table_entry>
 {
   static hashval_t hash (addr_table_entry *);
   static bool equal (addr_table_entry *, addr_table_entry *);
@@ -4424,7 +4516,7 @@ add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr,
 /* Get the RTX from to an address DIE attribute.  */
 
 static inline rtx
-AT_addr (dw_attr_ref a)
+AT_addr (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_addr);
   return a->dw_attr_val.v.val_addr;
@@ -4448,7 +4540,7 @@ add_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind,
 /* Get the dwarf_file_data from a file DIE attribute.  */
 
 static inline struct dwarf_file_data *
-AT_file (dw_attr_ref a)
+AT_file (dw_attr_node *a)
 {
   gcc_assert (a && AT_class (a) == dw_val_class_file);
   return a->dw_attr_val.v.val_file;
@@ -4566,7 +4658,7 @@ add_AT_range_list (dw_die_ref die, enum dwarf_attribute attr_kind,
 /* Return the start label of a delta attribute.  */
 
 static inline const char *
-AT_vms_delta1 (dw_attr_ref a)
+AT_vms_delta1 (dw_attr_node *a)
 {
   gcc_assert (a && (AT_class (a) == dw_val_class_vms_delta));
   return a->dw_attr_val.v.val_vms_delta.lbl1;
@@ -4575,14 +4667,14 @@ AT_vms_delta1 (dw_attr_ref a)
 /* Return the end label of a delta attribute.  */
 
 static inline const char *
-AT_vms_delta2 (dw_attr_ref a)
+AT_vms_delta2 (dw_attr_node *a)
 {
   gcc_assert (a && (AT_class (a) == dw_val_class_vms_delta));
   return a->dw_attr_val.v.val_vms_delta.lbl2;
 }
 
 static inline const char *
-AT_lbl (dw_attr_ref a)
+AT_lbl (dw_attr_node *a)
 {
   gcc_assert (a && (AT_class (a) == dw_val_class_lbl_id
                    || AT_class (a) == dw_val_class_lineptr
@@ -4593,10 +4685,10 @@ AT_lbl (dw_attr_ref a)
 
 /* Get the attribute of type attr_kind.  */
 
-static dw_attr_ref
+static dw_attr_node *
 get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
   dw_die_ref spec = NULL;
 
@@ -4640,7 +4732,7 @@ get_die_parent (dw_die_ref die)
 static inline const char *
 get_AT_low_pc (dw_die_ref die)
 {
-  dw_attr_ref a = get_AT (die, DW_AT_low_pc);
+  dw_attr_node *a = get_AT (die, DW_AT_low_pc);
 
   return a ? AT_lbl (a) : NULL;
 }
@@ -4652,7 +4744,7 @@ get_AT_low_pc (dw_die_ref die)
 static inline const char *
 get_AT_hi_pc (dw_die_ref die)
 {
-  dw_attr_ref a = get_AT (die, DW_AT_high_pc);
+  dw_attr_node *a = get_AT (die, DW_AT_high_pc);
 
   return a ? AT_lbl (a) : NULL;
 }
@@ -4663,7 +4755,7 @@ get_AT_hi_pc (dw_die_ref die)
 static inline const char *
 get_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_node *a = get_AT (die, attr_kind);
 
   return a ? AT_string (a) : NULL;
 }
@@ -4674,7 +4766,7 @@ get_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind)
 static inline int
 get_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_node *a = get_AT (die, attr_kind);
 
   return a ? AT_flag (a) : 0;
 }
@@ -4685,7 +4777,7 @@ get_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind)
 static inline unsigned
 get_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_node *a = get_AT (die, attr_kind);
 
   return a ? AT_unsigned (a) : 0;
 }
@@ -4693,7 +4785,7 @@ get_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind)
 static inline dw_die_ref
 get_AT_ref (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_node *a = get_AT (die, attr_kind);
 
   return a ? AT_ref (a) : NULL;
 }
@@ -4701,7 +4793,7 @@ get_AT_ref (dw_die_ref die, enum dwarf_attribute attr_kind)
 static inline struct dwarf_file_data *
 get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a = get_AT (die, attr_kind);
+  dw_attr_node *a = get_AT (die, attr_kind);
 
   return a ? AT_file (a) : NULL;
 }
@@ -4751,16 +4843,17 @@ is_ada (void)
   return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
 }
 
-/* Remove the specified attribute if present.  */
+/* Remove the specified attribute if present.  Return TRUE if removal
+   was successful.  */
 
-static void
+static bool
 remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   if (! die)
-    return;
+    return false;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (a->dw_attr == attr_kind)
@@ -4772,8 +4865,9 @@ remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
        /* vec::ordered_remove should help reduce the number of abbrevs
           that are needed.  */
        die->die_attr->ordered_remove (ix);
-       return;
+       return true;
       }
+  return false;
 }
 
 /* Remove CHILD from its parent.  PREV must have the property that
@@ -4847,6 +4941,7 @@ remove_child_TAG (dw_die_ref die, enum dwarf_tag tag)
     while (c->die_tag == tag)
       {
        remove_child_with_prev (c, prev);
+       c->die_parent = NULL;
        /* Might have removed every child.  */
        if (c == c->die_sib)
          return;
@@ -4876,6 +4971,40 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
   die->die_child = child_die;
 }
 
+/* Like add_child_die, but put CHILD_DIE after AFTER_DIE.  */
+
+static void
+add_child_die_after (dw_die_ref die, dw_die_ref child_die,
+                    dw_die_ref after_die)
+{
+  gcc_assert (die
+             && child_die
+             && after_die
+             && die->die_child
+             && die != child_die);
+
+  child_die->die_parent = die;
+  child_die->die_sib = after_die->die_sib;
+  after_die->die_sib = child_die;
+  if (die->die_child == after_die)
+    die->die_child = child_die;
+}
+
+/* Unassociate CHILD from its parent, and make its parent be
+   NEW_PARENT.  */
+
+static void
+reparent_child (dw_die_ref child, dw_die_ref new_parent)
+{
+  for (dw_die_ref p = child->die_parent->die_child; ; p = p->die_sib)
+    if (p->die_sib == child)
+      {
+       remove_child_with_prev (child, p);
+       break;
+      }
+  add_child_die (new_parent, child);
+}
+
 /* Move CHILD, which must be a child of PARENT or the DIE for which PARENT
    is the specification, to the end of PARENT's list of children.
    This is done by removing and re-adding it.  */
@@ -4883,8 +5012,6 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
 static void
 splice_child_die (dw_die_ref parent, dw_die_ref child)
 {
-  dw_die_ref p;
-
   /* We want the declaration DIE from inside the class, not the
      specification DIE at toplevel.  */
   if (child->die_parent != parent)
@@ -4899,17 +5026,13 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
              || (child->die_parent
                  == get_AT_ref (parent, DW_AT_specification)));
 
-  for (p = child->die_parent->die_child; ; p = p->die_sib)
-    if (p->die_sib == child)
-      {
-       remove_child_with_prev (child, p);
-       break;
-      }
-
-  add_child_die (parent, child);
+  reparent_child (child, parent);
 }
 
-/* Return a pointer to a newly created DIE node.  */
+/* Create and return a new die with a parent of PARENT_DIE.  If
+   PARENT_DIE is NULL, the new DIE is placed in limbo and an
+   associated tree T must be supplied to determine parenthood
+   later.  */
 
 static inline dw_die_ref
 new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
@@ -4924,6 +5047,35 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
     {
       limbo_die_node *limbo_node;
 
+      /* No DIEs created after early dwarf should end up in limbo,
+        because the limbo list should not persist past LTO
+        streaming.  */
+      if (tag_value != DW_TAG_compile_unit
+         /* These are allowed because they're generated while
+            breaking out COMDAT units late.  */
+         && tag_value != DW_TAG_type_unit
+         && !early_dwarf
+         /* Allow nested functions to live in limbo because they will
+            only temporarily live there, as decls_for_scope will fix
+            them up.  */
+         && (TREE_CODE (t) != FUNCTION_DECL
+             || !decl_function_context (t))
+         /* Same as nested functions above but for types.  Types that
+            are local to a function will be fixed in
+            decls_for_scope.  */
+         && (!RECORD_OR_UNION_TYPE_P (t)
+             || !TYPE_CONTEXT (t)
+             || TREE_CODE (TYPE_CONTEXT (t)) != FUNCTION_DECL)
+         /* FIXME debug-early: Allow late limbo DIE creation for LTO,
+            especially in the ltrans stage, but once we implement LTO
+            dwarf streaming, we should remove this exception.  */
+         && !in_lto_p)
+       {
+         fprintf (stderr, "symbol ended up in limbo too late:");
+         debug_generic_stmt (t);
+         gcc_unreachable ();
+       }
+
       limbo_node = ggc_cleared_alloc<limbo_die_node> ();
       limbo_node->die = die;
       limbo_node->created_for = t;
@@ -5218,9 +5370,10 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
              && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))
        {
          HOST_WIDE_INT maxsize;
-         tree innerdecl;
-         innerdecl
-           = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize);
+         bool reverse;
+         tree innerdecl
+           = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize,
+                                      &reverse);
          if (!DECL_P (innerdecl)
              || DECL_IGNORED_P (innerdecl)
              || TREE_STATIC (innerdecl)
@@ -5401,6 +5554,15 @@ print_signature (FILE *outfile, char *sig)
     fprintf (outfile, "%02x", sig[i] & 0xff);
 }
 
+static inline void
+print_discr_value (FILE *outfile, dw_discr_value *discr_value)
+{
+  if (discr_value->pos)
+    fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, discr_value->v.sval);
+  else
+    fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, discr_value->v.uval);
+}
+
 static void print_loc_descr (dw_loc_descr_ref, FILE *);
 
 /* Print the value associated to the VAL DWARF value node to OUTFILE.  If
@@ -5445,7 +5607,7 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
       fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, val->v.val_unsigned);
       break;
     case dw_val_class_const_double:
-      fprintf (outfile, "constant ("HOST_WIDE_INT_PRINT_DEC","\
+      fprintf (outfile, "constant (" HOST_WIDE_INT_PRINT_DEC","\
                        HOST_WIDE_INT_PRINT_UNSIGNED")",
               val->v.val_double.high,
               val->v.val_double.low);
@@ -5519,6 +5681,26 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
          fprintf (outfile, "%02x", val->v.val_data8[i]);
        break;
       }
+    case dw_val_class_discr_value:
+      print_discr_value (outfile, &val->v.val_discr_value);
+      break;
+    case dw_val_class_discr_list:
+      for (dw_discr_list_ref node = val->v.val_discr_list;
+          node != NULL;
+          node = node->dw_discr_next)
+       {
+         if (node->dw_discr_range)
+           {
+             fprintf (outfile, " .. ");
+             print_discr_value (outfile, &node->dw_discr_lower_bound);
+             print_discr_value (outfile, &node->dw_discr_upper_bound);
+           }
+         else
+           print_discr_value (outfile, &node->dw_discr_lower_bound);
+
+         if (node->dw_discr_next != NULL)
+           fprintf (outfile, " | ");
+       }
     default:
       break;
     }
@@ -5527,7 +5709,7 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
 /* Likewise, for a DIE attribute.  */
 
 static void
-print_attribute (dw_attr_ref a, bool recurse, FILE *outfile)
+print_attribute (dw_attr_node *a, bool recurse, FILE *outfile)
 {
   print_dw_val (&a->dw_attr_val, recurse, outfile);
 }
@@ -5574,7 +5756,7 @@ print_loc_descr (dw_loc_descr_ref loc, FILE *outfile)
 static void
 print_die (dw_die_ref die, FILE *outfile)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   dw_die_ref c;
   unsigned ix;
 
@@ -5655,6 +5837,69 @@ debug_dwarf (void)
   print_indent = 0;
   print_die (comp_unit_die (), stderr);
 }
+
+/* Sanity checks on DIEs.  */
+
+static void
+check_die (dw_die_ref die)
+{
+  unsigned ix;
+  dw_attr_node *a;
+  bool inline_found = false;
+  int n_location = 0, n_low_pc = 0, n_high_pc = 0, n_artificial = 0;
+  int n_decl_line = 0, n_decl_file = 0;
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+    {
+      switch (a->dw_attr)
+       {
+       case DW_AT_inline:
+         if (a->dw_attr_val.v.val_unsigned)
+           inline_found = true;
+         break;
+       case DW_AT_location:
+         ++n_location;
+         break;
+       case DW_AT_low_pc:
+         ++n_low_pc;
+         break;
+       case DW_AT_high_pc:
+         ++n_high_pc;
+         break;
+       case DW_AT_artificial:
+         ++n_artificial;
+         break;
+       case DW_AT_decl_line:
+         ++n_decl_line;
+         break;
+       case DW_AT_decl_file:
+         ++n_decl_file;
+         break;
+       default:
+         break;
+       }
+    }
+  if (n_location > 1 || n_low_pc > 1 || n_high_pc > 1 || n_artificial > 1
+      || n_decl_line > 1 || n_decl_file > 1)
+    {
+      fprintf (stderr, "Duplicate attributes in DIE:\n");
+      debug_dwarf_die (die);
+      gcc_unreachable ();
+    }
+  if (inline_found)
+    {
+      /* A debugging information entry that is a member of an abstract
+        instance tree [that has DW_AT_inline] should not contain any
+        attributes which describe aspects of the subroutine which vary
+        between distinct inlined expansions or distinct out-of-line
+        expansions.  */
+      FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+       gcc_assert (a->dw_attr != DW_AT_low_pc
+                   && a->dw_attr != DW_AT_high_pc
+                   && a->dw_attr != DW_AT_location
+                   && a->dw_attr != DW_AT_frame_base
+                   && a->dw_attr != DW_AT_GNU_all_call_sites);
+    }
+}
 \f
 /* Start a new compilation unit DIE for an include file.  OLD_UNIT is the CU
    for the enclosing include file, if any.  BINCL_DIE is the DW_TAG_GNU_BINCL
@@ -5704,7 +5949,7 @@ loc_checksum (dw_loc_descr_ref loc, struct md5_ctx *ctx)
 /* Calculate the checksum of an attribute.  */
 
 static void
-attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark)
+attr_checksum (dw_attr_node *at, struct md5_ctx *ctx, int *mark)
 {
   dw_loc_descr_ref loc;
   rtx r;
@@ -5790,7 +6035,7 @@ static void
 die_checksum (dw_die_ref die, struct md5_ctx *ctx, int *mark)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   /* To avoid infinite recursion.  */
@@ -5924,7 +6169,7 @@ loc_checksum_ordered (dw_loc_descr_ref loc, struct md5_ctx *ctx)
 /* Calculate the checksum of an attribute.  */
 
 static void
-attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
+attr_checksum_ordered (enum dwarf_tag tag, dw_attr_node *at,
                       struct md5_ctx *ctx, int *mark)
 {
   dw_loc_descr_ref loc;
@@ -5947,7 +6192,7 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
          || (at->dw_attr == DW_AT_friend
              && tag == DW_TAG_friend))
        {
-         dw_attr_ref name_attr = get_AT (target_die, DW_AT_name);
+         dw_attr_node *name_attr = get_AT (target_die, DW_AT_name);
 
          if (name_attr != NULL)
            {
@@ -6079,53 +6324,55 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
 
 struct checksum_attributes
 {
-  dw_attr_ref at_name;
-  dw_attr_ref at_type;
-  dw_attr_ref at_friend;
-  dw_attr_ref at_accessibility;
-  dw_attr_ref at_address_class;
-  dw_attr_ref at_allocated;
-  dw_attr_ref at_artificial;
-  dw_attr_ref at_associated;
-  dw_attr_ref at_binary_scale;
-  dw_attr_ref at_bit_offset;
-  dw_attr_ref at_bit_size;
-  dw_attr_ref at_bit_stride;
-  dw_attr_ref at_byte_size;
-  dw_attr_ref at_byte_stride;
-  dw_attr_ref at_const_value;
-  dw_attr_ref at_containing_type;
-  dw_attr_ref at_count;
-  dw_attr_ref at_data_location;
-  dw_attr_ref at_data_member_location;
-  dw_attr_ref at_decimal_scale;
-  dw_attr_ref at_decimal_sign;
-  dw_attr_ref at_default_value;
-  dw_attr_ref at_digit_count;
-  dw_attr_ref at_discr;
-  dw_attr_ref at_discr_list;
-  dw_attr_ref at_discr_value;
-  dw_attr_ref at_encoding;
-  dw_attr_ref at_endianity;
-  dw_attr_ref at_explicit;
-  dw_attr_ref at_is_optional;
-  dw_attr_ref at_location;
-  dw_attr_ref at_lower_bound;
-  dw_attr_ref at_mutable;
-  dw_attr_ref at_ordering;
-  dw_attr_ref at_picture_string;
-  dw_attr_ref at_prototyped;
-  dw_attr_ref at_small;
-  dw_attr_ref at_segment;
-  dw_attr_ref at_string_length;
-  dw_attr_ref at_threads_scaled;
-  dw_attr_ref at_upper_bound;
-  dw_attr_ref at_use_location;
-  dw_attr_ref at_use_UTF8;
-  dw_attr_ref at_variable_parameter;
-  dw_attr_ref at_virtuality;
-  dw_attr_ref at_visibility;
-  dw_attr_ref at_vtable_elem_location;
+  dw_attr_node *at_name;
+  dw_attr_node *at_type;
+  dw_attr_node *at_friend;
+  dw_attr_node *at_accessibility;
+  dw_attr_node *at_address_class;
+  dw_attr_node *at_allocated;
+  dw_attr_node *at_artificial;
+  dw_attr_node *at_associated;
+  dw_attr_node *at_binary_scale;
+  dw_attr_node *at_bit_offset;
+  dw_attr_node *at_bit_size;
+  dw_attr_node *at_bit_stride;
+  dw_attr_node *at_byte_size;
+  dw_attr_node *at_byte_stride;
+  dw_attr_node *at_const_value;
+  dw_attr_node *at_containing_type;
+  dw_attr_node *at_count;
+  dw_attr_node *at_data_location;
+  dw_attr_node *at_data_member_location;
+  dw_attr_node *at_decimal_scale;
+  dw_attr_node *at_decimal_sign;
+  dw_attr_node *at_default_value;
+  dw_attr_node *at_digit_count;
+  dw_attr_node *at_discr;
+  dw_attr_node *at_discr_list;
+  dw_attr_node *at_discr_value;
+  dw_attr_node *at_encoding;
+  dw_attr_node *at_endianity;
+  dw_attr_node *at_explicit;
+  dw_attr_node *at_is_optional;
+  dw_attr_node *at_location;
+  dw_attr_node *at_lower_bound;
+  dw_attr_node *at_mutable;
+  dw_attr_node *at_ordering;
+  dw_attr_node *at_picture_string;
+  dw_attr_node *at_prototyped;
+  dw_attr_node *at_small;
+  dw_attr_node *at_segment;
+  dw_attr_node *at_string_length;
+  dw_attr_node *at_string_length_bit_size;
+  dw_attr_node *at_string_length_byte_size;
+  dw_attr_node *at_threads_scaled;
+  dw_attr_node *at_upper_bound;
+  dw_attr_node *at_use_location;
+  dw_attr_node *at_use_UTF8;
+  dw_attr_node *at_variable_parameter;
+  dw_attr_node *at_virtuality;
+  dw_attr_node *at_visibility;
+  dw_attr_node *at_vtable_elem_location;
 };
 
 /* Collect the attributes that we will want to use for the checksum.  */
@@ -6133,7 +6380,7 @@ struct checksum_attributes
 static void
 collect_checksum_attributes (struct checksum_attributes *attrs, dw_die_ref die)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -6257,6 +6504,12 @@ collect_checksum_attributes (struct checksum_attributes *attrs, dw_die_ref die)
         case DW_AT_string_length:
           attrs->at_string_length = a;
           break;
+       case DW_AT_string_length_bit_size:
+         attrs->at_string_length_bit_size = a;
+         break;
+       case DW_AT_string_length_byte_size:
+         attrs->at_string_length_byte_size = a;
+         break;
         case DW_AT_threads_scaled:
           attrs->at_threads_scaled = a;
           break;
@@ -6343,6 +6596,8 @@ die_checksum_ordered (dw_die_ref die, struct md5_ctx *ctx, int *mark)
   CHECKSUM_ATTR (attrs.at_small);
   CHECKSUM_ATTR (attrs.at_segment);
   CHECKSUM_ATTR (attrs.at_string_length);
+  CHECKSUM_ATTR (attrs.at_string_length_bit_size);
+  CHECKSUM_ATTR (attrs.at_string_length_byte_size);
   CHECKSUM_ATTR (attrs.at_threads_scaled);
   CHECKSUM_ATTR (attrs.at_upper_bound);
   CHECKSUM_ATTR (attrs.at_use_location);
@@ -6357,7 +6612,7 @@ die_checksum_ordered (dw_die_ref die, struct md5_ctx *ctx, int *mark)
   /* Checksum the child DIEs.  */
   c = die->die_child;
   if (c) do {
-    dw_attr_ref name_attr;
+    dw_attr_node *name_attr;
 
     c = c->die_sib;
     name_attr = get_AT (c, DW_AT_name);
@@ -6560,7 +6815,7 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
 /* Do the attributes look the same?  */
 
 static int
-same_attr_p (dw_attr_ref at1, dw_attr_ref at2, int *mark)
+same_attr_p (dw_attr_node *at1, dw_attr_node *at2, int *mark)
 {
   if (at1->dw_attr != at2->dw_attr)
     return 0;
@@ -6579,7 +6834,7 @@ static int
 same_die_p (dw_die_ref die1, dw_die_ref die2, int *mark)
 {
   dw_die_ref c1, c2;
-  dw_attr_ref a1;
+  dw_attr_node *a1;
   unsigned ix;
 
   /* To avoid infinite recursion.  */
@@ -6863,30 +7118,29 @@ struct cu_hash_table_entry
 
 /* Helpers to manipulate hash table of CUs.  */
 
-struct cu_hash_table_entry_hasher
+struct cu_hash_table_entry_hasher : pointer_hash <cu_hash_table_entry>
 {
-  typedef cu_hash_table_entry value_type;
-  typedef die_struct compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
-  static inline void remove (value_type *);
+  typedef die_struct *compare_type;
+  static inline hashval_t hash (const cu_hash_table_entry *);
+  static inline bool equal (const cu_hash_table_entry *, const die_struct *);
+  static inline void remove (cu_hash_table_entry *);
 };
 
 inline hashval_t
-cu_hash_table_entry_hasher::hash (const value_type *entry)
+cu_hash_table_entry_hasher::hash (const cu_hash_table_entry *entry)
 {
   return htab_hash_string (entry->cu->die_id.die_symbol);
 }
 
 inline bool
-cu_hash_table_entry_hasher::equal (const value_type *entry1,
-                                  const compare_type *entry2)
+cu_hash_table_entry_hasher::equal (const cu_hash_table_entry *entry1,
+                                  const die_struct *entry2)
 {
   return !strcmp (entry1->cu->die_id.die_symbol, entry2->die_id.die_symbol);
 }
 
 inline void
-cu_hash_table_entry_hasher::remove (value_type *entry)
+cu_hash_table_entry_hasher::remove (cu_hash_table_entry *entry)
 {
   struct cu_hash_table_entry *next;
 
@@ -7020,7 +7274,7 @@ break_out_includes (dw_die_ref die)
 static int
 is_declaration_die (dw_die_ref die)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -7103,7 +7357,7 @@ static dw_die_ref
 clone_die (dw_die_ref die)
 {
   dw_die_ref clone;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   clone = ggc_cleared_alloc<die_node> ();
@@ -7135,7 +7389,7 @@ clone_as_declaration (dw_die_ref die)
 {
   dw_die_ref clone;
   dw_die_ref decl;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   /* If the DIE is already a declaration, just clone it.  */
@@ -7200,23 +7454,22 @@ struct decl_table_entry
 
 /* Hashtable helpers.  */
 
-struct decl_table_entry_hasher : typed_free_remove <decl_table_entry>
+struct decl_table_entry_hasher : free_ptr_hash <decl_table_entry>
 {
-  typedef decl_table_entry value_type;
-  typedef die_struct compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  typedef die_struct *compare_type;
+  static inline hashval_t hash (const decl_table_entry *);
+  static inline bool equal (const decl_table_entry *, const die_struct *);
 };
 
 inline hashval_t
-decl_table_entry_hasher::hash (const value_type *entry)
+decl_table_entry_hasher::hash (const decl_table_entry *entry)
 {
   return htab_hash_pointer (entry->orig);
 }
 
 inline bool
-decl_table_entry_hasher::equal (const value_type *entry1,
-                               const compare_type *entry2)
+decl_table_entry_hasher::equal (const decl_table_entry *entry1,
+                               const die_struct *entry2)
 {
   return entry1->orig == entry2;
 }
@@ -7296,7 +7549,7 @@ copy_declaration_context (dw_die_ref unit, dw_die_ref die)
     {
       unsigned ix;
       dw_die_ref c;
-      dw_attr_ref a;
+      dw_attr_node *a;
 
       /* The original DIE will be changed to a declaration, and must
          be moved to be a child of the original declaration DIE.  */
@@ -7480,6 +7733,101 @@ remove_child_or_replace_with_skeleton (dw_die_ref unit, dw_die_ref child,
   return skeleton;
 }
 
+static void
+copy_dwarf_procs_ref_in_attrs (dw_die_ref die,
+                              comdat_type_node *type_node,
+                              hash_map<dw_die_ref, dw_die_ref> &copied_dwarf_procs);
+
+/* Helper for copy_dwarf_procs_ref_in_dies.  Make a copy of the DIE DWARF
+   procedure, put it under TYPE_NODE and return the copy.  Continue looking for
+   DWARF procedure references in the DW_AT_location attribute.  */
+
+static dw_die_ref
+copy_dwarf_procedure (dw_die_ref die,
+                     comdat_type_node *type_node,
+                     hash_map<dw_die_ref, dw_die_ref> &copied_dwarf_procs)
+{
+  gcc_assert (die->die_tag == DW_TAG_dwarf_procedure);
+
+  /* DWARF procedures are not supposed to have children...  */
+  gcc_assert (die->die_child == NULL);
+
+  /* ... and they are supposed to have only one attribute: DW_AT_location.  */
+  gcc_assert (vec_safe_length (die->die_attr) == 1
+             && ((*die->die_attr)[0].dw_attr == DW_AT_location));
+
+  /* Do not copy more than once DWARF procedures.  */
+  bool existed;
+  dw_die_ref &die_copy = copied_dwarf_procs.get_or_insert (die, &existed);
+  if (existed)
+    return die_copy;
+
+  die_copy = clone_die (die);
+  add_child_die (type_node->root_die, die_copy);
+  copy_dwarf_procs_ref_in_attrs (die_copy, type_node, copied_dwarf_procs);
+  return die_copy;
+}
+
+/* Helper for copy_dwarf_procs_ref_in_dies.  Look for references to DWARF
+   procedures in DIE's attributes.  */
+
+static void
+copy_dwarf_procs_ref_in_attrs (dw_die_ref die,
+                              comdat_type_node *type_node,
+                              hash_map<dw_die_ref, dw_die_ref> &copied_dwarf_procs)
+{
+  dw_attr_node *a;
+  unsigned i;
+
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, i, a)
+    {
+      dw_loc_descr_ref loc;
+
+      if (a->dw_attr_val.val_class != dw_val_class_loc)
+       continue;
+
+      for (loc = a->dw_attr_val.v.val_loc; loc != NULL; loc = loc->dw_loc_next)
+       {
+         switch (loc->dw_loc_opc)
+           {
+           case DW_OP_call2:
+           case DW_OP_call4:
+           case DW_OP_call_ref:
+             gcc_assert (loc->dw_loc_oprnd1.val_class
+                         == dw_val_class_die_ref);
+             loc->dw_loc_oprnd1.v.val_die_ref.die
+               = copy_dwarf_procedure (loc->dw_loc_oprnd1.v.val_die_ref.die,
+                                       type_node,
+                                       copied_dwarf_procs);
+
+           default:
+             break;
+           }
+       }
+    }
+}
+
+/* Copy DWARF procedures that are referenced by the DIE tree to TREE_NODE and
+   rewrite references to point to the copies.
+
+   References are looked for in DIE's attributes and recursively in all its
+   children attributes that are location descriptions. COPIED_DWARF_PROCS is a
+   mapping from old DWARF procedures to their copy. It is used not to copy
+   twice the same DWARF procedure under TYPE_NODE.  */
+
+static void
+copy_dwarf_procs_ref_in_dies (dw_die_ref die,
+                             comdat_type_node *type_node,
+                             hash_map<dw_die_ref, dw_die_ref> &copied_dwarf_procs)
+{
+  dw_die_ref c;
+
+  copy_dwarf_procs_ref_in_attrs (die, type_node, copied_dwarf_procs);
+  FOR_EACH_CHILD (die, c, copy_dwarf_procs_ref_in_dies (c,
+                                                       type_node,
+                                                       copied_dwarf_procs));
+}
+
 /* Traverse the DIE and set up additional .debug_types sections for each
    type worthy of being placed in a COMDAT section.  */
 
@@ -7503,7 +7851,7 @@ break_out_comdat_types (dw_die_ref die)
     if (should_move_die_to_comdat (c))
       {
         dw_die_ref replacement;
-       comdat_type_node_ref type_node;
+       comdat_type_node *type_node;
 
         /* Break out nested types into their own type units.  */
         break_out_comdat_types (c);
@@ -7530,6 +7878,13 @@ break_out_comdat_types (dw_die_ref die)
         /* Add the DIE to the new compunit.  */
        add_child_die (unit, c);
 
+       /* Types can reference DWARF procedures for type size or data location
+          expressions.  Calls in DWARF expressions cannot target procedures
+          that are not in the same section.  So we must copy DWARF procedures
+          along with this type and then rewrite references to them.  */
+       hash_map<dw_die_ref, dw_die_ref> copied_dwarf_procs;
+       copy_dwarf_procs_ref_in_dies (c, type_node, copied_dwarf_procs);
+
         if (replacement != NULL)
           c = replacement;
       }
@@ -7588,7 +7943,7 @@ static void
 copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type *decl_table)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -7713,7 +8068,7 @@ static void
 output_location_lists (dw_die_ref die)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -7742,16 +8097,14 @@ struct external_ref
 
 /* Hashtable helpers.  */
 
-struct external_ref_hasher : typed_free_remove <external_ref>
+struct external_ref_hasher : free_ptr_hash <external_ref>
 {
-  typedef external_ref value_type;
-  typedef external_ref compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  static inline hashval_t hash (const external_ref *);
+  static inline bool equal (const external_ref *, const external_ref *);
 };
 
 inline hashval_t
-external_ref_hasher::hash (const value_type *r)
+external_ref_hasher::hash (const external_ref *r)
 {
   dw_die_ref die = r->type;
   hashval_t h = 0;
@@ -7765,14 +8118,14 @@ external_ref_hasher::hash (const value_type *r)
     {
       /* We have a type signature; use a subset of the bits as the hash.
         The 8-byte signature is at least as large as hashval_t.  */
-      comdat_type_node_ref type_node = die->die_id.die_type_node;
+      comdat_type_node *type_node = die->die_id.die_type_node;
       memcpy (&h, type_node->signature, sizeof (h));
     }
   return h;
 }
 
 inline bool
-external_ref_hasher::equal (const value_type *r1, const compare_type *r2)
+external_ref_hasher::equal (const external_ref *r1, const external_ref *r2)
 {
   return r1->type == r2->type;
 }
@@ -7807,7 +8160,7 @@ static void
 optimize_external_refs_1 (dw_die_ref die, external_ref_hash_type *map)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
   struct external_ref *ref_p;
 
@@ -7895,7 +8248,7 @@ build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
   unsigned long abbrev_id;
   unsigned int n_alloc;
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   /* Scan the DIE references, and replace any that refer to
@@ -7919,7 +8272,7 @@ build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
   for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
     {
       dw_die_ref abbrev = abbrev_die_table[abbrev_id];
-      dw_attr_ref die_a, abbrev_a;
+      dw_attr_node *die_a, *abbrev_a;
       unsigned ix;
       bool ok = true;
 
@@ -7991,7 +8344,7 @@ static unsigned long
 size_of_die (dw_die_ref die)
 {
   unsigned long size = 0;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
   enum dwarf_form form;
 
@@ -8134,6 +8487,18 @@ size_of_die (dw_die_ref die)
        case dw_val_class_high_pc:
          size += DWARF2_ADDR_SIZE;
          break;
+       case dw_val_class_discr_value:
+         size += size_of_discr_value (&a->dw_attr_val.v.val_discr_value);
+         break;
+       case dw_val_class_discr_list:
+           {
+             unsigned block_size = size_of_discr_list (AT_discr_list (a));
+
+             /* This is a block, so we have the block length and then its
+                data.  */
+             size += constant_size (block_size) + block_size;
+           }
+         break;
        default:
          gcc_unreachable ();
        }
@@ -8230,7 +8595,7 @@ static void
 unmark_all_dies (dw_die_ref die)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   if (!die->die_mark)
@@ -8284,7 +8649,7 @@ size_of_pubnames (vec<pubname_entry, va_gc> *names)
 {
   unsigned long size;
   unsigned i;
-  pubname_ref p;
+  pubname_entry *p;
   int space_for_flags = (debug_generate_pub_sections == 2) ? 1 : 0;
 
   size = DWARF_PUBNAMES_HEADER_SIZE;
@@ -8334,7 +8699,7 @@ size_of_aranges (void)
 /* Select the encoding of an attribute value.  */
 
 static enum dwarf_form
-value_format (dw_attr_ref a)
+value_format (dw_attr_node *a)
 {
   switch (AT_class (a))
     {
@@ -8517,6 +8882,23 @@ value_format (dw_attr_ref a)
          gcc_unreachable ();
        }
 
+    case dw_val_class_discr_value:
+      return (a->dw_attr_val.v.val_discr_value.pos
+             ? DW_FORM_udata
+             : DW_FORM_sdata);
+    case dw_val_class_discr_list:
+      switch (constant_size (size_of_discr_list (AT_discr_list (a))))
+       {
+       case 1:
+         return DW_FORM_block1;
+       case 2:
+         return DW_FORM_block2;
+       case 4:
+         return DW_FORM_block4;
+       default:
+         gcc_unreachable ();
+       }
+
     default:
       gcc_unreachable ();
     }
@@ -8525,7 +8907,7 @@ value_format (dw_attr_ref a)
 /* Output the encoding of an attribute value.  */
 
 static void
-output_value_format (dw_attr_ref a)
+output_value_format (dw_attr_node *a)
 {
   enum dwarf_form form = value_format (a);
 
@@ -8538,7 +8920,7 @@ static void
 output_die_abbrevs (unsigned long abbrev_id, dw_die_ref abbrev)
 {
   unsigned ix;
-  dw_attr_ref a_attr;
+  dw_attr_node *a_attr;
 
   dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)");
   dw2_asm_output_data_uleb128 (abbrev->die_tag, "(TAG: %s)",
@@ -8713,7 +9095,7 @@ output_loc_list (dw_loc_list_ref list_head)
    indirect reference.  */
 
 static void
-output_range_list_offset (dw_attr_ref a)
+output_range_list_offset (dw_attr_node *a)
 {
   const char *name = dwarf_attr_name (a->dw_attr);
 
@@ -8733,7 +9115,7 @@ output_range_list_offset (dw_attr_ref a)
 /* Output the offset into the debug_loc section.  */
 
 static void
-output_loc_list_offset (dw_attr_ref a)
+output_loc_list_offset (dw_attr_node *a)
 {
   char *sym = AT_loc_list (a)->ll_symbol;
 
@@ -8749,7 +9131,7 @@ output_loc_list_offset (dw_attr_ref a)
 /* Output an attribute's index or value appropriately.  */
 
 static void
-output_attr_index_or_value (dw_attr_ref a)
+output_attr_index_or_value (dw_attr_node *a)
 {
   const char *name = dwarf_attr_name (a->dw_attr);
 
@@ -8786,13 +9168,24 @@ output_signature (const char *sig, const char *name)
     dw2_asm_output_data (1, sig[i], i == 0 ? "%s" : NULL, name);
 }
 
+/* Output a discriminant value.  */
+
+static inline void
+output_discr_value (dw_discr_value *discr_value, const char *name)
+{
+  if (discr_value->pos)
+    dw2_asm_output_data_uleb128 (discr_value->v.uval, "%s", name);
+  else
+    dw2_asm_output_data_sleb128 (discr_value->v.sval, "%s", name);
+}
+
 /* Output the DIE and its attributes.  Called recursively to generate
    the definitions of each child DIE.  */
 
 static void
 output_die (dw_die_ref die)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   dw_die_ref c;
   unsigned long size;
   unsigned ix;
@@ -8897,15 +9290,15 @@ output_die (dw_die_ref die)
              for (i = len - 1; i >= 0; --i)
                {
                  dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
-                                      name);
-                 name = NULL;
+                                      "%s", name);
+                 name = "";
                }
            else
              for (i = 0; i < len; ++i)
                {
                  dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
-                                      name);
-                 name = NULL;
+                                      "%s", name);
+                 name = "";
                }
          }
          break;
@@ -8959,7 +9352,7 @@ output_die (dw_die_ref die)
            {
              if (AT_ref (a)->comdat_type_p)
                {
-                 comdat_type_node_ref type_node =
+                 comdat_type_node *type_node =
                    AT_ref (a)->die_id.die_type_node;
 
                  gcc_assert (type_node);
@@ -9002,9 +9395,15 @@ output_die (dw_die_ref die)
          break;
 
        case dw_val_class_vms_delta:
+#ifdef ASM_OUTPUT_DWARF_VMS_DELTA
          dw2_asm_output_vms_delta (DWARF_OFFSET_SIZE,
                                    AT_vms_delta2 (a), AT_vms_delta1 (a),
                                    "%s", name);
+#else
+         dw2_asm_output_delta (DWARF_OFFSET_SIZE,
+                               AT_vms_delta2 (a), AT_vms_delta1 (a),
+                               "%s", name);
+#endif
          break;
 
        case dw_val_class_lbl_id:
@@ -9058,6 +9457,37 @@ output_die (dw_die_ref die)
                                get_AT_low_pc (die), "DW_AT_high_pc");
          break;
 
+       case dw_val_class_discr_value:
+         output_discr_value (&a->dw_attr_val.v.val_discr_value, name);
+         break;
+
+       case dw_val_class_discr_list:
+         {
+           dw_discr_list_ref list = AT_discr_list (a);
+           const int size = size_of_discr_list (list);
+
+           /* This is a block, so output its length first.  */
+           dw2_asm_output_data (constant_size (size), size,
+                                "%s: block size", name);
+
+           for (; list != NULL; list = list->dw_discr_next)
+             {
+               /* One byte for the discriminant value descriptor, and then as
+                  many LEB128 numbers as required.  */
+               if (list->dw_discr_range)
+                 dw2_asm_output_data (1, DW_DSC_range,
+                                      "%s: DW_DSC_range", name);
+               else
+                 dw2_asm_output_data (1, DW_DSC_label,
+                                      "%s: DW_DSC_label", name);
+
+               output_discr_value (&list->dw_discr_lower_bound, name);
+               if (list->dw_discr_range)
+                 output_discr_value (&list->dw_discr_upper_bound, name);
+             }
+           break;
+         }
+
        default:
          gcc_unreachable ();
        }
@@ -9081,12 +9511,16 @@ output_compilation_unit_header (void)
      DWARFv5 draft DIE tags in DWARFv4 format.  */
   int ver = dwarf_version < 5 ? dwarf_version : 4;
 
-  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
-    dw2_asm_output_data (4, 0xffffffff,
-      "Initial length escape value indicating 64-bit DWARF extension");
-  dw2_asm_output_data (DWARF_OFFSET_SIZE,
-                      next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
-                      "Length of Compilation Unit Info");
+  if (!XCOFF_DEBUGGING_INFO)
+    {
+      if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+       dw2_asm_output_data (4, 0xffffffff,
+         "Initial length escape value indicating 64-bit DWARF extension");
+      dw2_asm_output_data (DWARF_OFFSET_SIZE,
+                          next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
+                          "Length of Compilation Unit Info");
+    }
+
   dw2_asm_output_data (2, ver, "DWARF version number");
   dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label,
                         debug_abbrev_section,
@@ -9514,12 +9948,16 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
 {
   unsigned i;
   unsigned long pubnames_length = size_of_pubnames (names);
-  pubname_ref pub;
+  pubname_entry *pub;
 
-  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
-    dw2_asm_output_data (4, 0xffffffff,
-      "Initial length escape value indicating 64-bit DWARF extension");
-  dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, "Pub Info Length");
+  if (!XCOFF_DEBUGGING_INFO)
+    {
+      if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+       dw2_asm_output_data (4, 0xffffffff,
+         "Initial length escape value indicating 64-bit DWARF extension");
+      dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
+                          "Pub Info Length");
+    }
 
   /* Version number for pubnames/pubtypes is independent of dwarf version.  */
   dw2_asm_output_data (2, 2, "DWARF Version");
@@ -9551,7 +9989,7 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
             the skeleton DIE (if there is one).  */
          if (pub->die->comdat_type_p && names == pubtype_table)
            {
-             comdat_type_node_ref type_node = pub->die->die_id.die_type_node;
+             comdat_type_node *type_node = pub->die->die_id.die_type_node;
 
              if (type_node != NULL)
                die_offset = (type_node->skeleton_die != NULL
@@ -9589,15 +10027,20 @@ output_pubtables (void)
    text section generated for this compilation unit.  */
 
 static void
-output_aranges (unsigned long aranges_length)
+output_aranges (void)
 {
   unsigned i;
+  unsigned long aranges_length = size_of_aranges ();
+  
+  if (!XCOFF_DEBUGGING_INFO)
+    {
+      if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+       dw2_asm_output_data (4, 0xffffffff,
+         "Initial length escape value indicating 64-bit DWARF extension");
+      dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length,
+                          "Length of Address Ranges Info");
+    }
 
-  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
-    dw2_asm_output_data (4, 0xffffffff,
-      "Initial length escape value indicating 64-bit DWARF extension");
-  dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length,
-                      "Length of Address Ranges Info");
   /* Version number for aranges is still 2, even up to DWARF5.  */
   dw2_asm_output_data (2, 2, "DWARF Version");
   if (dwarf_split_debug_info)
@@ -9683,10 +10126,10 @@ add_ranges_num (int num)
   if (in_use == ranges_table_allocated)
     {
       ranges_table_allocated += RANGES_TABLE_INCREMENT;
-      ranges_table = GGC_RESIZEVEC (struct dw_ranges_struct, ranges_table,
+      ranges_table = GGC_RESIZEVEC (dw_ranges, ranges_table,
                                    ranges_table_allocated);
       memset (ranges_table + ranges_table_in_use, 0,
-             RANGES_TABLE_INCREMENT * sizeof (struct dw_ranges_struct));
+             RANGES_TABLE_INCREMENT * sizeof (dw_ranges));
     }
 
   ranges_table[in_use].num = num;
@@ -9719,12 +10162,10 @@ add_ranges_by_labels (dw_die_ref die, const char *begin, const char *end,
   if (in_use == ranges_by_label_allocated)
     {
       ranges_by_label_allocated += RANGES_TABLE_INCREMENT;
-      ranges_by_label = GGC_RESIZEVEC (struct dw_ranges_by_label_struct,
-                                      ranges_by_label,
+      ranges_by_label = GGC_RESIZEVEC (dw_ranges_by_label, ranges_by_label,
                                       ranges_by_label_allocated);
       memset (ranges_by_label + ranges_by_label_in_use, 0,
-             RANGES_TABLE_INCREMENT
-             * sizeof (struct dw_ranges_by_label_struct));
+             RANGES_TABLE_INCREMENT * sizeof (dw_ranges_by_label));
     }
 
   ranges_by_label[in_use].begin = begin;
@@ -10283,11 +10724,15 @@ output_line_info (bool prologue_only)
   ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, 0);
 
-  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
-    dw2_asm_output_data (4, 0xffffffff,
-      "Initial length escape value indicating 64-bit DWARF extension");
-  dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
-                       "Length of Source Line Info");
+  if (!XCOFF_DEBUGGING_INFO)
+    {
+      if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+       dw2_asm_output_data (4, 0xffffffff,
+         "Initial length escape value indicating 64-bit DWARF extension");
+      dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+                           "Length of Source Line Info");
+    }
+
   ASM_OUTPUT_LABEL (asm_out_file, l1);
 
   dw2_asm_output_data (2, ver, "DWARF Version");
@@ -10378,17 +10823,29 @@ output_line_info (bool prologue_only)
   ASM_OUTPUT_LABEL (asm_out_file, l2);
 }
 \f
+/* Return true if DW_AT_endianity should be emitted according to REVERSE.  */
+
+static inline bool
+need_endianity_attribute_p (bool reverse)
+{
+  return reverse && (dwarf_version >= 3 || !dwarf_strict);
+}
+
 /* Given a pointer to a tree node for some base type, return a pointer to
-   a DIE that describes the given type.
+   a DIE that describes the given type.  REVERSE is true if the type is
+   to be interpreted in the reverse storage order wrt the target order.
 
    This routine must only be called for GCC type nodes that correspond to
    Dwarf base (fundamental) types.  */
 
 static dw_die_ref
-base_type_die (tree type)
+base_type_die (tree type, bool reverse)
 {
   dw_die_ref base_type_result;
   enum dwarf_type encoding;
+  bool fpt_used = false;
+  struct fixed_point_type_info fpt_info;
+  tree type_bias = NULL_TREE;
 
   if (TREE_CODE (type) == ERROR_MARK || TREE_CODE (type) == VOID_TYPE)
     return 0;
@@ -10415,6 +10872,19 @@ base_type_die (tree type)
              break;
            }
        }
+      if ((dwarf_version >= 3 || !dwarf_strict)
+         && lang_hooks.types.get_fixed_point_type_info)
+       {
+         memset (&fpt_info, 0, sizeof (fpt_info));
+         if (lang_hooks.types.get_fixed_point_type_info (type, &fpt_info))
+           {
+             fpt_used = true;
+             encoding = ((TYPE_UNSIGNED (type))
+                         ? DW_ATE_unsigned_fixed
+                         : DW_ATE_signed_fixed);
+             break;
+           }
+       }
       if (TYPE_STRING_FLAG (type))
        {
          if (TYPE_UNSIGNED (type))
@@ -10426,6 +10896,10 @@ base_type_die (tree type)
        encoding = DW_ATE_unsigned;
       else
        encoding = DW_ATE_signed;
+
+      if (!dwarf_strict
+         && lang_hooks.types.get_type_bias)
+       type_bias = lang_hooks.types.get_type_bias (type);
       break;
 
     case REAL_TYPE:
@@ -10473,6 +10947,55 @@ 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);
+
+  if (need_endianity_attribute_p (reverse))
+    add_AT_unsigned (base_type_result, DW_AT_endianity,
+                    BYTES_BIG_ENDIAN ? DW_END_little : DW_END_big);
+
+  if (fpt_used)
+    {
+      switch (fpt_info.scale_factor_kind)
+       {
+       case fixed_point_scale_factor_binary:
+         add_AT_int (base_type_result, DW_AT_binary_scale,
+                     fpt_info.scale_factor.binary);
+         break;
+
+       case fixed_point_scale_factor_decimal:
+         add_AT_int (base_type_result, DW_AT_decimal_scale,
+                     fpt_info.scale_factor.decimal);
+         break;
+
+       case fixed_point_scale_factor_arbitrary:
+         /* Arbitrary scale factors cannot be described in standard DWARF,
+            yet.  */
+         if (!dwarf_strict)
+           {
+             /* Describe the scale factor as a rational constant.  */
+             const dw_die_ref scale_factor
+               = new_die (DW_TAG_constant, comp_unit_die (), type);
+
+             add_AT_unsigned (scale_factor, DW_AT_GNU_numerator,
+                              fpt_info.scale_factor.arbitrary.numerator);
+             add_AT_int (scale_factor, DW_AT_GNU_denominator,
+                         fpt_info.scale_factor.arbitrary.denominator);
+
+             add_AT_die_ref (base_type_result, DW_AT_small, scale_factor);
+           }
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+    }
+
+  if (type_bias)
+    add_scalar_info (base_type_result, DW_AT_GNU_bias, type_bias,
+                    dw_scalar_form_constant
+                    | dw_scalar_form_exprloc
+                    | dw_scalar_form_reference,
+                    NULL);
+
   add_pubtype (type, base_type_result);
 
   return base_type_result;
@@ -10574,7 +11097,8 @@ offset_int_type_size_in_bits (const_tree type)
     to a DIE that describes the given type.  */
 
 static dw_die_ref
-subrange_type_die (tree type, tree low, tree high, dw_die_ref context_die)
+subrange_type_die (tree type, tree low, tree high, tree bias,
+                  dw_die_ref context_die)
 {
   dw_die_ref subrange_die;
   const HOST_WIDE_INT size_in_bytes = int_size_in_bytes (type);
@@ -10595,6 +11119,12 @@ subrange_type_die (tree type, tree low, tree high, dw_die_ref context_die)
     add_bound_info (subrange_die, DW_AT_lower_bound, low, NULL);
   if (high)
     add_bound_info (subrange_die, DW_AT_upper_bound, high, NULL);
+  if (bias && !dwarf_strict)
+    add_scalar_info (subrange_die, DW_AT_GNU_bias, bias,
+                    dw_scalar_form_constant
+                    | dw_scalar_form_exprloc
+                    | dw_scalar_form_reference,
+                    NULL);
 
   return subrange_die;
 }
@@ -10607,6 +11137,10 @@ static int
 decl_quals (const_tree decl)
 {
   return ((TREE_READONLY (decl)
+          /* The C++ front-end correctly marks reference-typed
+             variables as readonly, but from a language (and debug
+             info) standpoint they are not const-qualified.  */
+          && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
           ? TYPE_QUAL_CONST : TYPE_UNQUALIFIED)
          | (TREE_THIS_VOLATILE (decl)
             ? TYPE_QUAL_VOLATILE : TYPE_UNQUALIFIED));
@@ -10646,11 +11180,53 @@ get_nearest_type_subqualifiers (tree type, int type_quals, int qual_mask)
   return best_qual;
 }
 
+struct dwarf_qual_info_t { int q; enum dwarf_tag t; };
+static const dwarf_qual_info_t dwarf_qual_info[] =
+{
+  { TYPE_QUAL_CONST, DW_TAG_const_type },
+  { TYPE_QUAL_VOLATILE, DW_TAG_volatile_type },
+  { TYPE_QUAL_RESTRICT, DW_TAG_restrict_type },
+  { TYPE_QUAL_ATOMIC, DW_TAG_atomic_type }
+};
+static const unsigned int dwarf_qual_info_size
+  = sizeof (dwarf_qual_info) / sizeof (dwarf_qual_info[0]);
+
+/* If DIE is a qualified DIE of some base DIE with the same parent,
+   return the base DIE, otherwise return NULL.  Set MASK to the
+   qualifiers added compared to the returned DIE.  */
+
+static dw_die_ref
+qualified_die_p (dw_die_ref die, int *mask, unsigned int depth)
+{
+  unsigned int i;
+  for (i = 0; i < dwarf_qual_info_size; i++)
+    if (die->die_tag == dwarf_qual_info[i].t)
+      break;
+  if (i == dwarf_qual_info_size)
+    return NULL;
+  if (vec_safe_length (die->die_attr) != 1)
+    return NULL;
+  dw_die_ref type = get_AT_ref (die, DW_AT_type);
+  if (type == NULL || type->die_parent != die->die_parent)
+    return NULL;
+  *mask |= dwarf_qual_info[i].q;
+  if (depth)
+    {
+      dw_die_ref ret = qualified_die_p (type, mask, depth - 1);
+      if (ret)
+       return ret;
+    }
+  return type;
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
-   entry that chains various modifiers in front of the given type.  */
+   entry that chains the modifiers specified by CV_QUALS in front of the
+   given type.  REVERSE is true if the type is to be interpreted in the
+   reverse storage order wrt the target order.  */
 
 static dw_die_ref
-modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
+modified_type_die (tree type, int cv_quals, bool reverse,
+                  dw_die_ref context_die)
 {
   enum tree_code code = TREE_CODE (type);
   dw_die_ref mod_type_die;
@@ -10666,6 +11242,14 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
   if (code == ERROR_MARK)
     return NULL;
 
+  if (lang_hooks.types.get_debug_type)
+    {
+      tree debug_type = lang_hooks.types.get_debug_type (type);
+
+      if (debug_type != NULL_TREE && debug_type != type)
+       return modified_type_die (debug_type, cv_quals, reverse, context_die);
+    }
+
   cv_quals &= cv_qual_mask;
 
   /* Don't emit DW_TAG_restrict_type for DWARFv2, since it is a type
@@ -10700,7 +11284,12 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
   if (qualified_type)
     {
       mod_type_die = lookup_type_die (qualified_type);
-      if (mod_type_die)
+
+      /* DW_AT_endianity doesn't come from a qualifier on the type.  */
+      if (mod_type_die
+         && (!need_endianity_attribute_p (reverse)
+             || !is_base_type (type)
+             || get_AT_unsigned (mod_type_die, DW_AT_endianity)))
        return mod_type_die;
     }
 
@@ -10726,8 +11315,8 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
              || (cv_quals == dquals && DECL_ORIGINAL_TYPE (name) != type))
            /* cv-unqualified version of named type.  Just use
               the unnamed type to which it refers.  */
-           return modified_type_die (DECL_ORIGINAL_TYPE (name),
-                                     cv_quals, context_die);
+           return modified_type_die (DECL_ORIGINAL_TYPE (name), cv_quals,
+                                     reverse, context_die);
          /* Else cv-qualified version of named type; fall through.  */
        }
     }
@@ -10736,66 +11325,145 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
 
   if (cv_quals)
     {
-      struct qual_info { int q; enum dwarf_tag t; };
-      static const struct qual_info qual_info[] =
-       {
-         { TYPE_QUAL_ATOMIC, DW_TAG_atomic_type },
-         { TYPE_QUAL_RESTRICT, DW_TAG_restrict_type },
-         { TYPE_QUAL_VOLATILE, DW_TAG_volatile_type },
-         { TYPE_QUAL_CONST, DW_TAG_const_type },
-       };
-      int sub_quals;
+      int sub_quals = 0, first_quals = 0;
       unsigned i;
+      dw_die_ref first = NULL, last = NULL;
 
       /* Determine a lesser qualified type that most closely matches
         this one.  Then generate DW_TAG_* entries for the remaining
         qualifiers.  */
       sub_quals = get_nearest_type_subqualifiers (type, cv_quals,
                                                  cv_qual_mask);
-      mod_type_die = modified_type_die (type, sub_quals, context_die);
+      if (sub_quals && use_debug_types)
+       {
+         bool needed = false;
+         /* If emitting type units, make sure the order of qualifiers
+            is canonical.  Thus, start from unqualified type if
+            an earlier qualifier is missing in sub_quals, but some later
+            one is present there.  */
+         for (i = 0; i < dwarf_qual_info_size; i++)
+           if (dwarf_qual_info[i].q & cv_quals & ~sub_quals)
+             needed = true;
+           else if (needed && (dwarf_qual_info[i].q & cv_quals))
+             {
+               sub_quals = 0;
+               break;
+             }
+       }
+      mod_type_die = modified_type_die (type, sub_quals, reverse, context_die);
+      if (mod_scope && mod_type_die && mod_type_die->die_parent == mod_scope)
+       {
+         /* As not all intermediate qualified DIEs have corresponding
+            tree types, ensure that qualified DIEs in the same scope
+            as their DW_AT_type are emitted after their DW_AT_type,
+            only with other qualified DIEs for the same type possibly
+            in between them.  Determine the range of such qualified
+            DIEs now (first being the base type, last being corresponding
+            last qualified DIE for it).  */
+         unsigned int count = 0;
+         first = qualified_die_p (mod_type_die, &first_quals,
+                                  dwarf_qual_info_size);
+         if (first == NULL)
+           first = mod_type_die;
+         gcc_assert ((first_quals & ~sub_quals) == 0);
+         for (count = 0, last = first;
+              count < (1U << dwarf_qual_info_size);
+              count++, last = last->die_sib)
+           {
+             int quals = 0;
+             if (last == mod_scope->die_child)
+               break;
+             if (qualified_die_p (last->die_sib, &quals, dwarf_qual_info_size)
+                 != first)
+               break;
+           }
+       }
 
-      for (i = 0; i < sizeof (qual_info) / sizeof (qual_info[0]); i++)
-       if (qual_info[i].q & cv_quals & ~sub_quals)
+      for (i = 0; i < dwarf_qual_info_size; i++)
+       if (dwarf_qual_info[i].q & cv_quals & ~sub_quals)
          {
-           dw_die_ref d = new_die (qual_info[i].t, mod_scope, type);
+           dw_die_ref d;
+           if (first && first != last)
+             {
+               for (d = first->die_sib; ; d = d->die_sib)
+                 {
+                   int quals = 0;
+                   qualified_die_p (d, &quals, dwarf_qual_info_size);
+                   if (quals == (first_quals | dwarf_qual_info[i].q))
+                     break;
+                   if (d == last)
+                     {
+                       d = NULL;
+                       break;
+                     }
+                 }
+               if (d)
+                 {
+                   mod_type_die = d;
+                   continue;
+                 }
+             }
+           if (first)
+             {
+               d = ggc_cleared_alloc<die_node> ();
+               d->die_tag = dwarf_qual_info[i].t;
+               add_child_die_after (mod_scope, d, last);
+               last = d;
+             }
+           else
+             d = new_die (dwarf_qual_info[i].t, mod_scope, type);
            if (mod_type_die)
              add_AT_die_ref (d, DW_AT_type, mod_type_die);
            mod_type_die = d;
+           first_quals |= dwarf_qual_info[i].q;
          }
     }
-  else if (code == POINTER_TYPE)
-    {
-      mod_type_die = new_die (DW_TAG_pointer_type, mod_scope, type);
-      add_AT_unsigned (mod_type_die, DW_AT_byte_size,
-                      simple_type_size_in_bits (type) / BITS_PER_UNIT);
-      item_type = TREE_TYPE (type);
-      if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type)))
-       add_AT_unsigned (mod_type_die, DW_AT_address_class,
-                        TYPE_ADDR_SPACE (item_type));
-    }
-  else if (code == REFERENCE_TYPE)
+  else if (code == POINTER_TYPE || code == REFERENCE_TYPE)
     {
-      if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
-       mod_type_die = new_die (DW_TAG_rvalue_reference_type, mod_scope,
-                               type);
-      else
-       mod_type_die = new_die (DW_TAG_reference_type, mod_scope, type);
+      dwarf_tag tag = DW_TAG_pointer_type;
+      if (code == REFERENCE_TYPE)
+       {
+         if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
+           tag = DW_TAG_rvalue_reference_type;
+         else
+           tag = DW_TAG_reference_type;
+       }
+      mod_type_die = new_die (tag, mod_scope, type);
+
       add_AT_unsigned (mod_type_die, DW_AT_byte_size,
                       simple_type_size_in_bits (type) / BITS_PER_UNIT);
       item_type = TREE_TYPE (type);
-      if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type)))
-       add_AT_unsigned (mod_type_die, DW_AT_address_class,
-                        TYPE_ADDR_SPACE (item_type));
+
+      addr_space_t as = TYPE_ADDR_SPACE (item_type);
+      if (!ADDR_SPACE_GENERIC_P (as))
+       {
+         int action = targetm.addr_space.debug (as);
+         if (action >= 0)
+           {
+             /* Positive values indicate an address_class.  */
+             add_AT_unsigned (mod_type_die, DW_AT_address_class, action);
+           }
+         else
+           {
+             /* Negative values indicate an (inverted) segment base reg.  */
+             dw_loc_descr_ref d
+               = one_reg_loc_descriptor (~action, VAR_INIT_STATUS_INITIALIZED);
+             add_AT_loc (mod_type_die, DW_AT_segment, d);
+           }
+       }
     }
   else if (code == INTEGER_TYPE
           && TREE_TYPE (type) != NULL_TREE
           && subrange_type_for_debug_p (type, &low, &high))
     {
-      mod_type_die = subrange_type_die (type, low, high, context_die);
+      tree bias = NULL_TREE;
+      if (lang_hooks.types.get_type_bias)
+       bias = lang_hooks.types.get_type_bias (type);
+      mod_type_die = subrange_type_die (type, low, high, bias, context_die);
       item_type = TREE_TYPE (type);
     }
   else if (is_base_type (type))
-    mod_type_die = base_type_die (type);
+    mod_type_die = base_type_die (type, reverse);
   else
     {
       gen_type_die (type, context_die);
@@ -10852,6 +11520,7 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
        types are possible in Ada.  */
     sub_die = modified_type_die (item_type,
                                 TYPE_QUALS_NO_ADDR_SPACE (item_type),
+                                reverse,
                                 context_die);
 
   if (sub_die != NULL)
@@ -10996,7 +11665,7 @@ generic_parameter_die (tree parm, tree arg,
          add_type_attribute (tmpl_die, tmpl_type,
                              (TREE_THIS_VOLATILE (tmpl_type)
                               ? TYPE_QUAL_VOLATILE : TYPE_UNQUALIFIED),
-                             parent_die);
+                             false, parent_die);
        }
       else
        {
@@ -11140,7 +11809,7 @@ reg_loc_descriptor (rtx rtl, enum var_init_status initialized)
 
   regs = targetm.dwarf_register_span (rtl);
 
-  if (hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)] > 1 || regs)
+  if (REG_NREGS (rtl) > 1 || regs)
     return multiple_reg_loc_descriptor (rtl, regs, initialized);
   else
     {
@@ -11197,7 +11866,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs,
 #endif
 
       gcc_assert ((unsigned) DBX_REGISTER_NUMBER (reg) == dbx_reg_number (rtl));
-      nregs = hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)];
+      nregs = REG_NREGS (rtl);
 
       size = GET_MODE_SIZE (GET_MODE (rtl)) / nregs;
 
@@ -11337,6 +12006,151 @@ int_loc_descriptor (HOST_WIDE_INT i)
   return new_loc_descr (op, i, 0);
 }
 
+/* Likewise, for unsigned constants.  */
+
+static dw_loc_descr_ref
+uint_loc_descriptor (unsigned HOST_WIDE_INT i)
+{
+  const unsigned HOST_WIDE_INT max_int = INTTYPE_MAXIMUM (HOST_WIDE_INT);
+  const unsigned HOST_WIDE_INT max_uint
+    = INTTYPE_MAXIMUM (unsigned HOST_WIDE_INT);
+
+  /* If possible, use the clever signed constants handling.  */
+  if (i <= max_int)
+    return int_loc_descriptor ((HOST_WIDE_INT) i);
+
+  /* Here, we are left with positive numbers that cannot be represented as
+     HOST_WIDE_INT, i.e.:
+         max (HOST_WIDE_INT) < i <= max (unsigned HOST_WIDE_INT)
+
+     Using DW_OP_const4/8/./u operation to encode them consumes a lot of bytes
+     whereas may be better to output a negative integer: thanks to integer
+     wrapping, we know that:
+         x = x - 2 ** DWARF2_ADDR_SIZE
+          = x - 2 * (max (HOST_WIDE_INT) + 1)
+     So numbers close to max (unsigned HOST_WIDE_INT) could be represented as
+     small negative integers.  Let's try that in cases it will clearly improve
+     the encoding: there is no gain turning DW_OP_const4u into
+     DW_OP_const4s.  */
+  if (DWARF2_ADDR_SIZE * 8 == HOST_BITS_PER_WIDE_INT
+      && ((DWARF2_ADDR_SIZE == 4 && i > max_uint - 0x8000)
+         || (DWARF2_ADDR_SIZE == 8 && i > max_uint - 0x80000000)))
+    {
+      const unsigned HOST_WIDE_INT first_shift = i - max_int - 1;
+
+      /* Now, -1 <  first_shift <= max (HOST_WIDE_INT)
+        i.e.  0 <= first_shift <= max (HOST_WIDE_INT).  */
+      const HOST_WIDE_INT second_shift
+        = (HOST_WIDE_INT) first_shift - (HOST_WIDE_INT) max_int - 1;
+
+      /* So we finally have:
+             -max (HOST_WIDE_INT) - 1 <= second_shift <= -1.
+        i.e.  min (HOST_WIDE_INT)     <= second_shift <  0.  */
+      return int_loc_descriptor (second_shift);
+    }
+
+  /* Last chance: fallback to a simple constant operation.  */
+  return new_loc_descr
+     ((HOST_BITS_PER_WIDE_INT == 32 || i <= 0xffffffff)
+      ? DW_OP_const4u
+      : DW_OP_const8u,
+      i, 0);
+}
+
+/* Generate and return a location description that computes the unsigned
+   comparison of the two stack top entries (a OP b where b is the top-most
+   entry and a is the second one).  The KIND of comparison can be LT_EXPR,
+   LE_EXPR, GT_EXPR or GE_EXPR.  */
+
+static dw_loc_descr_ref
+uint_comparison_loc_list (enum tree_code kind)
+{
+  enum dwarf_location_atom op, flip_op;
+  dw_loc_descr_ref ret, bra_node, jmp_node, tmp;
+
+  switch (kind)
+    {
+    case LT_EXPR:
+      op = DW_OP_lt;
+      break;
+    case LE_EXPR:
+      op = DW_OP_le;
+      break;
+    case GT_EXPR:
+      op = DW_OP_gt;
+      break;
+    case GE_EXPR:
+      op = DW_OP_ge;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  bra_node = new_loc_descr (DW_OP_bra, 0, 0);
+  jmp_node = new_loc_descr (DW_OP_skip, 0, 0);
+
+  /* Until DWARFv4, operations all work on signed integers.  It is nevertheless
+     possible to perform unsigned comparisons: we just have to distinguish
+     three cases:
+
+       1. when a and b have the same sign (as signed integers); then we should
+         return: a OP(signed) b;
+
+       2. when a is a negative signed integer while b is a positive one, then a
+         is a greater unsigned integer than b; likewise when a and b's roles
+         are flipped.
+
+     So first, compare the sign of the two operands.  */
+  ret = new_loc_descr (DW_OP_over, 0, 0);
+  add_loc_descr (&ret, new_loc_descr (DW_OP_over, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_xor, 0, 0));
+  /* If they have different signs (i.e. they have different sign bits), then
+     the stack top value has now the sign bit set and thus it's smaller than
+     zero.  */
+  add_loc_descr (&ret, new_loc_descr (DW_OP_lit0, 0, 0));
+  add_loc_descr (&ret, new_loc_descr (DW_OP_lt, 0, 0));
+  add_loc_descr (&ret, bra_node);
+
+  /* We are in case 1.  At this point, we know both operands have the same
+     sign, to it's safe to use the built-in signed comparison.  */
+  add_loc_descr (&ret, new_loc_descr (op, 0, 0));
+  add_loc_descr (&ret, jmp_node);
+
+  /* We are in case 2.  Here, we know both operands do not have the same sign,
+     so we have to flip the signed comparison.  */
+  flip_op = (kind == LT_EXPR || kind == LE_EXPR) ? DW_OP_gt : DW_OP_lt;
+  tmp = new_loc_descr (flip_op, 0, 0);
+  bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  bra_node->dw_loc_oprnd1.v.val_loc = tmp;
+  add_loc_descr (&ret, tmp);
+
+  /* This dummy operation is necessary to make the two branches join.  */
+  tmp = new_loc_descr (DW_OP_nop, 0, 0);
+  jmp_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
+  jmp_node->dw_loc_oprnd1.v.val_loc = tmp;
+  add_loc_descr (&ret, tmp);
+
+  return ret;
+}
+
+/* Likewise, but takes the location description lists (might be destructive on
+   them).  Return NULL if either is NULL or if concatenation fails.  */
+
+static dw_loc_list_ref
+loc_list_from_uint_comparison (dw_loc_list_ref left, dw_loc_list_ref right,
+                              enum tree_code kind)
+{
+  if (left == NULL || right == NULL)
+    return NULL;
+
+  add_loc_list (&left, right);
+  if (left == NULL)
+    return NULL;
+
+  add_loc_descr_to_each (left, uint_comparison_loc_list (kind));
+  return left;
+}
+
 /* Return size_of_locs (int_shift_loc_descriptor (i, shift))
    without actually allocating it.  */
 
@@ -11614,14 +12428,14 @@ const_ok_for_output_1 (rtx rtl)
     {
       /* If delegitimize_address couldn't do anything with the UNSPEC, assume
         we can't express it in the debug info.  */
-#ifdef ENABLE_CHECKING
       /* Don't complain about TLS UNSPECs, those are just too hard to
         delegitimize.  Note this could be a non-decl SYMBOL_REF such as
         one in a constant pool entry, so testing SYMBOL_REF_TLS_MODEL
         rather than DECL_THREAD_LOCAL_P is not just an optimization.  */
-      if (XVECLEN (rtl, 0) == 0
-         || GET_CODE (XVECEXP (rtl, 0, 0)) != SYMBOL_REF
-         || SYMBOL_REF_TLS_MODEL (XVECEXP (rtl, 0, 0)) == TLS_MODEL_NONE)
+      if (flag_checking
+         && (XVECLEN (rtl, 0) == 0
+             || GET_CODE (XVECEXP (rtl, 0, 0)) != SYMBOL_REF
+             || SYMBOL_REF_TLS_MODEL (XVECEXP (rtl, 0, 0)) == TLS_MODEL_NONE))
        inform (current_function_decl
                ? DECL_SOURCE_LOCATION (current_function_decl)
                : UNKNOWN_LOCATION,
@@ -11633,7 +12447,6 @@ const_ok_for_output_1 (rtx rtl)
 #else
                "non-delegitimized UNSPEC %d found in variable location",
                XINT (rtl, 1));
-#endif
 #endif
       expansion_failed (NULL_TREE, rtl,
                        "UNSPEC hasn't been delegitimized.\n");
@@ -11739,7 +12552,8 @@ base_type_for_mode (machine_mode mode, bool unsignedp)
     }
   type_die = lookup_type_die (type);
   if (!type_die)
-    type_die = modified_type_die (type, TYPE_UNQUALIFIED, comp_unit_die ());
+    type_die = modified_type_die (type, TYPE_UNQUALIFIED, false,
+                                 comp_unit_die ());
   if (type_die == NULL || type_die->die_tag != DW_TAG_base_type)
     return NULL;
   return type_die;
@@ -11806,7 +12620,7 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
     return NULL;
 
   if (dwarf_strict
-      && (GET_MODE_CLASS (op_mode) != MODE_INT
+      && (!SCALAR_INT_MODE_P (op_mode)
          || GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE))
     return NULL;
 
@@ -11818,7 +12632,7 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
   if (op0 == NULL || op1 == NULL)
     return NULL;
 
-  if (GET_MODE_CLASS (op_mode) != MODE_INT
+  if (!SCALAR_INT_MODE_P (op_mode)
       || GET_MODE_SIZE (op_mode) == DWARF2_ADDR_SIZE)
     return compare_loc_descriptor (op, op0, op1);
 
@@ -11913,7 +12727,7 @@ ucompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
     op_mode = GET_MODE (XEXP (rtl, 1));
   if (op_mode == VOIDmode)
     return NULL;
-  if (GET_MODE_CLASS (op_mode) != MODE_INT)
+  if (!SCALAR_INT_MODE_P (op_mode))
     return NULL;
 
   if (dwarf_strict && GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE)
@@ -11980,7 +12794,7 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
   dw_loc_descr_ref bra_node, drop_node;
 
   if (dwarf_strict
-      && (GET_MODE_CLASS (mode) != MODE_INT
+      && (!SCALAR_INT_MODE_P (mode)
          || GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE))
     return NULL;
 
@@ -12013,7 +12827,7 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
          add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst, bias, 0));
        }
     }
-  else if (GET_MODE_CLASS (mode) == MODE_INT
+  else if (!SCALAR_INT_MODE_P (mode)
           && GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE)
     {
       int shift = (DWARF2_ADDR_SIZE - GET_MODE_SIZE (mode)) * BITS_PER_UNIT;
@@ -12022,7 +12836,7 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
       add_loc_descr (&op1, int_loc_descriptor (shift));
       add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0));
     }
-  else if (GET_MODE_CLASS (mode) == MODE_INT
+  else if (SCALAR_INT_MODE_P (mode)
           && GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)
     {
       dw_die_ref type_die = base_type_for_mode (mode, 0);
@@ -12056,7 +12870,7 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
   bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
   bra_node->dw_loc_oprnd1.v.val_loc = drop_node;
   if ((GET_CODE (rtl) == SMIN || GET_CODE (rtl) == SMAX)
-      && GET_MODE_CLASS (mode) == MODE_INT
+      && SCALAR_INT_MODE_P (mode)
       && GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)
     ret = convert_descriptor_to_mode (mode, ret);
   return ret;
@@ -12135,7 +12949,7 @@ clz_loc_descriptor (rtx rtl, machine_mode mode,
   dw_loc_descr_ref l4jump, l4label;
   rtx msb;
 
-  if (GET_MODE_CLASS (mode) != MODE_INT
+  if (!SCALAR_INT_MODE_P (mode)
       || GET_MODE (XEXP (rtl, 0)) != mode)
     return NULL;
 
@@ -12177,7 +12991,7 @@ clz_loc_descriptor (rtx rtl, machine_mode mode,
   if (GET_CODE (rtl) != CLZ)
     msb = const1_rtx;
   else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
-    msb = GEN_INT ((unsigned HOST_WIDE_INT) 1
+    msb = GEN_INT (HOST_WIDE_INT_1U
                   << (GET_MODE_BITSIZE (mode) - 1));
   else
     msb = immed_wide_int_const
@@ -12243,7 +13057,7 @@ popcount_loc_descriptor (rtx rtl, machine_mode mode,
   dw_loc_descr_ref l1jump, l1label;
   dw_loc_descr_ref l2jump, l2label;
 
-  if (GET_MODE_CLASS (mode) != MODE_INT
+  if (!SCALAR_INT_MODE_P (mode)
       || GET_MODE (XEXP (rtl, 0)) != mode)
     return NULL;
 
@@ -12304,7 +13118,7 @@ bswap_loc_descriptor (rtx rtl, machine_mode mode,
   dw_loc_descr_ref l1jump, l1label;
   dw_loc_descr_ref l2jump, l2label;
 
-  if (GET_MODE_CLASS (mode) != MODE_INT
+  if (!SCALAR_INT_MODE_P (mode)
       || BITS_PER_UNIT != 8
       || (GET_MODE_BITSIZE (mode) != 32
          &&  GET_MODE_BITSIZE (mode) != 64))
@@ -12389,7 +13203,7 @@ rotate_loc_descriptor (rtx rtl, machine_mode mode,
   dw_loc_descr_ref op0, op1, ret, mask[2] = { NULL, NULL };
   int i;
 
-  if (GET_MODE_CLASS (mode) != MODE_INT)
+  if (!SCALAR_INT_MODE_P (mode))
     return NULL;
 
   if (GET_MODE (rtlop1) != VOIDmode
@@ -12535,11 +13349,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       if (!subreg_lowpart_p (rtl))
        break;
       inner = SUBREG_REG (rtl);
+      /* FALLTHRU */
     case TRUNCATE:
       if (inner == NULL_RTX)
         inner = XEXP (rtl, 0);
-      if (GET_MODE_CLASS (mode) == MODE_INT
-         && GET_MODE_CLASS (GET_MODE (inner)) == MODE_INT
+      if (SCALAR_INT_MODE_P (mode)
+         && SCALAR_INT_MODE_P (GET_MODE (inner))
          && (GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
 #ifdef POINTERS_EXTEND_UNSIGNED
              || (mode == Pmode && mem_mode != VOIDmode)
@@ -12557,8 +13372,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (inner)))
        break;
       if (GET_MODE_SIZE (mode) != GET_MODE_SIZE (GET_MODE (inner))
-         && (GET_MODE_CLASS (mode) != MODE_INT
-             || GET_MODE_CLASS (GET_MODE (inner)) != MODE_INT))
+         && (!SCALAR_INT_MODE_P (mode)
+             || !SCALAR_INT_MODE_P (GET_MODE (inner))))
        break;
       else
        {
@@ -12570,8 +13385,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
                                               mem_mode, initialized);
          if (mem_loc_result == NULL)
            break;
-         type_die = base_type_for_mode (mode,
-                                        GET_MODE_CLASS (mode) == MODE_INT);
+         type_die = base_type_for_mode (mode, SCALAR_INT_MODE_P (mode));
          if (type_die == NULL)
            {
              mem_loc_result = NULL;
@@ -12586,11 +13400,18 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
          cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
          cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
          add_loc_descr (&mem_loc_result, cvt);
+         if (SCALAR_INT_MODE_P (mode)
+             && GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE)
+           {
+             /* Convert it to untyped afterwards.  */
+             cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+             add_loc_descr (&mem_loc_result, cvt);
+           }
        }
       break;
 
     case REG:
-      if (GET_MODE_CLASS (mode) != MODE_INT
+      if (! SCALAR_INT_MODE_P (mode)
          || (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
              && rtl != arg_pointer_rtx
              && rtl != frame_pointer_rtx
@@ -12606,15 +13427,14 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
            break;
          if (REGNO (rtl) > FIRST_PSEUDO_REGISTER)
            break;
-         type_die = base_type_for_mode (mode,
-                                        GET_MODE_CLASS (mode) == MODE_INT);
+         type_die = base_type_for_mode (mode, SCALAR_INT_MODE_P (mode));
          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,
+          mem_loc_result = new_loc_descr (DW_OP_GNU_regval_type,
                                          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;
@@ -12650,7 +13470,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 
     case SIGN_EXTEND:
     case ZERO_EXTEND:
-      if (GET_MODE_CLASS (mode) != MODE_INT)
+      if (!SCALAR_INT_MODE_P (mode))
        break;
       op0 = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (XEXP (rtl, 0)),
                                mem_mode, VAR_INIT_STATUS_INITIALIZED);
@@ -12731,7 +13551,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       if (mem_loc_result != NULL)
        {
          if (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
-             || GET_MODE_CLASS (mode) != MODE_INT)
+             || !SCALAR_INT_MODE_P(mode))
            {
              dw_die_ref type_die;
              dw_loc_descr_ref deref;
@@ -12739,7 +13559,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
              if (dwarf_strict)
                return NULL;
              type_die
-               = base_type_for_mode (mode, GET_MODE_CLASS (mode) == MODE_INT);
+               = base_type_for_mode (mode, SCALAR_INT_MODE_P (mode));
              if (type_die == NULL)
                return NULL;
              deref = new_loc_descr (DW_OP_GNU_deref_type,
@@ -12767,8 +13587,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
         pool.  */
     case CONST:
     case SYMBOL_REF:
-      if ((GET_MODE_CLASS (mode) != MODE_INT
-          && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
+      if (!SCALAR_INT_MODE_P (mode)
          || (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
 #ifdef POINTERS_EXTEND_UNSIGNED
              && (mode != Pmode || mem_mode == VOIDmode)
@@ -12793,7 +13612,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
        }
 
       if (!const_ok_for_output (rtl))
-       break;
+       {
+         if (GET_CODE (rtl) == CONST)
+           mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
+                                                initialized);
+         break;
+       }
 
     symref:
       mem_loc_result = new_addr_loc_descr (rtl, dtprel_false);
@@ -12813,7 +13637,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
        return NULL;
       if (REG_P (ENTRY_VALUE_EXP (rtl)))
        {
-         if (GET_MODE_CLASS (mode) != MODE_INT
+         if (!SCALAR_INT_MODE_P (mode)
              || GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)
            op0 = mem_loc_descriptor (ENTRY_VALUE_EXP (rtl), mode,
                                      VOIDmode, VAR_INIT_STATUS_INITIALIZED);
@@ -12863,7 +13687,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
                                        : -GET_MODE_UNIT_SIZE (mem_mode),
                                        mode));
 
-      /* ... fall through ...  */
+      /* fall through */
 
     case PLUS:
     plus:
@@ -12871,7 +13695,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
          && (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)
+         && SCALAR_INT_MODE_P (mode))
        mem_loc_result = based_loc_descr (XEXP (rtl, 0),
                                          INTVAL (XEXP (rtl, 1)),
                                          VAR_INIT_STATUS_INITIALIZED);
@@ -12910,7 +13734,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 
     case DIV:
       if (!dwarf_strict
-         && GET_MODE_CLASS (mode) == MODE_INT
+         && SCALAR_INT_MODE_P (mode)
          && GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)
        {
          mem_loc_result = typed_binop (DW_OP_div, rtl,
@@ -12938,7 +13762,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       goto do_shift;
 
     do_shift:
-      if (GET_MODE_CLASS (mode) != MODE_INT)
+      if (!SCALAR_INT_MODE_P (mode))
        break;
       op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
                                VAR_INIT_STATUS_INITIALIZED);
@@ -13013,7 +13837,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       break;
 
     case UDIV:
-      if (!dwarf_strict && GET_MODE_CLASS (mode) == MODE_INT)
+      if (!dwarf_strict && SCALAR_INT_MODE_P (mode))
        {
          if (GET_MODE_CLASS (mode) > DWARF2_ADDR_SIZE)
            {
@@ -13121,8 +13945,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
              || (GET_MODE (rtl) == VOIDmode
                  && GET_MODE_BITSIZE (mode) != HOST_BITS_PER_DOUBLE_INT))
            break;
-         type_die = base_type_for_mode (mode,
-                                        GET_MODE_CLASS (mode) == MODE_INT);
+         type_die = base_type_for_mode (mode, SCALAR_INT_MODE_P (mode));
          if (type_die == NULL)
            return NULL;
          mem_loc_result = new_loc_descr (DW_OP_GNU_const_type, 0, 0);
@@ -13157,8 +13980,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
        {
          dw_die_ref type_die;
 
-         type_die = base_type_for_mode (mode,
-                                        GET_MODE_CLASS (mode) == MODE_INT);
+         type_die = base_type_for_mode (mode, SCALAR_INT_MODE_P (mode));
          if (type_die == NULL)
            return NULL;
          mem_loc_result = new_loc_descr (DW_OP_GNU_const_type, 0, 0);
@@ -13214,7 +14036,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 
     case UMIN:
     case UMAX:
-      if (GET_MODE_CLASS (mode) != MODE_INT)
+      if (!SCALAR_INT_MODE_P (mode))
        break;
       /* FALLTHRU */
     case SMIN:
@@ -13229,7 +14051,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
          && ((unsigned) INTVAL (XEXP (rtl, 1))
              + (unsigned) INTVAL (XEXP (rtl, 2))
              <= GET_MODE_BITSIZE (mode))
-         && GET_MODE_CLASS (mode) == MODE_INT
+         && SCALAR_INT_MODE_P (mode)
          && GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
          && GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0))) <= DWARF2_ADDR_SIZE)
        {
@@ -13306,7 +14128,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
                                    mem_mode, VAR_INIT_STATUS_INITIALIZED);
          if (op0 == NULL)
            break;
-         if (GET_MODE_CLASS (GET_MODE (XEXP (rtl, 0))) == MODE_INT
+         if (SCALAR_INT_MODE_P (GET_MODE (XEXP (rtl, 0)))
              && (GET_CODE (rtl) == FLOAT
                  || GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0)))
                     <= DWARF2_ADDR_SIZE))
@@ -13329,7 +14151,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
          cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
          cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
          add_loc_descr (&op0, cvt);
-         if (GET_MODE_CLASS (mode) == MODE_INT
+         if (SCALAR_INT_MODE_P (mode)
              && (GET_CODE (rtl) == FIX
                  || GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE))
            {
@@ -13416,12 +14238,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       goto symref;
 
     default:
-#ifdef ENABLE_CHECKING
-      print_rtl (stderr, rtl);
-      gcc_unreachable ();
-#else
+      if (flag_checking)
+       {
+         print_rtl (stderr, rtl);
+         gcc_unreachable ();
+       }
       break;
-#endif
     }
 
   if (mem_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
@@ -13759,7 +14581,8 @@ loc_descriptor (rtx rtl, machine_mode mode,
       /* FALLTHRU */
     do_default:
     default:
-      if ((GET_MODE_CLASS (mode) == MODE_INT && GET_MODE (rtl) == mode
+      if ((SCALAR_INT_MODE_P (mode)
+          && GET_MODE (rtl) == mode
           && GET_MODE_SIZE (GET_MODE (rtl)) <= DWARF2_ADDR_SIZE
           && dwarf_version >= 4)
          || (!dwarf_strict && mode != VOIDmode && mode != BLKmode))
@@ -14324,12 +15147,12 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev,
   tree obj, offset;
   HOST_WIDE_INT bitsize, bitpos, bytepos;
   machine_mode mode;
-  int unsignedp, volatilep = 0;
+  int unsignedp, reversep, volatilep = 0;
   dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
 
   obj = get_inner_reference (TREE_OPERAND (loc, 0),
                             &bitsize, &bitpos, &offset, &mode,
-                            &unsignedp, &volatilep, false);
+                            &unsignedp, &reversep, &volatilep);
   STRIP_NOPS (obj);
   if (bitpos % BITS_PER_UNIT)
     {
@@ -14377,6 +15200,68 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev,
   return list_ret;
 }
 
+/* Set LOC to the next operation that is not a DW_OP_nop operation. In the case
+   all operations from LOC are nops, move to the last one.  Insert in NOPS all
+   operations that are skipped.  */
+
+static void
+loc_descr_to_next_no_nop (dw_loc_descr_ref &loc,
+                         hash_set<dw_loc_descr_ref> &nops)
+{
+  while (loc->dw_loc_next != NULL && loc->dw_loc_opc == DW_OP_nop)
+    {
+      nops.add (loc);
+      loc = loc->dw_loc_next;
+    }
+}
+
+/* Helper for loc_descr_without_nops: free the location description operation
+   P.  */
+
+bool
+free_loc_descr (const dw_loc_descr_ref &loc, void *data ATTRIBUTE_UNUSED)
+{
+  ggc_free (loc);
+  return true;
+}
+
+/* Remove all DW_OP_nop operations from LOC except, if it exists, the one that
+   finishes LOC.  */
+
+static void
+loc_descr_without_nops (dw_loc_descr_ref &loc)
+{
+  if (loc->dw_loc_opc == DW_OP_nop && loc->dw_loc_next == NULL)
+    return;
+
+  /* Set of all DW_OP_nop operations we remove.  */
+  hash_set<dw_loc_descr_ref> nops;
+
+  /* First, strip all prefix NOP operations in order to keep the head of the
+     operations list.  */
+  loc_descr_to_next_no_nop (loc, nops);
+
+  for (dw_loc_descr_ref cur = loc; cur != NULL;)
+    {
+      /* For control flow operations: strip "prefix" nops in destination
+        labels.  */
+      if (cur->dw_loc_oprnd1.val_class == dw_val_class_loc)
+       loc_descr_to_next_no_nop (cur->dw_loc_oprnd1.v.val_loc, nops);
+      if (cur->dw_loc_oprnd2.val_class == dw_val_class_loc)
+       loc_descr_to_next_no_nop (cur->dw_loc_oprnd2.v.val_loc, nops);
+
+      /* Do the same for the operations that follow, then move to the next
+        iteration.  */
+      if (cur->dw_loc_next != NULL)
+       loc_descr_to_next_no_nop (cur->dw_loc_next, nops);
+      cur = cur->dw_loc_next;
+    }
+
+  nops.traverse<void *, free_loc_descr> (NULL);
+}
+
+
+struct dwarf_procedure_info;
 
 /* Helper structure for location descriptions generation.  */
 struct loc_descr_context
@@ -14388,58 +15273,525 @@ struct loc_descr_context
   /* The ..._DECL node that should be translated as a
      DW_OP_push_object_address operation.  */
   tree base_decl;
+  /* Information about the DWARF procedure we are currently generating. NULL if
+     we are not generating a DWARF procedure.  */
+  struct dwarf_procedure_info *dpi;
 };
 
-/* Generate Dwarf location list representing LOC.
-   If WANT_ADDRESS is false, expression computing LOC will be computed
-   If WANT_ADDRESS is 1, expression computing address of LOC will be returned
-   if WANT_ADDRESS is 2, expression computing address useable in location
-     will be returned (i.e. DW_OP_reg can be used
-     to refer to register values).
+/* DWARF procedures generation
 
-   CONTEXT provides information to customize the location descriptions
-   generation.  Its context_type field specifies what type is implicitly
-   referenced by DW_OP_push_object_address.  If it is NULL_TREE, this operation
-   will not be generated.
+   DWARF expressions (aka. location descriptions) are used to encode variable
+   things such as sizes or offsets.  Such computations can have redundant parts
+   that can be factorized in order to reduce the size of the output debug
+   information.  This is the whole point of DWARF procedures.
 
-   If CONTEXT is NULL, the behavior is the same as if both context_type and
-   base_decl fields were NULL_TREE.  */
+   Thanks to stor-layout.c, size and offset expressions in GENERIC trees are
+   already factorized into functions ("size functions") in order to handle very
+   big and complex types.  Such functions are quite simple: they have integral
+   arguments, they return an integral result and their body contains only a
+   return statement with arithmetic expressions.  This is the only kind of
+   function we are interested in translating into DWARF procedures, here.
 
-static dw_loc_list_ref
-loc_list_from_tree (tree loc, int want_address,
-                   const struct loc_descr_context *context)
+   DWARF expressions and DWARF procedure are executed using a stack, so we have
+   to define some calling convention for them to interact.  Let's say that:
+
+   - Before calling a DWARF procedure, DWARF expressions must push on the stack
+     all arguments in reverse order (right-to-left) so that when the DWARF
+     procedure execution starts, the first argument is the top of the stack.
+
+   - Then, when returning, the DWARF procedure must have consumed all arguments
+     on the stack, must have pushed the result and touched nothing else.
+
+   - Each integral argument and the result are integral types can be hold in a
+     single stack slot.
+
+   - We call "frame offset" the number of stack slots that are "under DWARF
+     procedure control": it includes the arguments slots, the temporaries and
+     the result slot. Thus, it is equal to the number of arguments when the
+     procedure execution starts and must be equal to one (the result) when it
+     returns.  */
+
+/* Helper structure used when generating operations for a DWARF procedure.  */
+struct dwarf_procedure_info
 {
-  dw_loc_descr_ref ret = NULL, ret1 = NULL;
-  dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
-  int have_address = 0;
-  enum dwarf_location_atom op;
+  /* The FUNCTION_DECL node corresponding to the DWARF procedure that is
+     currently translated.  */
+  tree fndecl;
+  /* The number of arguments FNDECL takes.  */
+  unsigned args_count;
+};
 
-  /* ??? Most of the time we do not take proper care for sign/zero
-     extending the values properly.  Hopefully this won't be a real
-     problem...  */
+/* Return a pointer to a newly created DIE node for a DWARF procedure.  Add
+   LOCATION as its DW_AT_location attribute.  If FNDECL is not NULL_TREE,
+   equate it to this DIE.  */
 
-  if (context != NULL
-      && context->base_decl == loc
-      && want_address == 0)
-    {
-      if (dwarf_version >= 3 || !dwarf_strict)
-       return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0),
-                            NULL, NULL, NULL);
-      else
-       return NULL;
-    }
+static dw_die_ref
+new_dwarf_proc_die (dw_loc_descr_ref location, tree fndecl,
+                   dw_die_ref parent_die)
+{
+  dw_die_ref dwarf_proc_die;
 
-  switch (TREE_CODE (loc))
-    {
-    case ERROR_MARK:
-      expansion_failed (loc, NULL_RTX, "ERROR_MARK");
-      return 0;
+  if ((dwarf_version < 3 && dwarf_strict)
+      || location == NULL)
+    return NULL;
 
-    case PLACEHOLDER_EXPR:
-      /* This case involves extracting fields from an object to determine the
-        position of other fields. It is supposed to appear only as the first
-         operand of COMPONENT_REF nodes and to reference precisely the type
-         that the context allows.  */
+  dwarf_proc_die = new_die (DW_TAG_dwarf_procedure, parent_die, fndecl);
+  if (fndecl)
+    equate_decl_number_to_die (fndecl, dwarf_proc_die);
+  add_AT_loc (dwarf_proc_die, DW_AT_location, location);
+  return dwarf_proc_die;
+}
+
+/* Return whether TYPE is a supported type as a DWARF procedure argument
+   type or return type (we handle only scalar types and pointer types that
+   aren't wider than the DWARF expression evaluation stack.  */
+
+static bool
+is_handled_procedure_type (tree type)
+{
+  return ((INTEGRAL_TYPE_P (type)
+          || TREE_CODE (type) == OFFSET_TYPE
+          || TREE_CODE (type) == POINTER_TYPE)
+         && int_size_in_bytes (type) <= DWARF2_ADDR_SIZE);
+}
+
+/* Helper for resolve_args_picking: do the same but stop when coming across
+   visited nodes.  For each node we visit, register in FRAME_OFFSETS the frame
+   offset *before* evaluating the corresponding operation.  */
+
+static bool
+resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset,
+                       struct dwarf_procedure_info *dpi,
+                       hash_map<dw_loc_descr_ref, unsigned> &frame_offsets)
+{
+  /* The "frame_offset" identifier is already used to name a macro... */
+  unsigned frame_offset_ = initial_frame_offset;
+  dw_loc_descr_ref l;
+
+  for (l = loc; l != NULL;)
+    {
+      bool existed;
+      unsigned &l_frame_offset = frame_offsets.get_or_insert (l, &existed);
+
+      /* If we already met this node, there is nothing to compute anymore.  */
+      if (existed)
+       {
+         /* Make sure that the stack size is consistent wherever the execution
+            flow comes from.  */
+         gcc_assert ((unsigned) l_frame_offset == frame_offset_);
+         break;
+       }
+      l_frame_offset = frame_offset_;
+
+      /* If needed, relocate the picking offset with respect to the frame
+        offset. */
+      if (l->dw_loc_opc == DW_OP_pick && l->frame_offset_rel)
+       {
+         /* frame_offset_ is the size of the current stack frame, including
+            incoming arguments. Besides, the arguments are pushed
+            right-to-left.  Thus, in order to access the Nth argument from
+            this operation node, the picking has to skip temporaries *plus*
+            one stack slot per argument (0 for the first one, 1 for the second
+            one, etc.).
+
+            The targetted argument number (N) is already set as the operand,
+            and the number of temporaries can be computed with:
+              frame_offsets_ - dpi->args_count */
+         l->dw_loc_oprnd1.v.val_unsigned += frame_offset_ - dpi->args_count;
+
+         /* DW_OP_pick handles only offsets from 0 to 255 (inclusive)...  */
+         if (l->dw_loc_oprnd1.v.val_unsigned > 255)
+           return false;
+       }
+
+      /* Update frame_offset according to the effect the current operation has
+        on the stack.  */
+      switch (l->dw_loc_opc)
+       {
+       case DW_OP_deref:
+       case DW_OP_swap:
+       case DW_OP_rot:
+       case DW_OP_abs:
+       case DW_OP_neg:
+       case DW_OP_not:
+       case DW_OP_plus_uconst:
+       case DW_OP_skip:
+       case DW_OP_reg0:
+       case DW_OP_reg1:
+       case DW_OP_reg2:
+       case DW_OP_reg3:
+       case DW_OP_reg4:
+       case DW_OP_reg5:
+       case DW_OP_reg6:
+       case DW_OP_reg7:
+       case DW_OP_reg8:
+       case DW_OP_reg9:
+       case DW_OP_reg10:
+       case DW_OP_reg11:
+       case DW_OP_reg12:
+       case DW_OP_reg13:
+       case DW_OP_reg14:
+       case DW_OP_reg15:
+       case DW_OP_reg16:
+       case DW_OP_reg17:
+       case DW_OP_reg18:
+       case DW_OP_reg19:
+       case DW_OP_reg20:
+       case DW_OP_reg21:
+       case DW_OP_reg22:
+       case DW_OP_reg23:
+       case DW_OP_reg24:
+       case DW_OP_reg25:
+       case DW_OP_reg26:
+       case DW_OP_reg27:
+       case DW_OP_reg28:
+       case DW_OP_reg29:
+       case DW_OP_reg30:
+       case DW_OP_reg31:
+       case DW_OP_bregx:
+       case DW_OP_piece:
+       case DW_OP_deref_size:
+       case DW_OP_nop:
+       case DW_OP_form_tls_address:
+       case DW_OP_bit_piece:
+       case DW_OP_implicit_value:
+       case DW_OP_stack_value:
+         break;
+
+       case DW_OP_addr:
+       case DW_OP_const1u:
+       case DW_OP_const1s:
+       case DW_OP_const2u:
+       case DW_OP_const2s:
+       case DW_OP_const4u:
+       case DW_OP_const4s:
+       case DW_OP_const8u:
+       case DW_OP_const8s:
+       case DW_OP_constu:
+       case DW_OP_consts:
+       case DW_OP_dup:
+       case DW_OP_over:
+       case DW_OP_pick:
+       case DW_OP_lit0:
+       case DW_OP_lit1:
+       case DW_OP_lit2:
+       case DW_OP_lit3:
+       case DW_OP_lit4:
+       case DW_OP_lit5:
+       case DW_OP_lit6:
+       case DW_OP_lit7:
+       case DW_OP_lit8:
+       case DW_OP_lit9:
+       case DW_OP_lit10:
+       case DW_OP_lit11:
+       case DW_OP_lit12:
+       case DW_OP_lit13:
+       case DW_OP_lit14:
+       case DW_OP_lit15:
+       case DW_OP_lit16:
+       case DW_OP_lit17:
+       case DW_OP_lit18:
+       case DW_OP_lit19:
+       case DW_OP_lit20:
+       case DW_OP_lit21:
+       case DW_OP_lit22:
+       case DW_OP_lit23:
+       case DW_OP_lit24:
+       case DW_OP_lit25:
+       case DW_OP_lit26:
+       case DW_OP_lit27:
+       case DW_OP_lit28:
+       case DW_OP_lit29:
+       case DW_OP_lit30:
+       case DW_OP_lit31:
+       case DW_OP_breg0:
+       case DW_OP_breg1:
+       case DW_OP_breg2:
+       case DW_OP_breg3:
+       case DW_OP_breg4:
+       case DW_OP_breg5:
+       case DW_OP_breg6:
+       case DW_OP_breg7:
+       case DW_OP_breg8:
+       case DW_OP_breg9:
+       case DW_OP_breg10:
+       case DW_OP_breg11:
+       case DW_OP_breg12:
+       case DW_OP_breg13:
+       case DW_OP_breg14:
+       case DW_OP_breg15:
+       case DW_OP_breg16:
+       case DW_OP_breg17:
+       case DW_OP_breg18:
+       case DW_OP_breg19:
+       case DW_OP_breg20:
+       case DW_OP_breg21:
+       case DW_OP_breg22:
+       case DW_OP_breg23:
+       case DW_OP_breg24:
+       case DW_OP_breg25:
+       case DW_OP_breg26:
+       case DW_OP_breg27:
+       case DW_OP_breg28:
+       case DW_OP_breg29:
+       case DW_OP_breg30:
+       case DW_OP_breg31:
+       case DW_OP_fbreg:
+       case DW_OP_push_object_address:
+       case DW_OP_call_frame_cfa:
+         ++frame_offset_;
+         break;
+
+       case DW_OP_drop:
+       case DW_OP_xderef:
+       case DW_OP_and:
+       case DW_OP_div:
+       case DW_OP_minus:
+       case DW_OP_mod:
+       case DW_OP_mul:
+       case DW_OP_or:
+       case DW_OP_plus:
+       case DW_OP_shl:
+       case DW_OP_shr:
+       case DW_OP_shra:
+       case DW_OP_xor:
+       case DW_OP_bra:
+       case DW_OP_eq:
+       case DW_OP_ge:
+       case DW_OP_gt:
+       case DW_OP_le:
+       case DW_OP_lt:
+       case DW_OP_ne:
+       case DW_OP_regx:
+       case DW_OP_xderef_size:
+         --frame_offset_;
+         break;
+
+       case DW_OP_call2:
+       case DW_OP_call4:
+       case DW_OP_call_ref:
+         {
+           dw_die_ref dwarf_proc = l->dw_loc_oprnd1.v.val_die_ref.die;
+           int *stack_usage = dwarf_proc_stack_usage_map->get (dwarf_proc);
+
+           if (stack_usage == NULL)
+             return false;
+           frame_offset_ += *stack_usage;
+           break;
+         }
+
+       case DW_OP_GNU_push_tls_address:
+       case DW_OP_GNU_uninit:
+       case DW_OP_GNU_encoded_addr:
+       case DW_OP_GNU_implicit_pointer:
+       case DW_OP_GNU_entry_value:
+       case DW_OP_GNU_const_type:
+       case DW_OP_GNU_regval_type:
+       case DW_OP_GNU_deref_type:
+       case DW_OP_GNU_convert:
+       case DW_OP_GNU_reinterpret:
+       case DW_OP_GNU_parameter_ref:
+         /* loc_list_from_tree will probably not output these operations for
+            size functions, so assume they will not appear here.  */
+         /* Fall through...  */
+
+       default:
+         gcc_unreachable ();
+       }
+
+      /* Now, follow the control flow (except subroutine calls).  */
+      switch (l->dw_loc_opc)
+       {
+       case DW_OP_bra:
+         if (!resolve_args_picking_1 (l->dw_loc_next, frame_offset_, dpi,
+                                      frame_offsets))
+           return false;
+         /* Fall through. */
+
+       case DW_OP_skip:
+         l = l->dw_loc_oprnd1.v.val_loc;
+         break;
+
+       case DW_OP_stack_value:
+         return true;
+
+       default:
+         l = l->dw_loc_next;
+         break;
+       }
+    }
+
+  return true;
+}
+
+/* Make a DFS over operations reachable through LOC (i.e. follow branch
+   operations) in order to resolve the operand of DW_OP_pick operations that
+   target DWARF procedure arguments (DPI).  INITIAL_FRAME_OFFSET is the frame
+   offset *before* LOC is executed.  Return if all relocations were
+   successful.  */
+
+static bool
+resolve_args_picking (dw_loc_descr_ref loc, unsigned initial_frame_offset,
+                     struct dwarf_procedure_info *dpi)
+{
+  /* Associate to all visited operations the frame offset *before* evaluating
+     this operation.  */
+  hash_map<dw_loc_descr_ref, unsigned> frame_offsets;
+
+  return resolve_args_picking_1 (loc, initial_frame_offset, dpi,
+                                frame_offsets);
+}
+
+/* Try to generate a DWARF procedure that computes the same result as FNDECL.
+   Return NULL if it is not possible.  */
+
+static dw_die_ref
+function_to_dwarf_procedure (tree fndecl)
+{
+  struct loc_descr_context ctx;
+  struct dwarf_procedure_info dpi;
+  dw_die_ref dwarf_proc_die;
+  tree tree_body = DECL_SAVED_TREE (fndecl);
+  dw_loc_descr_ref loc_body, epilogue;
+
+  tree cursor;
+  unsigned i;
+
+  /* Do not generate multiple DWARF procedures for the same function
+     declaration.  */
+  dwarf_proc_die = lookup_decl_die (fndecl);
+  if (dwarf_proc_die != NULL)
+    return dwarf_proc_die;
+
+  /* DWARF procedures are available starting with the DWARFv3 standard.  */
+  if (dwarf_version < 3 && dwarf_strict)
+    return NULL;
+
+  /* We handle only functions for which we still have a body, that return a
+     supported type and that takes arguments with supported types.  Note that
+     there is no point translating functions that return nothing.  */
+  if (tree_body == NULL_TREE
+      || DECL_RESULT (fndecl) == NULL_TREE
+      || !is_handled_procedure_type (TREE_TYPE (DECL_RESULT (fndecl))))
+    return NULL;
+
+  for (cursor = DECL_ARGUMENTS (fndecl);
+       cursor != NULL_TREE;
+       cursor = TREE_CHAIN (cursor))
+    if (!is_handled_procedure_type (TREE_TYPE (cursor)))
+      return NULL;
+
+  /* Match only "expr" in: RETURN_EXPR (MODIFY_EXPR (RESULT_DECL, expr)).  */
+  if (TREE_CODE (tree_body) != RETURN_EXPR)
+    return NULL;
+  tree_body = TREE_OPERAND (tree_body, 0);
+  if (TREE_CODE (tree_body) != MODIFY_EXPR
+      || TREE_OPERAND (tree_body, 0) != DECL_RESULT (fndecl))
+    return NULL;
+  tree_body = TREE_OPERAND (tree_body, 1);
+
+  /* Try to translate the body expression itself.  Note that this will probably
+     cause an infinite recursion if its call graph has a cycle.  This is very
+     unlikely for size functions, however, so don't bother with such things at
+     the moment.  */
+  ctx.context_type = NULL_TREE;
+  ctx.base_decl = NULL_TREE;
+  ctx.dpi = &dpi;
+  dpi.fndecl = fndecl;
+  dpi.args_count = list_length (DECL_ARGUMENTS (fndecl));
+  loc_body = loc_descriptor_from_tree (tree_body, 0, &ctx);
+  if (!loc_body)
+    return NULL;
+
+  /* After evaluating all operands in "loc_body", we should still have on the
+     stack all arguments plus the desired function result (top of the stack).
+     Generate code in order to keep only the result in our stack frame.  */
+  epilogue = NULL;
+  for (i = 0; i < dpi.args_count; ++i)
+    {
+      dw_loc_descr_ref op_couple = new_loc_descr (DW_OP_swap, 0, 0);
+      op_couple->dw_loc_next = new_loc_descr (DW_OP_drop, 0, 0);
+      op_couple->dw_loc_next->dw_loc_next = epilogue;
+      epilogue = op_couple;
+    }
+  add_loc_descr (&loc_body, epilogue);
+  if (!resolve_args_picking (loc_body, dpi.args_count, &dpi))
+    return NULL;
+
+  /* Trailing nops from loc_descriptor_from_tree (if any) cannot be removed
+     because they are considered useful.  Now there is an epilogue, they are
+     not anymore, so give it another try.   */
+  loc_descr_without_nops (loc_body);
+
+  /* fndecl may be used both as a regular DW_TAG_subprogram DIE and as
+     a DW_TAG_dwarf_procedure, so we may have a conflict, here.  It's unlikely,
+     though, given that size functions do not come from source, so they should
+     not have a dedicated DW_TAG_subprogram DIE.  */
+  dwarf_proc_die
+    = new_dwarf_proc_die (loc_body, fndecl,
+                         get_context_die (DECL_CONTEXT (fndecl)));
+
+  /* The called DWARF procedure consumes one stack slot per argument and
+     returns one stack slot.  */
+  dwarf_proc_stack_usage_map->put (dwarf_proc_die, 1 - dpi.args_count);
+
+  return dwarf_proc_die;
+}
+
+
+/* Generate Dwarf location list representing LOC.
+   If WANT_ADDRESS is false, expression computing LOC will be computed
+   If WANT_ADDRESS is 1, expression computing address of LOC will be returned
+   if WANT_ADDRESS is 2, expression computing address useable in location
+     will be returned (i.e. DW_OP_reg can be used
+     to refer to register values).
+
+   CONTEXT provides information to customize the location descriptions
+   generation.  Its context_type field specifies what type is implicitly
+   referenced by DW_OP_push_object_address.  If it is NULL_TREE, this operation
+   will not be generated.
+
+   Its DPI field determines whether we are generating a DWARF expression for a
+   DWARF procedure, so PARM_DECL references are processed specifically.
+
+   If CONTEXT is NULL, the behavior is the same as if context_type, base_decl
+   and dpi fields were null.  */
+
+static dw_loc_list_ref
+loc_list_from_tree_1 (tree loc, int want_address,
+                     const struct loc_descr_context *context)
+{
+  dw_loc_descr_ref ret = NULL, ret1 = NULL;
+  dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
+  int have_address = 0;
+  enum dwarf_location_atom op;
+
+  /* ??? Most of the time we do not take proper care for sign/zero
+     extending the values properly.  Hopefully this won't be a real
+     problem...  */
+
+  if (context != NULL
+      && context->base_decl == loc
+      && want_address == 0)
+    {
+      if (dwarf_version >= 3 || !dwarf_strict)
+       return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0),
+                            NULL, NULL, NULL);
+      else
+       return NULL;
+    }
+
+  switch (TREE_CODE (loc))
+    {
+    case ERROR_MARK:
+      expansion_failed (loc, NULL_RTX, "ERROR_MARK");
+      return 0;
+
+    case PLACEHOLDER_EXPR:
+      /* This case involves extracting fields from an object to determine the
+        position of other fields. It is supposed to appear only as the first
+         operand of COMPONENT_REF nodes and to reference precisely the type
+         that the context allows.  */
       if (context != NULL
           && TREE_TYPE (loc) == context->context_type
          && want_address >= 1)
@@ -14459,9 +15811,49 @@ loc_list_from_tree (tree loc, int want_address,
       break;
 
     case CALL_EXPR:
-      expansion_failed (loc, NULL_RTX, "CALL_EXPR");
-      /* There are no opcodes for these operations.  */
-      return 0;
+       {
+         const int nargs = call_expr_nargs (loc);
+         tree callee = get_callee_fndecl (loc);
+         int i;
+         dw_die_ref dwarf_proc;
+
+         if (callee == NULL_TREE)
+           goto call_expansion_failed;
+
+         /* We handle only functions that return an integer.  */
+         if (!is_handled_procedure_type (TREE_TYPE (TREE_TYPE (callee))))
+           goto call_expansion_failed;
+
+         dwarf_proc = function_to_dwarf_procedure (callee);
+         if (dwarf_proc == NULL)
+           goto call_expansion_failed;
+
+         /* Evaluate arguments right-to-left so that the first argument will
+            be the top-most one on the stack.  */
+         for (i = nargs - 1; i >= 0; --i)
+           {
+             dw_loc_descr_ref loc_descr
+               = loc_descriptor_from_tree (CALL_EXPR_ARG (loc, i), 0,
+                                           context);
+
+             if (loc_descr == NULL)
+               goto call_expansion_failed;
+
+             add_loc_descr (&ret, loc_descr);
+           }
+
+         ret1 = new_loc_descr (DW_OP_call4, 0, 0);
+         ret1->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+         ret1->dw_loc_oprnd1.v.val_die_ref.die = dwarf_proc;
+         ret1->dw_loc_oprnd1.v.val_die_ref.external = 0;
+         add_loc_descr (&ret, ret1);
+         break;
+
+       call_expansion_failed:
+         expansion_failed (loc, NULL_RTX, "CALL_EXPR");
+         /* There are no opcodes for these operations.  */
+         return 0;
+       }
 
     case PREINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
@@ -14486,7 +15878,7 @@ loc_list_from_tree (tree loc, int want_address,
        }
         /* Otherwise, process the argument and look for the address.  */
       if (!list_ret && !ret)
-        list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1, context);
+        list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 1, context);
       else
        {
          if (want_address)
@@ -14553,10 +15945,34 @@ loc_list_from_tree (tree loc, int want_address,
       /* FALLTHRU */
 
     case PARM_DECL:
+      if (context != NULL && context->dpi != NULL
+         && DECL_CONTEXT (loc) == context->dpi->fndecl)
+       {
+         /* We are generating code for a DWARF procedure and we want to access
+            one of its arguments: find the appropriate argument offset and let
+            the resolve_args_picking pass compute the offset that complies
+            with the stack frame size.  */
+         unsigned i = 0;
+         tree cursor;
+
+         for (cursor = DECL_ARGUMENTS (context->dpi->fndecl);
+              cursor != NULL_TREE && cursor != loc;
+              cursor = TREE_CHAIN (cursor), ++i)
+           ;
+         /* If we are translating a DWARF procedure, all referenced parameters
+            must belong to the current function.  */
+         gcc_assert (cursor != NULL_TREE);
+
+         ret = new_loc_descr (DW_OP_pick, i, 0);
+         ret->frame_offset_rel = 1;
+         break;
+       }
+      /* FALLTHRU */
+
     case RESULT_DECL:
       if (DECL_HAS_VALUE_EXPR_P (loc))
-       return loc_list_from_tree (DECL_VALUE_EXPR (loc),
-                                  want_address, context);
+       return loc_list_from_tree_1 (DECL_VALUE_EXPR (loc),
+                                    want_address, context);
       /* FALLTHRU */
 
     case FUNCTION_DECL:
@@ -14630,22 +16046,26 @@ loc_list_from_tree (tree loc, int want_address,
        }
       /* Fallthru.  */
     case INDIRECT_REF:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+      list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context);
       have_address = 1;
       break;
 
     case TARGET_MEM_REF:
     case SSA_NAME:
+    case DEBUG_EXPR_DECL:
       return NULL;
 
     case COMPOUND_EXPR:
-      return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address, context);
+      return loc_list_from_tree_1 (TREE_OPERAND (loc, 1), want_address,
+                                  context);
 
     CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
     case SAVE_EXPR:
     case MODIFY_EXPR:
-      return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address, context);
+    case NON_LVALUE_EXPR:
+      return loc_list_from_tree_1 (TREE_OPERAND (loc, 0), want_address,
+                                  context);
 
     case COMPONENT_REF:
     case BIT_FIELD_REF:
@@ -14657,17 +16077,17 @@ loc_list_from_tree (tree loc, int want_address,
        tree obj, offset;
        HOST_WIDE_INT bitsize, bitpos, bytepos;
        machine_mode mode;
-       int unsignedp, volatilep = 0;
+       int unsignedp, reversep, volatilep = 0;
 
        obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
-                                  &unsignedp, &volatilep, false);
+                                  &unsignedp, &reversep, &volatilep);
 
        gcc_assert (obj != loc);
 
-       list_ret = loc_list_from_tree (obj,
-                                      want_address == 2
-                                      && !bitpos && !offset ? 2 : 1,
-                                      context);
+       list_ret = loc_list_from_tree_1 (obj,
+                                        want_address == 2
+                                        && !bitpos && !offset ? 2 : 1,
+                                        context);
        /* TODO: We can extract value of the small expression via shifting even
           for nonzero bitpos.  */
        if (list_ret == 0)
@@ -14682,7 +16102,7 @@ loc_list_from_tree (tree loc, int want_address,
        if (offset != NULL_TREE)
          {
            /* Variable offset.  */
-           list_ret1 = loc_list_from_tree (offset, 0, context);
+           list_ret1 = loc_list_from_tree_1 (offset, 0, context);
            if (list_ret1 == 0)
              return 0;
            add_loc_list (&list_ret, list_ret1);
@@ -14713,6 +16133,8 @@ loc_list_from_tree (tree loc, int want_address,
        have_address = 1;
       else if (tree_fits_shwi_p (loc))
        ret = int_loc_descriptor (tree_to_shwi (loc));
+      else if (tree_fits_uhwi_p (loc))
+       ret = uint_loc_descriptor (tree_to_uhwi (loc));
       else
        {
          expansion_failed (loc, NULL_RTX,
@@ -14727,6 +16149,89 @@ loc_list_from_tree (tree loc, int want_address,
     case COMPLEX_CST:
       if ((ret = cst_pool_loc_descr (loc)))
        have_address = 1;
+      else if (TREE_CODE (loc) == CONSTRUCTOR)
+       {
+         tree type = TREE_TYPE (loc);
+         unsigned HOST_WIDE_INT size = int_size_in_bytes (type);
+         unsigned HOST_WIDE_INT offset = 0;
+         unsigned HOST_WIDE_INT cnt;
+         constructor_elt *ce;
+
+         if (TREE_CODE (type) == RECORD_TYPE)
+           {
+             /* This is very limited, but it's enough to output
+                pointers to member functions, as long as the
+                referenced function is defined in the current
+                translation unit.  */
+             FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (loc), cnt, ce)
+               {
+                 tree val = ce->value;
+
+                 tree field = ce->index;
+
+                 if (val)
+                   STRIP_NOPS (val);
+
+                 if (!field || DECL_BIT_FIELD (field))
+                   {
+                     expansion_failed (loc, NULL_RTX,
+                                       "bitfield in record type constructor");
+                     size = offset = (unsigned HOST_WIDE_INT)-1;
+                     ret = NULL;
+                     break;
+                   }
+
+                 HOST_WIDE_INT fieldsize = tree_to_shwi (DECL_SIZE_UNIT (field));
+                 unsigned HOST_WIDE_INT pos = int_byte_position (field);
+                 gcc_assert (pos + fieldsize <= size);
+                 if (pos < offset)
+                   {
+                     expansion_failed (loc, NULL_RTX,
+                                       "out-of-order fields in record constructor");
+                     size = offset = (unsigned HOST_WIDE_INT)-1;
+                     ret = NULL;
+                     break;
+                   }
+                 if (pos > offset)
+                   {
+                     ret1 = new_loc_descr (DW_OP_piece, pos - offset, 0);
+                     add_loc_descr (&ret, ret1);
+                     offset = pos;
+                   }
+                 if (val && fieldsize != 0)
+                   {
+                     ret1 = loc_descriptor_from_tree (val, want_address, context);
+                     if (!ret1)
+                       {
+                         expansion_failed (loc, NULL_RTX,
+                                           "unsupported expression in field");
+                         size = offset = (unsigned HOST_WIDE_INT)-1;
+                         ret = NULL;
+                         break;
+                       }
+                     add_loc_descr (&ret, ret1);
+                   }
+                 if (fieldsize)
+                   {
+                     ret1 = new_loc_descr (DW_OP_piece, fieldsize, 0);
+                     add_loc_descr (&ret, ret1);
+                     offset = pos + fieldsize;
+                   }
+               }
+
+             if (offset != size)
+               {
+                 ret1 = new_loc_descr (DW_OP_piece, size - offset, 0);
+                 add_loc_descr (&ret, ret1);
+                 offset = size;
+               }
+
+             have_address = !!want_address;
+           }
+         else
+           expansion_failed (loc, NULL_RTX,
+                             "constructor of non-record type");
+       }
       else
       /* We can construct small constants here using int_loc_descriptor.  */
        expansion_failed (loc, NULL_RTX,
@@ -14754,6 +16259,7 @@ loc_list_from_tree (tree loc, int want_address,
     case CEIL_DIV_EXPR:
     case ROUND_DIV_EXPR:
     case TRUNC_DIV_EXPR:
+    case EXACT_DIV_EXPR:
       if (TYPE_UNSIGNED (TREE_TYPE (loc)))
        return 0;
       op = DW_OP_div;
@@ -14772,8 +16278,8 @@ loc_list_from_tree (tree loc, int want_address,
          op = DW_OP_mod;
          goto do_binop;
        }
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
-      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context);
+      list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context);
+      list_ret1 = loc_list_from_tree_1 (TREE_OPERAND (loc, 1), 0, context);
       if (list_ret == 0 || list_ret1 == 0)
        return 0;
 
@@ -14804,11 +16310,49 @@ loc_list_from_tree (tree loc, int want_address,
     do_plus:
       if (tree_fits_shwi_p (TREE_OPERAND (loc, 1)))
        {
-         list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+         /* Big unsigned numbers can fit in HOST_WIDE_INT but it may be
+            smarter to encode their opposite.  The DW_OP_plus_uconst operation
+            takes 1 + X bytes, X being the size of the ULEB128 addend.  On the
+            other hand, a "<push literal>; DW_OP_minus" pattern takes 1 + Y
+            bytes, Y being the size of the operation that pushes the opposite
+            of the addend.  So let's choose the smallest representation.  */
+         const tree tree_addend = TREE_OPERAND (loc, 1);
+         offset_int wi_addend;
+         HOST_WIDE_INT shwi_addend;
+         dw_loc_descr_ref loc_naddend;
+
+         list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context);
          if (list_ret == 0)
            return 0;
 
-         loc_list_plus_const (list_ret, tree_to_shwi (TREE_OPERAND (loc, 1)));
+         /* Try to get the literal to push.  It is the opposite of the addend,
+            so as we rely on wrapping during DWARF evaluation, first decode
+            the literal as a "DWARF-sized" signed number.  */
+         wi_addend = wi::to_offset (tree_addend);
+         wi_addend = wi::sext (wi_addend, DWARF2_ADDR_SIZE * 8);
+         shwi_addend = wi_addend.to_shwi ();
+         loc_naddend = (shwi_addend != INTTYPE_MINIMUM (HOST_WIDE_INT))
+                       ? int_loc_descriptor (-shwi_addend)
+                       : NULL;
+
+         if (loc_naddend != NULL
+             && ((unsigned) size_of_uleb128 (shwi_addend)
+                 > size_of_loc_descr (loc_naddend)))
+           {
+             add_loc_descr_to_each (list_ret, loc_naddend);
+             add_loc_descr_to_each (list_ret,
+                                    new_loc_descr (DW_OP_minus, 0, 0));
+           }
+         else
+           {
+             for (dw_loc_descr_ref loc_cur = loc_naddend; loc_cur != NULL; )
+               {
+                 loc_naddend = loc_cur;
+                 loc_cur = loc_cur->dw_loc_next;
+                 ggc_free (loc_naddend);
+               }
+             loc_list_plus_const (list_ret, wi_addend.to_shwi ());
+           }
          break;
        }
 
@@ -14816,32 +16360,32 @@ loc_list_from_tree (tree loc, int want_address,
       goto do_binop;
 
     case LE_EXPR:
-      if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
-       return 0;
-
       op = DW_OP_le;
-      goto do_binop;
+      goto do_comp_binop;
 
     case GE_EXPR:
-      if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
-       return 0;
-
       op = DW_OP_ge;
-      goto do_binop;
+      goto do_comp_binop;
 
     case LT_EXPR:
-      if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
-       return 0;
-
       op = DW_OP_lt;
-      goto do_binop;
+      goto do_comp_binop;
 
     case GT_EXPR:
-      if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
-       return 0;
-
       op = DW_OP_gt;
-      goto do_binop;
+      goto do_comp_binop;
+
+    do_comp_binop:
+      if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+       {
+         list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+         list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context);
+         list_ret = loc_list_from_uint_comparison (list_ret, list_ret1,
+                                                   TREE_CODE (loc));
+         break;
+       }
+      else
+       goto do_binop;
 
     case EQ_EXPR:
       op = DW_OP_eq;
@@ -14852,8 +16396,8 @@ loc_list_from_tree (tree loc, int want_address,
       goto do_binop;
 
     do_binop:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
-      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context);
+      list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context);
+      list_ret1 = loc_list_from_tree_1 (TREE_OPERAND (loc, 1), 0, context);
       if (list_ret == 0 || list_ret1 == 0)
        return 0;
 
@@ -14877,7 +16421,7 @@ loc_list_from_tree (tree loc, int want_address,
       goto do_unop;
 
     do_unop:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+      list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context);
       if (list_ret == 0)
        return 0;
 
@@ -14896,17 +16440,17 @@ loc_list_from_tree (tree loc, int want_address,
                      TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
       }
 
-      /* ... fall through ...  */
+      /* fall through */
 
     case COND_EXPR:
       {
        dw_loc_descr_ref lhs
          = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0, context);
        dw_loc_list_ref rhs
-         = loc_list_from_tree (TREE_OPERAND (loc, 2), 0, context);
+         = loc_list_from_tree_1 (TREE_OPERAND (loc, 2), 0, context);
        dw_loc_descr_ref bra_node, jump_node, tmp;
 
-       list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+       list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context);
        if (list_ret == 0 || lhs == 0 || rhs == 0)
          return 0;
 
@@ -14943,15 +16487,14 @@ loc_list_from_tree (tree loc, int want_address,
          return 0;
        }
 
-#ifdef ENABLE_CHECKING
       /* Otherwise this is a generic code; we should just lists all of
         these explicitly.  We forgot one.  */
-      gcc_unreachable ();
-#else
+      if (flag_checking)
+       gcc_unreachable ();
+
       /* In a release build, we want to degrade gracefully: better to
         generate incomplete debugging information than to crash.  */
       return NULL;
-#endif
     }
 
   if (!ret && !list_ret)
@@ -15010,6 +16553,22 @@ loc_list_from_tree (tree loc, int want_address,
   return list_ret;
 }
 
+/* Likewise, but strip useless DW_OP_nop operations in the resulting
+   expressions.  */
+
+static dw_loc_list_ref
+loc_list_from_tree (tree loc, int want_address,
+                   const struct loc_descr_context *context)
+{
+  dw_loc_list_ref result = loc_list_from_tree_1 (loc, want_address, context);
+
+  for (dw_loc_list_ref loc_cur = result;
+       loc_cur != NULL; loc_cur =
+       loc_cur->dw_loc_next)
+    loc_descr_without_nops (loc_cur->expr);
+  return result;
+}
+
 /* Same as above but return only single location expression.  */
 static dw_loc_descr_ref
 loc_descriptor_from_tree (tree loc, int want_address,
@@ -15080,35 +16639,91 @@ round_up_to_align (const offset_int &t, unsigned int align)
   return wi::udiv_trunc (t + align - 1, align) * align;
 }
 
-/* Given a pointer to a FIELD_DECL, compute and return the byte offset of the
-   lowest addressed byte of the "containing object" for the given FIELD_DECL,
-   or return 0 if we are unable to determine what that offset is, either
-   because the argument turns out to be a pointer to an ERROR_MARK node, or
-   because the offset is actually variable.  (We can't handle the latter case
-   just yet).  */
+/* Compute the size of TYPE in bytes.  If possible, return NULL and store the
+   size as an integer constant in CST_SIZE.  Otherwise, if possible, return a
+   DWARF expression that computes the size.  Return NULL and set CST_SIZE to -1
+   if we fail to return the size in one of these two forms.  */
 
-static HOST_WIDE_INT
-field_byte_offset (const_tree decl)
+static dw_loc_descr_ref
+type_byte_size (const_tree type, HOST_WIDE_INT *cst_size)
+{
+  tree tree_size;
+  struct loc_descr_context ctx;
+
+  /* Return a constant integer in priority, if possible.  */
+  *cst_size = int_size_in_bytes (type);
+  if (*cst_size != -1)
+    return NULL;
+
+  ctx.context_type = const_cast<tree> (type);
+  ctx.base_decl = NULL_TREE;
+  ctx.dpi = NULL;
+
+  type = TYPE_MAIN_VARIANT (type);
+  tree_size = TYPE_SIZE_UNIT (type);
+  return ((tree_size != NULL_TREE)
+         ? loc_descriptor_from_tree (tree_size, 0, &ctx)
+         : NULL);
+}
+
+/* Helper structure for RECORD_TYPE processing.  */
+struct vlr_context
+{
+  /* Root RECORD_TYPE.  It is needed to generate data member location
+     descriptions in variable-length records (VLR), but also to cope with
+     variants, which are composed of nested structures multiplexed with
+     QUAL_UNION_TYPE nodes.  Each time such a structure is passed to a
+     function processing a FIELD_DECL, it is required to be non null.  */
+  tree struct_type;
+  /* When generating a variant part in a RECORD_TYPE (i.e. a nested
+     QUAL_UNION_TYPE), this holds an expression that computes the offset for
+     this variant part as part of the root record (in storage units).  For
+     regular records, it must be NULL_TREE.  */
+  tree variant_part_offset;
+};
+
+/* Given a pointer to a FIELD_DECL, compute the byte offset of the lowest
+   addressed byte of the "containing object" for the given FIELD_DECL. If
+   possible, return a native constant through CST_OFFSET (in which case NULL is
+   returned); otherwise return a DWARF expression that computes the offset.
+
+   Set *CST_OFFSET to 0 and return NULL if we are unable to determine what
+   that offset is, either because the argument turns out to be a pointer to an
+   ERROR_MARK node, or because the offset expression is too complex for us.
+
+   CTX is required: see the comment for VLR_CONTEXT.  */
+
+static dw_loc_descr_ref
+field_byte_offset (const_tree decl, struct vlr_context *ctx,
+                  HOST_WIDE_INT *cst_offset)
 {
   offset_int object_offset_in_bits;
   offset_int object_offset_in_bytes;
   offset_int bitpos_int;
+  bool is_byte_offset_cst, is_bit_offset_cst;
+  tree tree_result;
+  dw_loc_list_ref loc_result;
 
-  if (TREE_CODE (decl) == ERROR_MARK)
-    return 0;
+  *cst_offset = 0;
 
-  gcc_assert (TREE_CODE (decl) == FIELD_DECL);
+  if (TREE_CODE (decl) == ERROR_MARK)
+    return NULL;
+  else
+    gcc_assert (TREE_CODE (decl) == FIELD_DECL);
 
-  /* We cannot yet cope with fields whose positions are variable, so
-     for now, when we see such things, we simply return 0.  Someday, we may
-     be able to handle such cases, but it will be damn difficult.  */
-  if (TREE_CODE (bit_position (decl)) != INTEGER_CST)
-    return 0;
+  is_bit_offset_cst = TREE_CODE (DECL_FIELD_BIT_OFFSET (decl)) != INTEGER_CST;
+  is_byte_offset_cst = TREE_CODE (DECL_FIELD_OFFSET (decl)) != INTEGER_CST;
 
-  bitpos_int = wi::to_offset (bit_position (decl));
+  /* We cannot handle variable bit offsets at the moment, so abort if it's the
+     case.  */
+  if (is_bit_offset_cst)
+    return NULL;
 
 #ifdef PCC_BITFIELD_TYPE_MATTERS
-  if (PCC_BITFIELD_TYPE_MATTERS)
+  /* We used to handle only constant offsets in all cases.  Now, we handle
+     properly dynamic byte offsets only when PCC bitfield type doesn't
+     matter.  */
+  if (PCC_BITFIELD_TYPE_MATTERS && is_byte_offset_cst && is_bit_offset_cst)
     {
       tree type;
       tree field_size_tree;
@@ -15118,6 +16733,7 @@ field_byte_offset (const_tree decl)
       unsigned int decl_align_in_bits;
       offset_int type_size_in_bits;
 
+      bitpos_int = wi::to_offset (bit_position (decl));
       type = field_type (decl);
       type_size_in_bits = offset_int_type_size_in_bits (type);
       type_align_in_bits = simple_type_align_in_bits (type);
@@ -15204,13 +16820,33 @@ field_byte_offset (const_tree decl)
            = round_up_to_align (object_offset_in_bits, decl_align_in_bits);
        }
     }
-  else
 #endif /* PCC_BITFIELD_TYPE_MATTERS */
-    object_offset_in_bits = bitpos_int;
 
-  object_offset_in_bytes
-    = wi::lrshift (object_offset_in_bits, LOG2_BITS_PER_UNIT);
-  return object_offset_in_bytes.to_shwi ();
+  tree_result = byte_position (decl);
+  if (ctx->variant_part_offset != NULL_TREE)
+    tree_result = fold (build2 (PLUS_EXPR, TREE_TYPE (tree_result),
+                               ctx->variant_part_offset, tree_result));
+
+  /* If the byte offset is a constant, it's simplier to handle a native
+     constant rather than a DWARF expression.  */
+  if (TREE_CODE (tree_result) == INTEGER_CST)
+    {
+      *cst_offset = wi::to_offset (tree_result).to_shwi ();
+      return NULL;
+    }
+  struct loc_descr_context loc_ctx = {
+    ctx->struct_type, /* context_type */
+    NULL_TREE,       /* base_decl */
+    NULL             /* dpi */
+  };
+  loc_result = loc_list_from_tree (tree_result, 0, &loc_ctx);
+
+  /* We want a DWARF expression: abort if we only have a location list with
+     multiple elements.  */
+  if (!loc_result || !single_element_loc_list_p (loc_result))
+    return NULL;
+  else
+    return loc_result->expr;
 }
 \f
 /* The following routines define various Dwarf attributes and any data
@@ -15274,10 +16910,14 @@ add_accessibility_attribute (dw_die_ref die, tree decl)
    DW_AT_byte_size attribute for this bit-field.  (See the
    `byte_size_attribute' function below.)  It is also used when calculating the
    value of the DW_AT_bit_offset attribute.  (See the `bit_offset_attribute'
-   function below.)  */
+   function below.)
+
+   CTX is required: see the comment for VLR_CONTEXT.  */
 
 static void
-add_data_member_location_attribute (dw_die_ref die, tree decl)
+add_data_member_location_attribute (dw_die_ref die,
+                                   tree decl,
+                                   struct vlr_context *ctx)
 {
   HOST_WIDE_INT offset;
   dw_loc_descr_ref loc_descr = 0;
@@ -15327,7 +16967,23 @@ add_data_member_location_attribute (dw_die_ref die, tree decl)
        offset = tree_to_shwi (BINFO_OFFSET (decl));
     }
   else
-    offset = field_byte_offset (decl);
+    {
+      loc_descr = field_byte_offset (decl, ctx, &offset);
+
+      /* If loc_descr is available then we know the field offset is dynamic.
+        However, GDB does not handle dynamic field offsets very well at the
+        moment.  */
+      if (loc_descr != NULL && gnat_encodings != DWARF_GNAT_ENCODINGS_MINIMAL)
+       {
+         loc_descr = NULL;
+         offset = 0;
+       }
+
+      /* Data member location evalutation starts with the base address on the
+        stack.  Compute the field offset and add it to this base address.  */
+      else if (loc_descr != NULL)
+       add_loc_descr (&loc_descr, new_loc_descr (DW_OP_plus, 0, 0));
+    }
 
   if (! loc_descr)
     {
@@ -15422,12 +17078,10 @@ insert_wide_int (const wide_int &val, unsigned char *dest, int elt_size)
 static void
 insert_float (const_rtx rtl, unsigned char *array)
 {
-  REAL_VALUE_TYPE rv;
   long val[4];
   int i;
 
-  REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
-  real_to_target (val, &rv, GET_MODE (rtl));
+  real_to_target (val, CONST_DOUBLE_REAL_VALUE (rtl), GET_MODE (rtl));
 
   /* real_to_target puts 32-bit pieces in each long.  Pack them.  */
   for (i = 0; i < GET_MODE_SIZE (GET_MODE (rtl)) / 4; i++)
@@ -15460,8 +17114,13 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
       return true;
 
     case CONST_WIDE_INT:
-      add_AT_wide (die, DW_AT_const_value,
-                  std::make_pair (rtl, GET_MODE (rtl)));
+      {
+       wide_int w1 = std::make_pair (rtl, MAX_MODE_INT);
+       unsigned int prec = MIN (wi::min_precision (w1, UNSIGNED),
+                                (unsigned int)CONST_WIDE_INT_NUNITS (rtl) * HOST_BITS_PER_WIDE_INT);
+       wide_int w = wi::zext (w1, prec);
+       add_AT_wide (die, DW_AT_const_value, w);
+      }
       return true;
 
     case CONST_DOUBLE:
@@ -15962,7 +17621,7 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
   machine_mode mode;
   HOST_WIDE_INT bitsize, bitpos;
   tree offset;
-  int unsignedp, volatilep = 0;
+  int unsignedp, reversep, volatilep = 0;
 
   /* If the decl isn't a VAR_DECL, or if it isn't static, or if
      it does not have a value (the offset into the common area), or if it
@@ -15978,8 +17637,8 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
   if (TREE_CODE (val_expr) != COMPONENT_REF)
     return NULL_TREE;
 
-  cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset,
-                             &mode, &unsignedp, &volatilep, true);
+  cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset, &mode,
+                             &unsignedp, &reversep, &volatilep);
 
   if (cvar == NULL_TREE
       || TREE_CODE (cvar) != VAR_DECL
@@ -16017,17 +17676,23 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
    since we will need to refer to them each time the function is inlined.  */
 
 static bool
-add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
-                                      enum dwarf_attribute attr)
+add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p)
 {
   rtx rtl;
   dw_loc_list_ref list;
   var_loc_list *loc_list;
   cached_dw_loc_list *cache;
 
+  if (early_dwarf)
+    return false;
+
   if (TREE_CODE (decl) == ERROR_MARK)
     return false;
 
+  if (get_AT (die, DW_AT_location)
+      || get_AT (die, DW_AT_const_value))
+    return true;
+
   gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
              || TREE_CODE (decl) == RESULT_DECL);
 
@@ -16091,7 +17756,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
     }
   if (list)
     {
-      add_AT_location_description (die, attr, list);
+      add_AT_location_description (die, DW_AT_location, list);
       return true;
     }
   /* None of that worked, so it must not really have a location;
@@ -16099,17 +17764,6 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
   return tree_add_const_value_attribute_for_decl (die, decl);
 }
 
-/* Add VARIABLE and DIE into deferred locations list.  */
-
-static void
-defer_location (tree variable, dw_die_ref die)
-{
-  deferred_locations entry;
-  entry.variable = variable;
-  entry.die = die;
-  vec_safe_push (deferred_locations_list, entry);
-}
-
 /* Helper function for tree_add_const_value_attribute.  Natively encode
    initializer INIT into an array.  Return true if successful.  */
 
@@ -16238,7 +17892,7 @@ native_encode_initializer (tree init, unsigned char *array, int size)
              fieldsize = tree_to_shwi (DECL_SIZE_UNIT (field));
              pos = int_byte_position (field);
              gcc_assert (pos + fieldsize <= size);
-             if (val
+             if (val && fieldsize != 0
                  && !native_encode_initializer (val, array + pos, fieldsize))
                return false;
            }
@@ -16308,12 +17962,12 @@ tree_add_const_value_attribute_for_decl (dw_die_ref var_die, tree decl)
          && !TREE_STATIC (decl)))
     return false;
 
-    if (TREE_READONLY (decl)
-       && ! TREE_THIS_VOLATILE (decl)
-       && DECL_INITIAL (decl))
-      /* OK */;
-    else
-      return false;
+  if (TREE_READONLY (decl)
+      && ! TREE_THIS_VOLATILE (decl)
+      && DECL_INITIAL (decl))
+    /* OK */;
+  else
+    return false;
 
   /* Don't add DW_AT_const_value if abstract origin already has one.  */
   if (get_AT (var_die, DW_AT_const_value))
@@ -16577,7 +18231,7 @@ static void
 add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
                 int forms, const struct loc_descr_context *context)
 {
-  dw_die_ref ctx, decl_die;
+  dw_die_ref context_die, decl_die;
   dw_loc_list_ref list;
 
   bool strip_conversions = true;
@@ -16694,13 +18348,14 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
     return;
 
   if (current_function_decl == 0)
-    ctx = comp_unit_die ();
+    context_die = comp_unit_die ();
   else
-    ctx = lookup_decl_die (current_function_decl);
+    context_die = lookup_decl_die (current_function_decl);
 
-  decl_die = new_die (DW_TAG_variable, ctx, value);
+  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, ctx);
+  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);
 }
@@ -16779,6 +18434,14 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
        /* FALLTHRU */
 
       default:
+       /* Because of the complex interaction there can be with other GNAT
+          encodings, GDB isn't ready yet to handle proper DWARF description
+          for self-referencial subrange bounds: let GNAT encodings do the
+          magic in such a case.  */
+       if (gnat_encodings != DWARF_GNAT_ENCODINGS_MINIMAL
+           && contains_placeholder_p (bound))
+         return;
+
        add_scalar_info (subrange_die, bound_attr, bound,
                         dw_scalar_form_constant
                         | dw_scalar_form_exprloc
@@ -16791,14 +18454,17 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
 /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
    possibly nested array subscripts in a flat sequence if COLLAPSE_P is true.
    Note that the block of subscript information for an array type also
-   includes information about the element type of the given array type.  */
+   includes information about the element type of the given array type.
+
+   This function reuses previously set type and bound information if
+   available.  */
 
 static void
 add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
 {
   unsigned dimension_number;
   tree lower, upper;
-  dw_die_ref subrange_die;
+  dw_die_ref child = type_die->die_child;
 
   for (dimension_number = 0;
        TREE_CODE (type) == ARRAY_TYPE && (dimension_number == 0 || collapse_p);
@@ -16812,7 +18478,37 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
       /* Arrays come in three flavors: Unspecified bounds, fixed bounds,
         and (in GNU C only) variable bounds.  Handle all three forms
         here.  */
-      subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
+
+      /* Find and reuse a previously generated DW_TAG_subrange_type if
+        available.
+
+         For multi-dimensional arrays, as we iterate through the
+         various dimensions in the enclosing for loop above, we also
+         iterate through the DIE children and pick at each
+         DW_TAG_subrange_type previously generated (if available).
+         Each child DW_TAG_subrange_type DIE describes the range of
+         the current dimension.  At this point we should have as many
+         DW_TAG_subrange_type's as we have dimensions in the
+         array.  */
+      dw_die_ref subrange_die = NULL;
+      if (child)
+       while (1)
+         {
+           child = child->die_sib;
+           if (child->die_tag == DW_TAG_subrange_type)
+             subrange_die = child;
+           if (child == type_die->die_child)
+             {
+               /* If we wrapped around, stop looking next time.  */
+               child = NULL;
+               break;
+             }
+           if (child->die_tag == DW_TAG_subrange_type)
+             break;
+         }
+      if (!subrange_die)
+       subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
+
       if (domain)
        {
          /* We have an array type with specified bounds.  */
@@ -16820,7 +18516,8 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
          upper = TYPE_MAX_VALUE (domain);
 
          /* Define the index type.  */
-         if (TREE_TYPE (domain))
+         if (TREE_TYPE (domain)
+             && !get_AT (subrange_die, DW_AT_type))
            {
              /* ??? This is probably an Ada unnamed subrange type.  Ignore the
                 TREE_TYPE field.  We can't emit debug info for this
@@ -16832,7 +18529,7 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
                ;
              else
                add_type_attribute (subrange_die, TREE_TYPE (domain),
-                                   TYPE_UNQUALIFIED, type_die);
+                                   TYPE_UNQUALIFIED, false, type_die);
            }
 
          /* ??? If upper is NULL, the array has unspecified length,
@@ -16842,8 +18539,9 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
             to produce useful results, go ahead and output the lower
             bound solo, and hope the debugger can cope.  */
 
-         add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
-         if (upper)
+         if (!get_AT (subrange_die, DW_AT_lower_bound))
+           add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
+         if (upper && !get_AT (subrange_die, DW_AT_upper_bound))
            add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL);
        }
 
@@ -16860,6 +18558,7 @@ add_byte_size_attribute (dw_die_ref die, tree tree_node)
 {
   dw_die_ref decl_die;
   HOST_WIDE_INT size;
+  dw_loc_descr_ref size_expr = NULL;
 
   switch (TREE_CODE (tree_node))
     {
@@ -16876,7 +18575,7 @@ add_byte_size_attribute (dw_die_ref die, tree tree_node)
          add_AT_die_ref (die, DW_AT_byte_size, decl_die);
          return;
        }
-      size = int_size_in_bytes (tree_node);
+      size_expr = type_byte_size (tree_node, &size);
       break;
     case FIELD_DECL:
       /* For a data member of a struct or union, the DW_AT_byte_size is
@@ -16889,10 +18588,17 @@ add_byte_size_attribute (dw_die_ref die, tree tree_node)
       gcc_unreachable ();
     }
 
+  /* Support for dynamically-sized objects was introduced by DWARFv3.
+     At the moment, GDB does not handle variable byte sizes very well,
+     though.  */
+  if ((dwarf_version >= 3 || !dwarf_strict)
+      && gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL
+      && size_expr != NULL)
+    add_AT_loc (die, DW_AT_byte_size, size_expr);
+
   /* Note that `size' might be -1 when we get to this point.  If it is, that
-     indicates that the byte size of the entity in question is variable.  We
-     have no good way of expressing this fact in Dwarf at the present time,
-     when location description was not used by the caller code instead.  */
+     indicates that the byte size of the entity in question is variable and
+     that we could not generate a DWARF expression that computes it.  */
   if (size >= 0)
     add_AT_unsigned (die, DW_AT_byte_size, size);
 }
@@ -16909,22 +18615,26 @@ add_byte_size_attribute (dw_die_ref die, tree tree_node)
    exact location of the "containing object" for a bit-field is rather
    complicated.  It's handled by the `field_byte_offset' function (above).
 
+   CTX is required: see the comment for VLR_CONTEXT.
+
    Note that it is the size (in bytes) of the hypothetical "containing object"
    which will be given in the DW_AT_byte_size attribute for this bit-field.
    (See `byte_size_attribute' above).  */
 
 static inline void
-add_bit_offset_attribute (dw_die_ref die, tree decl)
+add_bit_offset_attribute (dw_die_ref die, tree decl, struct vlr_context *ctx)
 {
-  HOST_WIDE_INT object_offset_in_bytes = field_byte_offset (decl);
-  tree type = DECL_BIT_FIELD_TYPE (decl);
+  HOST_WIDE_INT object_offset_in_bytes;
+  tree original_type = DECL_BIT_FIELD_TYPE (decl);
   HOST_WIDE_INT bitpos_int;
   HOST_WIDE_INT highest_order_object_bit_offset;
   HOST_WIDE_INT highest_order_field_bit_offset;
   HOST_WIDE_INT bit_offset;
 
+  field_byte_offset (decl, ctx, &object_offset_in_bytes);
+
   /* Must be a field and a bit field.  */
-  gcc_assert (type && TREE_CODE (decl) == FIELD_DECL);
+  gcc_assert (original_type && TREE_CODE (decl) == FIELD_DECL);
 
   /* We can't yet handle bit-fields whose offsets are variable, so if we
      encounter such things, just return without generating any attribute
@@ -16946,7 +18656,8 @@ add_bit_offset_attribute (dw_die_ref die, tree decl)
   if (! BYTES_BIG_ENDIAN)
     {
       highest_order_field_bit_offset += tree_to_shwi (DECL_SIZE (decl));
-      highest_order_object_bit_offset += simple_type_size_in_bits (type);
+      highest_order_object_bit_offset +=
+        simple_type_size_in_bits (original_type);
     }
 
   bit_offset
@@ -16996,15 +18707,16 @@ add_prototyped_attribute (dw_die_ref die, tree func_type)
 }
 
 /* Add an 'abstract_origin' attribute below a given DIE.  The DIE is found
-   by looking in either the type declaration or object declaration
-   equate table.  */
+   by looking in the type declaration, the object declaration equate table or
+   the block mapping.  */
 
 static inline dw_die_ref
 add_abstract_origin_attribute (dw_die_ref die, tree origin)
 {
   dw_die_ref origin_die = NULL;
 
-  if (TREE_CODE (origin) != FUNCTION_DECL)
+  if (TREE_CODE (origin) != FUNCTION_DECL
+      && TREE_CODE (origin) != BLOCK)
     {
       /* We may have gotten separated from the block for the inlined
         function, if we're in an exception handler or some such; make
@@ -17026,6 +18738,8 @@ add_abstract_origin_attribute (dw_die_ref die, tree 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);
 
   /* 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
@@ -17099,6 +18813,26 @@ add_src_coords_attributes (dw_die_ref die, tree decl)
 
 /* Add DW_AT_{,MIPS_}linkage_name attribute for the given decl.  */
 
+static void
+add_linkage_name_raw (dw_die_ref die, tree decl)
+{
+  /* Defer until we have an assembler name set.  */
+  if (!DECL_ASSEMBLER_NAME_SET_P (decl))
+    {
+      limbo_die_node *asm_name;
+
+      asm_name = ggc_cleared_alloc<limbo_die_node> ();
+      asm_name->die = die;
+      asm_name->created_for = decl;
+      asm_name->next = deferred_asm_name;
+      deferred_asm_name = asm_name;
+    }
+  else if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
+    add_linkage_attr (die, decl);
+}
+
+/* Add DW_AT_{,MIPS_}linkage_name attribute for the given decl if desired.  */
+
 static void
 add_linkage_name (dw_die_ref die, tree decl)
 {
@@ -17107,21 +18841,7 @@ add_linkage_name (dw_die_ref die, tree decl)
       && TREE_PUBLIC (decl)
       && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
       && die->die_tag != DW_TAG_member)
-    {
-      /* Defer until we have an assembler name set.  */
-      if (!DECL_ASSEMBLER_NAME_SET_P (decl))
-       {
-         limbo_die_node *asm_name;
-
-         asm_name = ggc_cleared_alloc<limbo_die_node> ();
-         asm_name->die = die;
-         asm_name->created_for = decl;
-         asm_name->next = deferred_asm_name;
-         deferred_asm_name = asm_name;
-       }
-      else if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
-       add_linkage_attr (die, decl);
-    }
+    add_linkage_name_raw (die, decl);
 }
 
 /* Add a DW_AT_name attribute and source coordinate attribute for the
@@ -17156,6 +18876,44 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
 #endif /* VMS_DEBUGGING_INFO */
 }
 
+/* Add VALUE as a DW_AT_discr_value attribute to DIE.  */
+
+static void
+add_discr_value (dw_die_ref die, dw_discr_value *value)
+{
+  dw_attr_node attr;
+
+  attr.dw_attr = DW_AT_discr_value;
+  attr.dw_attr_val.val_class = dw_val_class_discr_value;
+  attr.dw_attr_val.val_entry = NULL;
+  attr.dw_attr_val.v.val_discr_value.pos = value->pos;
+  if (value->pos)
+    attr.dw_attr_val.v.val_discr_value.v.uval = value->v.uval;
+  else
+    attr.dw_attr_val.v.val_discr_value.v.sval = value->v.sval;
+  add_dwarf_attr (die, &attr);
+}
+
+/* Add DISCR_LIST as a DW_AT_discr_list to DIE.  */
+
+static void
+add_discr_list (dw_die_ref die, dw_discr_list_ref discr_list)
+{
+  dw_attr_node attr;
+
+  attr.dw_attr = DW_AT_discr_list;
+  attr.dw_attr_val.val_class = dw_val_class_discr_list;
+  attr.dw_attr_val.val_entry = NULL;
+  attr.dw_attr_val.v.val_discr_list = discr_list;
+  add_dwarf_attr (die, &attr);
+}
+
+static inline dw_discr_list_ref
+AT_discr_list (dw_attr_node *attr)
+{
+  return attr->dw_attr_val.v.val_discr_list;
+}
+
 #ifdef VMS_DEBUGGING_INFO
 /* Output the debug main pointer die for VMS */
 
@@ -17338,7 +19096,7 @@ class_or_namespace_scope_p (dw_die_ref context_die)
 
 static void
 add_type_attribute (dw_die_ref object_die, tree type, int cv_quals,
-                   dw_die_ref context_die)
+                   bool reverse, dw_die_ref context_die)
 {
   enum tree_code code  = TREE_CODE (type);
   dw_die_ref type_die  = NULL;
@@ -17360,6 +19118,7 @@ add_type_attribute (dw_die_ref object_die, tree type, int cv_quals,
 
   type_die = modified_type_die (type,
                                cv_quals | TYPE_QUALS_NO_ADDR_SPACE (type),
+                               reverse,
                                context_die);
 
   if (type_die != NULL)
@@ -17470,6 +19229,25 @@ decl_start_label (tree decl)
 }
 #endif
 \f
+/* For variable-length arrays that have been previously generated, but
+   may be incomplete due to missing subscript info, fill the subscript
+   info.  Return TRUE if this is one of those cases.  */
+static bool
+fill_variable_array_bounds (tree type)
+{
+  if (TREE_ASM_WRITTEN (type)
+      && TREE_CODE (type) == ARRAY_TYPE
+      && variably_modified_type_p (type, NULL))
+    {
+      dw_die_ref array_die = lookup_type_die (type);
+      if (!array_die)
+       return false;
+      add_subscript_info (array_die, type, !is_ada ());
+      return true;
+    }
+  return false;
+}
+
 /* These routines generate the internal representation of the DIE's for
    the compilation unit.  Debugging information is collected by walking
    the declaration trees passed in from dwarf2out_decl().  */
@@ -17477,7 +19255,6 @@ decl_start_label (tree decl)
 static void
 gen_array_type_die (tree type, dw_die_ref context_die)
 {
-  dw_die_ref scope_die = scope_die_for (type, context_die);
   dw_die_ref array_die;
 
   /* GNU compilers represent multidimensional array types as sequences of one
@@ -17491,6 +19268,11 @@ gen_array_type_die (tree type, dw_die_ref context_die)
      flexibilty wrt arrays of variable size.  */
 
   bool collapse_nested_arrays = !is_ada ();
+
+  if (fill_variable_array_bounds (type))
+    return;
+
+  dw_die_ref scope_die = scope_die_for (type, context_die);
   tree element_type;
 
   /* Emit DW_TAG_string_type for Fortran character types (with kind 1 only, as
@@ -17509,18 +19291,72 @@ gen_array_type_die (tree type, dw_die_ref context_die)
       if (size >= 0)
        add_AT_unsigned (array_die, DW_AT_byte_size, size);
       else if (TYPE_DOMAIN (type) != NULL_TREE
-              && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
-              && DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
+              && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE)
        {
          tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
-         dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2, NULL);
+         tree rszdecl = szdecl;
+         HOST_WIDE_INT rsize = 0;
 
          size = int_size_in_bytes (TREE_TYPE (szdecl));
-         if (loc && size > 0)
+         if (!DECL_P (szdecl))
+           {
+             if (TREE_CODE (szdecl) == INDIRECT_REF
+                 && DECL_P (TREE_OPERAND (szdecl, 0)))
+               {
+                 rszdecl = TREE_OPERAND (szdecl, 0);
+                 rsize = int_size_in_bytes (TREE_TYPE (rszdecl));
+                 if (rsize <= 0)
+                   size = 0;
+               }
+             else
+               size = 0;
+           }
+         if (size > 0)
            {
-             add_AT_location_description (array_die, DW_AT_string_length, loc);
-             if (size != DWARF2_ADDR_SIZE)
-               add_AT_unsigned (array_die, DW_AT_byte_size, size);
+             dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2, NULL);
+             if (loc == NULL
+                 && early_dwarf
+                 && current_function_decl
+                 && DECL_CONTEXT (rszdecl) == current_function_decl)
+               {
+                 dw_die_ref ref = lookup_decl_die (rszdecl);
+                 dw_loc_descr_ref l = NULL;
+                 if (ref)
+                   {
+                     l = new_loc_descr (DW_OP_call4, 0, 0);
+                     l->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+                     l->dw_loc_oprnd1.v.val_die_ref.die = ref;
+                     l->dw_loc_oprnd1.v.val_die_ref.external = 0;
+                   }
+                 else if (TREE_CODE (rszdecl) == PARM_DECL
+                          && string_types)
+                   {
+                     l = new_loc_descr (DW_OP_call4, 0, 0);
+                     l->dw_loc_oprnd1.val_class = dw_val_class_decl_ref;
+                     l->dw_loc_oprnd1.v.val_decl_ref = rszdecl;
+                     string_types->safe_push (array_die);
+                   }
+                 if (l && rszdecl != szdecl)
+                   {
+                     if (rsize == DWARF2_ADDR_SIZE)
+                       add_loc_descr (&l, new_loc_descr (DW_OP_deref,
+                                                         0, 0));
+                     else
+                       add_loc_descr (&l, new_loc_descr (DW_OP_deref_size,
+                                                         rsize, 0));
+                   }
+                 if (l)
+                   loc = new_loc_list (l, NULL, NULL, NULL);
+               }
+             if (loc)
+               {
+                 add_AT_location_description (array_die, DW_AT_string_length,
+                                              loc);
+                 if (size != DWARF2_ADDR_SIZE)
+                   add_AT_unsigned (array_die, dwarf_version >= 5
+                                               ? DW_AT_string_length_byte_size
+                                               : DW_AT_byte_size, size);
+               }
            }
        }
       return;
@@ -17573,7 +19409,10 @@ gen_array_type_die (tree type, dw_die_ref context_die)
        element_type = TREE_TYPE (element_type);
       }
 
-  add_type_attribute (array_die, element_type, TYPE_UNQUALIFIED, context_die);
+  add_type_attribute (array_die, element_type, TYPE_UNQUALIFIED,
+                     TREE_CODE (type) == ARRAY_TYPE
+                     && TYPE_REVERSE_STORAGE_ORDER (type),
+                     context_die);
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
   if (TYPE_ARTIFICIAL (type))
@@ -17583,6 +19422,39 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     add_pubtype (type, array_die);
 }
 
+/* After all arguments are created, adjust any DW_TAG_string_type
+   DIEs DW_AT_string_length attributes.  */
+
+static void
+adjust_string_types (void)
+{
+  dw_die_ref array_die;
+  unsigned int i;
+  FOR_EACH_VEC_ELT (*string_types, i, array_die)
+    {
+      dw_attr_node *a = get_AT (array_die, DW_AT_string_length);
+      if (a == NULL)
+       continue;
+      dw_loc_descr_ref loc = AT_loc (a);
+      gcc_assert (loc->dw_loc_opc == DW_OP_call4
+                 && loc->dw_loc_oprnd1.val_class == dw_val_class_decl_ref);
+      dw_die_ref ref = lookup_decl_die (loc->dw_loc_oprnd1.v.val_decl_ref);
+      if (ref)
+       {
+         loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+         loc->dw_loc_oprnd1.v.val_die_ref.die = ref;
+         loc->dw_loc_oprnd1.v.val_die_ref.external = 0;
+       }
+      else
+       {
+         remove_AT (array_die, DW_AT_string_length);
+         remove_AT (array_die, dwarf_version >= 5
+                               ? DW_AT_string_length_byte_size
+                               : DW_AT_byte_size);
+       }
+    }
+}
+
 /* This routine generates DIE for array with hidden descriptor, details
    are filled into *info by a langhook.  */
 
@@ -17592,7 +19464,7 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 {
   const dw_die_ref scope_die = scope_die_for (type, context_die);
   const dw_die_ref array_die = new_die (DW_TAG_array_type, scope_die, type);
-  const struct loc_descr_context context = { type, info->base_decl };
+  const struct loc_descr_context context = { type, info->base_decl, NULL };
   int dim;
 
   add_name_attribute (array_die, type_tag (type));
@@ -17626,6 +19498,19 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
                         dw_scalar_form_constant
                         | dw_scalar_form_exprloc
                         | dw_scalar_form_reference, &context);
+      if (info->stride)
+       {
+         const enum dwarf_attribute attr
+           = (info->stride_in_bits) ? DW_AT_bit_stride : DW_AT_byte_stride;
+         const int forms
+           = (info->stride_in_bits)
+             ? dw_scalar_form_constant
+             : (dw_scalar_form_constant
+                | dw_scalar_form_exprloc
+                | dw_scalar_form_reference);
+
+         add_scalar_info (array_die, attr, info->stride, forms, &context);
+       }
     }
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
@@ -17637,8 +19522,8 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 
       if (info->dimen[dim].bounds_type)
        add_type_attribute (subrange_die,
-                           info->dimen[dim].bounds_type, 0,
-                           context_die);
+                           info->dimen[dim].bounds_type, TYPE_UNQUALIFIED,
+                           false, context_die);
       if (info->dimen[dim].lower_bound)
        add_bound_info (subrange_die, DW_AT_lower_bound,
                        info->dimen[dim].lower_bound, &context);
@@ -17656,6 +19541,8 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 
   gen_type_die (info->element_type, context_die);
   add_type_attribute (array_die, info->element_type, TYPE_UNQUALIFIED,
+                     TREE_CODE (type) == ARRAY_TYPE
+                     && TYPE_REVERSE_STORAGE_ORDER (type),
                      context_die);
 
   if (get_AT (array_die, DW_AT_name))
@@ -17675,7 +19562,7 @@ gen_entry_point_die (tree decl, dw_die_ref context_die)
     {
       add_name_and_src_coords_attributes (decl_die, decl);
       add_type_attribute (decl_die, TREE_TYPE (TREE_TYPE (decl)),
-                         TYPE_UNQUALIFIED, context_die);
+                         TYPE_UNQUALIFIED, false, context_die);
     }
 
   if (DECL_ABSTRACT_P (decl))
@@ -17691,11 +19578,13 @@ gen_entry_point_die (tree decl, dw_die_ref context_die)
 static void
 retry_incomplete_types (void)
 {
+  set_early_dwarf s;
   int i;
 
   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 ());
+  vec_safe_truncate (incomplete_types, 0);
 }
 
 /* Determine what tag to use for a record type.  */
@@ -17765,7 +19654,7 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
       if (dwarf_version >= 3 || !dwarf_strict)
        {
          tree underlying = lang_hooks.types.enum_underlying_base_type (type);
-         add_type_attribute (type_die, underlying, TYPE_UNQUALIFIED,
+         add_type_attribute (type_die, underlying, TYPE_UNQUALIFIED, false,
                              context_die);
        }
       if (TYPE_STUB_DECL (type) != NULL_TREE)
@@ -17846,8 +19735,67 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
 {
   tree node_or_origin = node ? node : origin;
   tree ultimate_origin;
-  dw_die_ref parm_die
-    = new_die (DW_TAG_formal_parameter, context_die, node);
+  dw_die_ref parm_die = NULL;
+  
+  if (TREE_CODE_CLASS (TREE_CODE (node_or_origin)) == tcc_declaration)
+    {
+      parm_die = lookup_decl_die (node);
+
+      /* If the contexts differ, we may not be talking about the same
+        thing.  */
+      if (parm_die && parm_die->die_parent != context_die)
+       {
+         if (!DECL_ABSTRACT_P (node))
+           {
+             /* This can happen when creating an inlined instance, in
+                which case we need to create a new DIE that will get
+                annotated with DW_AT_abstract_origin.  */
+             parm_die = NULL;
+           }
+         else
+           {
+             /* FIXME: Reuse DIE even with a differing context.
+
+                This can happen when calling
+                dwarf2out_abstract_function to build debug info for
+                the abstract instance of a function for which we have
+                already generated a DIE in
+                dwarf2out_early_global_decl.
+
+                Once we remove dwarf2out_abstract_function, we should
+                have a call to gcc_unreachable here.  */
+           }
+       }
+
+      if (parm_die && parm_die->die_parent == NULL)
+       {
+         /* Check that parm_die already has the right attributes that
+            we would have added below.  If any attributes are
+            missing, fall through to add them.  */
+         if (! DECL_ABSTRACT_P (node_or_origin)
+             && !get_AT (parm_die, DW_AT_location)
+             && !get_AT (parm_die, DW_AT_const_value))
+           /* We are missing  location info, and are about to add it.  */
+           ;
+         else
+           {
+             add_child_die (context_die, parm_die);
+             return parm_die;
+           }
+       }
+    }
+
+  /* If we have a previously generated DIE, use it, unless this is an
+     concrete instance (origin != NULL), in which case we need a new
+     DIE with a corresponding DW_AT_abstract_origin.  */
+  bool reusing_die;
+  if (parm_die && origin == NULL)
+    reusing_die = true;
+  else
+    {
+      parm_die = new_die (DW_TAG_formal_parameter, context_die, node);
+      reusing_die = false;
+    }
 
   switch (TREE_CODE_CLASS (TREE_CODE (node_or_origin)))
     {
@@ -17855,6 +19803,10 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
       ultimate_origin = decl_ultimate_origin (node_or_origin);
       if (node || ultimate_origin)
        origin = ultimate_origin;
+
+      if (reusing_die)
+       goto add_location;
+
       if (origin != NULL)
        add_abstract_origin_attribute (parm_die, origin);
       else if (emit_name_p)
@@ -17868,26 +19820,27 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
          tree type = TREE_TYPE (node_or_origin);
          if (decl_by_reference_p (node_or_origin))
            add_type_attribute (parm_die, TREE_TYPE (type),
-                               TYPE_UNQUALIFIED, context_die);
+                               TYPE_UNQUALIFIED,
+                               false, context_die);
          else
            add_type_attribute (parm_die, type,
                                decl_quals (node_or_origin),
-                               context_die);
+                               false, context_die);
        }
       if (origin == NULL && DECL_ARTIFICIAL (node))
        add_AT_flag (parm_die, DW_AT_artificial, 1);
-
+    add_location:
       if (node && node != origin)
         equate_decl_number_to_die (node, parm_die);
       if (! DECL_ABSTRACT_P (node_or_origin))
        add_location_or_const_value_attribute (parm_die, node_or_origin,
-                                              node == NULL, DW_AT_location);
+                                              node == NULL);
 
       break;
 
     case tcc_type:
       /* We were called with some kind of a ..._TYPE node.  */
-      add_type_attribute (parm_die, node_or_origin, TYPE_UNQUALIFIED,
+      add_type_attribute (parm_die, node_or_origin, TYPE_UNQUALIFIED, false,
                          context_die);
       break;
 
@@ -18048,8 +20001,12 @@ gen_type_die_for_member (tree type, tree member, dw_die_ref context_die)
              || TREE_CODE (TREE_TYPE (member)) == UNION_TYPE
              || TREE_CODE (TREE_TYPE (member)) == RECORD_TYPE)
            {
+             struct vlr_context vlr_ctx = {
+               DECL_CONTEXT (member), /* struct_type */
+               NULL_TREE /* variant_part_offset */
+             };
              gen_type_die (member_declared_type (member), type_die);
-             gen_field_die (member, type_die);
+             gen_field_die (member, &vlr_ctx, type_die);
            }
        }
       else
@@ -18062,7 +20019,7 @@ gen_type_die_for_member (tree type, tree member, dw_die_ref context_die)
 /* 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);
+static void set_decl_abstract_flags (tree, vec<tree> &);
 
 /* 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
@@ -18135,64 +20092,86 @@ set_decl_origin_self (tree 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.  */
+/* Given a pointer to some BLOCK node, set the BLOCK_ABSTRACT flag to 1
+   and if it wasn't 1 before, push it to abstract_vec vector.
+   For all local decls and all local sub-blocks (recursively) do it
+   too.  */
 
 static void
-set_block_abstract_flags (tree stmt, int setting)
+set_block_abstract_flags (tree stmt, vec<tree> &abstract_vec)
 {
   tree local_decl;
   tree subblock;
   unsigned int i;
 
-  BLOCK_ABSTRACT (stmt) = setting;
+  if (!BLOCK_ABSTRACT (stmt))
+    {
+      abstract_vec.safe_push (stmt);
+      BLOCK_ABSTRACT (stmt) = 1;
+    }
 
   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);
+      set_decl_abstract_flags (local_decl, abstract_vec);
 
   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);
+       set_decl_abstract_flags (local_decl, abstract_vec);
     }
 
   for (subblock = BLOCK_SUBBLOCKS (stmt);
        subblock != NULL_TREE;
        subblock = BLOCK_CHAIN (subblock))
-    set_block_abstract_flags (subblock, setting);
+    set_block_abstract_flags (subblock, abstract_vec);
 }
 
-/* Given a pointer to some ..._DECL node, and a boolean value to set the
-   "abstract" flags to, set that value into the DECL_ABSTRACT_P 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.  */
+/* Given a pointer to some ..._DECL node, set DECL_ABSTRACT_P flag on it
+   to 1 and if it wasn't 1 before, push to abstract_vec vector.
+   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).  */
 
 static void
-set_decl_abstract_flags (tree decl, int setting)
+set_decl_abstract_flags (tree decl, vec<tree> &abstract_vec)
 {
-  DECL_ABSTRACT_P (decl) = setting;
+  if (!DECL_ABSTRACT_P (decl))
+    {
+      abstract_vec.safe_push (decl);
+      DECL_ABSTRACT_P (decl) = 1;
+    }
+
   if (TREE_CODE (decl) == FUNCTION_DECL)
     {
       tree arg;
 
       for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg))
-       DECL_ABSTRACT_P (arg) = setting;
+       if (!DECL_ABSTRACT_P (arg))
+         {
+           abstract_vec.safe_push (arg);
+           DECL_ABSTRACT_P (arg) = 1;
+         }
       if (DECL_INITIAL (decl) != NULL_TREE
          && DECL_INITIAL (decl) != error_mark_node)
-       set_block_abstract_flags (DECL_INITIAL (decl), setting);
+       set_block_abstract_flags (DECL_INITIAL (decl), abstract_vec);
     }
 }
 
 /* Generate the DWARF2 info for the "abstract" instance of a function which we
-   may later generate inlined and/or out-of-line instances of.  */
+   may later generate inlined and/or out-of-line instances of.
+
+   FIXME: In the early-dwarf world, this function, and most of the
+          DECL_ABSTRACT code should be obsoleted.  The early DIE _is_
+          the abstract instance.  All we would need to do is annotate
+          the early DIE with the appropriate DW_AT_inline in late
+          dwarf (perhaps in gen_inlined_subroutine_die).
+
+         However, we can't do this yet, because LTO streaming of DIEs
+         has not been implemented yet.  */
 
 static void
 dwarf2out_abstract_function (tree decl)
@@ -18200,7 +20179,6 @@ dwarf2out_abstract_function (tree decl)
   dw_die_ref old_die;
   tree save_fn;
   tree context;
-  int was_abstract;
   hash_table<decl_loc_hasher> *old_decl_loc_table;
   hash_table<dw_loc_list_hasher> *old_cached_dw_loc_list_table;
   int old_call_site_count, old_tail_call_site_count;
@@ -18242,11 +20220,16 @@ dwarf2out_abstract_function (tree decl)
   save_fn = current_function_decl;
   current_function_decl = decl;
 
-  was_abstract = DECL_ABSTRACT_P (decl);
-  set_decl_abstract_flags (decl, 1);
+  auto_vec<tree, 64> abstract_vec;
+  set_decl_abstract_flags (decl, abstract_vec);
   dwarf2out_decl (decl);
-  if (! was_abstract)
-    set_decl_abstract_flags (decl, 0);
+  unsigned int i;
+  tree t;
+  FOR_EACH_VEC_ELT (abstract_vec, i, t)
+    if (TREE_CODE (t) == BLOCK)
+      BLOCK_ABSTRACT (t) = 0;
+    else
+      DECL_ABSTRACT_P (t) = 0;
 
   current_function_decl = save_fn;
   decl_loc_table = old_decl_loc_table;
@@ -18340,8 +20323,7 @@ gen_call_site_die (tree decl, dw_die_ref subr_die,
         && block != DECL_INITIAL (decl)
         && TREE_CODE (block) == BLOCK)
     {
-      if (block_map.length () > BLOCK_NUMBER (block))
-       stmt_die = block_map[BLOCK_NUMBER (block)];
+      stmt_die = BLOCK_DIE (block);
       if (stmt_die)
        break;
       block = BLOCK_SUPERCONTEXT (block);
@@ -18371,26 +20353,94 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 {
   tree origin = decl_ultimate_origin (decl);
   dw_die_ref subr_die;
-  tree outer_scope;
   dw_die_ref old_die = lookup_decl_die (decl);
+
+  /* This function gets called multiple times for different stages of
+     the debug process.  For example, for func() in this code:
+
+       namespace S
+       {
+         void func() { ... }
+       }
+
+     ...we get called 4 times.  Twice in early debug and twice in
+     late debug:
+
+     Early debug
+     -----------
+
+       1. Once while generating func() within the namespace.  This is
+          the declaration.  The declaration bit below is set, as the
+          context is the namespace.
+
+         A new DIE will be generated with DW_AT_declaration set.
+
+       2. Once for func() itself.  This is the specification.  The
+          declaration bit below is clear as the context is the CU.
+
+         We will use the cached DIE from (1) to create a new DIE with
+         DW_AT_specification pointing to the declaration in (1).
+
+     Late debug via rest_of_handle_final()
+     -------------------------------------
+
+       3. Once generating func() within the namespace.  This is also the
+          declaration, as in (1), but this time we will early exit below
+          as we have a cached DIE and a declaration needs no additional
+          annotations (no locations), as the source declaration line
+          info is enough.
+
+       4. Once for func() itself.  As in (2), this is the specification,
+          but this time we will re-use the cached DIE, and just annotate
+          it with the location information that should now be available.
+
+     For something without namespaces, but with abstract instances, we
+     are also called a multiple times:
+
+        class Base
+       {
+       public:
+         Base ();        // constructor declaration (1)
+       };
+
+       Base::Base () { } // constructor specification (2)
+
+    Early debug
+    -----------
+
+       1. Once for the Base() constructor by virtue of it being a
+          member of the Base class.  This is done via
+          rest_of_type_compilation.
+
+         This is a declaration, so a new DIE will be created with
+         DW_AT_declaration.
+
+       2. Once for the Base() constructor definition, but this time
+          while generating the abstract instance of the base
+          constructor (__base_ctor) which is being generated via early
+          debug of reachable functions.
+
+         Even though we have a cached version of the declaration (1),
+         we will create a DW_AT_specification of the declaration DIE
+         in (1).
+
+       3. Once for the __base_ctor itself, but this time, we generate
+          an DW_AT_abstract_origin version of the DW_AT_specification in
+         (2).
+
+    Late debug via rest_of_handle_final
+    -----------------------------------
+
+       4. One final time for the __base_ctor (which will have a cached
+          DIE with DW_AT_abstract_origin created in (3).  This time,
+          we will just annotate the location information now
+          available.
+  */
   int declaration = (current_function_decl != decl
                     || class_or_namespace_scope_p (context_die));
 
   premark_used_types (DECL_STRUCT_FUNCTION (decl));
 
-  /* It is possible to have both DECL_ABSTRACT_P and DECLARATION be true if we
-     started to generate the abstract instance of an inline, decided to output
-     its containing class, and proceeded to emit the declaration of the inline
-     from the member list for the class.  If so, DECLARATION takes priority;
-     we'll get back to the abstract instance when done with the class.  */
-
-  /* The class-scope declaration DIE must be the primary DIE.  */
-  if (origin && declaration && class_or_namespace_scope_p (context_die))
-    {
-      origin = NULL;
-      gcc_assert (!old_die);
-    }
-
   /* Now that the C++ front end lazily declares artificial member fns, we
      might need to retrofit the declaration into its class.  */
   if (!declaration && !origin && !old_die
@@ -18399,6 +20449,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       && debug_info_level > DINFO_LEVEL_TERSE)
     old_die = force_decl_die (decl);
 
+  /* An inlined instance, tag a new DIE with DW_AT_abstract_origin.  */
   if (origin != NULL)
     {
       gcc_assert (!declaration || local_scope_p (context_die));
@@ -18408,19 +20459,32 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (old_die && old_die->die_parent == NULL)
        add_child_die (context_die, old_die);
 
-      subr_die = new_die (DW_TAG_subprogram, context_die, decl);
-      add_abstract_origin_attribute (subr_die, origin);
-      /*  This is where the actual code for a cloned function is.
-         Let's emit linkage name attribute for it.  This helps
-         debuggers to e.g, set breakpoints into
-         constructors/destructors when the user asks "break
-         K::K".  */
-      add_linkage_name (subr_die, decl);
+      if (old_die && get_AT_ref (old_die, DW_AT_abstract_origin))
+       {
+         /* If we have a DW_AT_abstract_origin we have a working
+            cached version.  */
+         subr_die = old_die;
+       }
+      else
+       {
+         subr_die = new_die (DW_TAG_subprogram, context_die, decl);
+         add_abstract_origin_attribute (subr_die, origin);
+         /*  This is where the actual code for a cloned function is.
+             Let's emit linkage name attribute for it.  This helps
+             debuggers to e.g, set breakpoints into
+             constructors/destructors when the user asks "break
+             K::K".  */
+         add_linkage_name (subr_die, decl);
+       }
     }
+  /* A cached copy, possibly from early dwarf generation.  Reuse as
+     much as possible.  */
   else if (old_die)
     {
-      expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
-      struct dwarf_file_data * file_index = lookup_filename (s.file);
+      /* A declaration that has been previously dumped needs no
+        additional information.  */
+      if (declaration)
+       return;
 
       if (!get_AT_flag (old_die, DW_AT_declaration)
          /* We can have a normal definition following an inline one in the
@@ -18430,7 +20494,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        {
          /* Detect and ignore this case, where we are trying to output
             something we have already output.  */
-         return;
+         if (get_AT (old_die, DW_AT_low_pc)
+             || get_AT (old_die, DW_AT_ranges))
+           return;
+
+         /* If we have no location information, this must be a
+            partially generated DIE from early dwarf generation.
+            Fall through and generate it.  */
        }
 
       /* If the definition comes from the same place as the declaration,
@@ -18440,23 +20510,44 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
         instances of inlines, since the spec requires the out-of-line copy
         to have the same parent.  For local class methods, this doesn't
         apply; we just use the old DIE.  */
-      if ((is_cu_die (old_die->die_parent) || context_die == NULL)
-         && (DECL_ARTIFICIAL (decl)
-             || (get_AT_file (old_die, DW_AT_decl_file) == file_index
-                 && (get_AT_unsigned (old_die, DW_AT_decl_line)
-                     == (unsigned) s.line))))
+      expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
+      struct dwarf_file_data * file_index = lookup_filename (s.file);
+      if ((is_cu_die (old_die->die_parent)
+          /* This condition fixes the inconsistency/ICE with the
+             following Fortran test (or some derivative thereof) while
+             building libgfortran:
+
+                module some_m
+                contains
+                   logical function funky (FLAG)
+                     funky = .true.
+                  end function
+                end module
+          */
+          || (old_die->die_parent
+              && old_die->die_parent->die_tag == DW_TAG_module)
+          || context_die == NULL)
+          && (DECL_ARTIFICIAL (decl)
+              || (get_AT_file (old_die, DW_AT_decl_file) == file_index
+                  && (get_AT_unsigned (old_die, DW_AT_decl_line)
+                      == (unsigned) s.line))))
        {
          subr_die = old_die;
 
-         /* Clear out the declaration attribute and the formal parameters.
-            Do not remove all children, because it is possible that this
-            declaration die was forced using force_decl_die(). In such
-            cases die that forced declaration die (e.g. TAG_imported_module)
-            is one of the children that we do not want to remove.  */
-         remove_AT (subr_die, DW_AT_declaration);
-         remove_AT (subr_die, DW_AT_object_pointer);
-         remove_child_TAG (subr_die, DW_TAG_formal_parameter);
+         /* Clear out the declaration attribute, but leave the
+            parameters so they can be augmented with location
+            information later.  Unless this was a declaration, in
+            which case, wipe out the nameless parameters and recreate
+            them further down.  */
+         if (remove_AT (subr_die, DW_AT_declaration))
+           {
+
+             remove_AT (subr_die, DW_AT_object_pointer);
+             remove_child_TAG (subr_die, DW_TAG_formal_parameter);
+           }
        }
+      /* Make a specification pointing to the previously built
+        declaration.  */
       else
        {
          subr_die = new_die (DW_TAG_subprogram, context_die, decl);
@@ -18474,10 +20565,29 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
              dw_die_ref die = get_AT_ref (old_die, DW_AT_type);
              if (die == auto_die || die == decltype_auto_die)
                add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),
-                                   TYPE_UNQUALIFIED, context_die);
+                                   TYPE_UNQUALIFIED, false, context_die);
            }
+
+         /* When we process the method declaration, we haven't seen
+            the out-of-class defaulted definition yet, so we have to
+            recheck now.  */
+         int defaulted = lang_hooks.decls.function_decl_defaulted (decl);
+         if (defaulted && (dwarf_version >= 5 || ! dwarf_strict)
+             && !get_AT (subr_die, DW_AT_defaulted))
+           switch (defaulted)
+             {
+             case 2:
+               add_AT_unsigned (subr_die, DW_AT_defaulted,
+                                DW_DEFAULTED_out_of_class);
+               break;
+
+             case 1: /* This must have been handled before.  */
+             default:
+               gcc_unreachable ();
+             }
        }
     }
+  /* Create a fresh DIE for anything else.  */
   else
     {
       subr_die = new_die (DW_TAG_subprogram, context_die, decl);
@@ -18491,7 +20601,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        {
          add_prototyped_attribute (subr_die, TREE_TYPE (decl));
          add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),
-                             TYPE_UNQUALIFIED, context_die);
+                             TYPE_UNQUALIFIED, false, context_die);
        }
 
       add_pure_or_virtual_attribute (subr_die, decl);
@@ -18504,6 +20614,11 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       add_accessibility_attribute (subr_die, decl);
     }
 
+  /* Unless we have an existing non-declaration DIE, equate the new
+     DIE.  */
+  if (!old_die || is_declaration_die (old_die))
+    equate_decl_number_to_die (decl, subr_die);
+
   if (declaration)
     {
       if (!old_die || !get_AT (old_die, DW_AT_inline))
@@ -18517,21 +20632,38 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
            add_AT_flag (subr_die, DW_AT_explicit, 1);
 
          /* If this is a C++11 deleted special function member then generate
-            a DW_AT_GNU_deleted attribute.  */
+            a DW_AT_deleted attribute.  */
          if (lang_hooks.decls.function_decl_deleted_p (decl)
-             && (! dwarf_strict))
-           add_AT_flag (subr_die, DW_AT_GNU_deleted, 1);
+             && (dwarf_version >= 5 || ! dwarf_strict))
+           add_AT_flag (subr_die, DW_AT_deleted, 1);
+
+         /* If this is a C++11 defaulted special function member then
+            generate a DW_AT_GNU_defaulted attribute.  */
+         int defaulted = lang_hooks.decls.function_decl_defaulted (decl);
+         if (defaulted && (dwarf_version >= 5 || ! dwarf_strict))
+           switch (defaulted)
+             {
+             case 1:
+               add_AT_unsigned (subr_die, DW_AT_defaulted,
+                                DW_DEFAULTED_in_class);
+               break;
 
-         /* The first time we see a member function, it is in the context of
-            the class to which it belongs.  We make sure of this by emitting
-            the class first.  The next time is the definition, which is
-            handled above.  The two may come from the same source text.
+               /* It is likely that this will never hit, since we
+                  don't have the out-of-class definition yet when we
+                  process the class definition and the method
+                  declaration.  We recheck elsewhere, but leave it
+                  here just in case.  */
+             case 2:
+               add_AT_unsigned (subr_die, DW_AT_defaulted,
+                                DW_DEFAULTED_out_of_class);
+               break;
 
-            Note that force_decl_die() forces function declaration die. It is
-            later reused to represent definition.  */
-         equate_decl_number_to_die (decl, subr_die);
+             default:
+               gcc_unreachable ();
+             }
        }
     }
+  /* Tag abstract instances with DW_AT_inline.  */
   else if (DECL_ABSTRACT_P (decl))
     {
       if (DECL_DECLARED_INLINE_P (decl))
@@ -18552,18 +20684,15 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (DECL_DECLARED_INLINE_P (decl)
          && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
        add_AT_flag (subr_die, DW_AT_artificial, 1);
-
-      equate_decl_number_to_die (decl, subr_die);
     }
-  else if (!DECL_EXTERNAL (decl))
+  /* For non DECL_EXTERNALs, if range information is available, fill
+     the DIE with it.  */
+  else if (!DECL_EXTERNAL (decl) && !early_dwarf)
     {
       HOST_WIDE_INT cfa_fb_offset;
-      struct function *fun = DECL_STRUCT_FUNCTION (decl);
 
-      if (!old_die || !get_AT (old_die, DW_AT_inline))
-       equate_decl_number_to_die (decl, subr_die);
+      struct function *fun = DECL_STRUCT_FUNCTION (decl);
 
-      gcc_checking_assert (fun);
       if (!flag_reorder_blocks_and_partition)
        {
          dw_fde_ref fde = fun->fde;
@@ -18717,12 +20846,27 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
 
       if (fun->static_chain_decl)
-       add_AT_location_description (subr_die, DW_AT_static_link,
-                loc_list_from_tree (fun->static_chain_decl, 2, NULL));
+       {
+         /* DWARF requires here a location expression that computes the
+            address of the enclosing subprogram's frame base.  The machinery
+            in tree-nested.c is supposed to store this specific address in the
+            last field of the FRAME record.  */
+         const tree frame_type
+           = TREE_TYPE (TREE_TYPE (fun->static_chain_decl));
+         const tree fb_decl = tree_last (TYPE_FIELDS (frame_type));
+
+         tree fb_expr
+           = build1 (INDIRECT_REF, frame_type, fun->static_chain_decl);
+         fb_expr = build3 (COMPONENT_REF, TREE_TYPE (fb_decl),
+                           fb_expr, fb_decl, NULL_TREE);
+
+         add_AT_location_description (subr_die, DW_AT_static_link,
+                                      loc_list_from_tree (fb_expr, 0, NULL));
+       }
     }
 
   /* Generate child dies for template paramaters.  */
-  if (debug_info_level > DINFO_LEVEL_TERSE)
+  if (early_dwarf && debug_info_level > DINFO_LEVEL_TERSE)
     gen_generic_params_dies (decl);
 
   /* Now output descriptions of the arguments for this function. This gets
@@ -18746,10 +20890,14 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
     {
       /* Generate DIEs to represent all known formal parameters.  */
       tree parm = DECL_ARGUMENTS (decl);
-      tree generic_decl = lang_hooks.decls.get_generic_function_decl (decl);
+      tree generic_decl = early_dwarf
+       ? lang_hooks.decls.get_generic_function_decl (decl) : NULL;
       tree generic_decl_parm = generic_decl
                                ? DECL_ARGUMENTS (generic_decl)
                                : NULL;
+      auto_vec<dw_die_ref> string_types_vec;
+      if (string_types == NULL)
+       string_types = &string_types_vec;
 
       /* Now we want to walk the list of parameters of the function and
         emit their relevant DIEs.
@@ -18778,7 +20926,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                                           &parm);
          else if (parm && !POINTER_BOUNDS_P (parm))
            {
-             dw_die_ref parm_die = gen_decl_die (parm, NULL, subr_die);
+             dw_die_ref parm_die = gen_decl_die (parm, NULL, NULL, subr_die);
 
              if (parm == DECL_ARGUMENTS (decl)
                  && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
@@ -18801,21 +20949,35 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
         void_type_node 2) an unprototyped function declaration (not a
         definition).  This just means that we have no info about the
         parameters at all.  */
-      if (prototype_p (TREE_TYPE (decl)))
+      if (early_dwarf)
        {
-         /* This is the prototyped case, check for....  */
-         if (stdarg_p (TREE_TYPE (decl)))
+         if (prototype_p (TREE_TYPE (decl)))
+           {
+             /* This is the prototyped case, check for....  */
+             if (stdarg_p (TREE_TYPE (decl)))
+               gen_unspecified_parameters_die (decl, subr_die);
+           }
+         else if (DECL_INITIAL (decl) == NULL_TREE)
            gen_unspecified_parameters_die (decl, subr_die);
        }
-      else if (DECL_INITIAL (decl) == NULL_TREE)
-       gen_unspecified_parameters_die (decl, subr_die);
+
+      /* Adjust DW_TAG_string_type DIEs if needed, now that all arguments
+        have DIEs.  */
+      if (string_types == &string_types_vec)
+       {
+         adjust_string_types ();
+         string_types = NULL;
+       }
     }
 
+  if (subr_die != old_die)
+    /* Add the calling convention attribute if requested.  */
+    add_calling_convention_attribute (subr_die, decl);
+
   /* Output Dwarf info for all of the stuff within the body of the function
-     (if it has one - it may be just a declaration).  */
-  outer_scope = DECL_INITIAL (decl);
+     (if it has one - it may be just a declaration).
 
-  /* OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent
+     OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent
      a function.  This BLOCK actually represents the outermost binding contour
      for the function, i.e. the contour in which the function's formal
      parameters and labels get declared. Curiously, it appears that the front
@@ -18829,6 +20991,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
      a BLOCK node representing the function's outermost pair of curly braces,
      and any blocks used for the base and member initializers of a C++
      constructor function.  */
+  tree outer_scope = DECL_INITIAL (decl);
   if (! declaration && outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
     {
       int call_site_note_count = 0;
@@ -18836,8 +20999,11 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 
       /* Emit a DW_TAG_variable DIE for a named return value.  */
       if (DECL_NAME (DECL_RESULT (decl)))
-       gen_decl_die (DECL_RESULT (decl), NULL, subr_die);
+       gen_decl_die (DECL_RESULT (decl), NULL, NULL, subr_die);
 
+      /* The first time through decls_for_scope we will generate the
+        DIEs for the locals.  The second time, we fill in the
+        location info.  */
       decls_for_scope (outer_scope, subr_die);
 
       if (call_arg_locations && !dwarf_strict)
@@ -18849,7 +21015,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
              rtx tloc = NULL_RTX, tlocc = NULL_RTX;
              rtx arg, next_arg;
 
-             for (arg = NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note);
+             for (arg = (ca_loc->call_arg_loc_note != NULL_RTX
+                         ? NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note)
+                         : NULL_RTX);
                   arg; arg = next_arg)
                {
                  dw_loc_descr_ref reg, val;
@@ -18872,18 +21040,23 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                    }
                  if (mode == VOIDmode || mode == BLKmode)
                    continue;
-                 if (XEXP (XEXP (arg, 0), 0) == pc_rtx)
-                   {
-                     gcc_assert (ca_loc->symbol_ref == NULL_RTX);
-                     tloc = XEXP (XEXP (arg, 0), 1);
-                     continue;
-                   }
-                 else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER
-                          && XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx)
+                 /* Get dynamic information about call target only if we
+                    have no static information: we cannot generate both
+                    DW_AT_abstract_origin and DW_AT_GNU_call_site_target
+                    attributes.  */
+                 if (ca_loc->symbol_ref == NULL_RTX)
                    {
-                     gcc_assert (ca_loc->symbol_ref == NULL_RTX);
-                     tlocc = XEXP (XEXP (arg, 0), 1);
-                     continue;
+                     if (XEXP (XEXP (arg, 0), 0) == pc_rtx)
+                       {
+                         tloc = XEXP (XEXP (arg, 0), 1);
+                         continue;
+                       }
+                     else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER
+                              && XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx)
+                       {
+                         tlocc = XEXP (XEXP (arg, 0), 1);
+                         continue;
+                       }
                    }
                  reg = NULL;
                  if (REG_P (XEXP (XEXP (arg, 0), 0)))
@@ -18989,10 +21162,6 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       call_site_count = -1;
       tail_call_site_count = -1;
     }
-
-  if (subr_die != old_die)
-    /* Add the calling convention attribute if requested.  */
-    add_calling_convention_attribute (subr_die, decl);
 }
 
 /* Returns a hash value for X (which really is a die_struct).  */
@@ -19012,6 +21181,33 @@ block_die_hasher::equal (die_struct *x, die_struct *y)
   return x->decl_id == y->decl_id && x->die_parent == y->die_parent;
 }
 
+/* Return TRUE if DECL, which may have been previously generated as
+   OLD_DIE, is a candidate for a DW_AT_specification.  DECLARATION is
+   true if decl (or its origin) is either an extern declaration or a
+   class/namespace scoped declaration.
+
+   The declare_in_namespace support causes us to get two DIEs for one
+   variable, both of which are declarations.  We want to avoid
+   considering one to be a specification, so we must test for
+   DECLARATION and DW_AT_declaration.  */
+static inline bool
+decl_will_get_specification_p (dw_die_ref old_die, tree decl, bool declaration)
+{
+  return (old_die && TREE_STATIC (decl) && !declaration
+         && get_AT_flag (old_die, DW_AT_declaration) == 1);
+}
+
+/* Return true if DECL is a local static.  */
+
+static inline bool
+local_function_static (tree decl)
+{
+  gcc_assert (TREE_CODE (decl) == VAR_DECL);
+  return TREE_STATIC (decl)
+    && DECL_CONTEXT (decl)
+    && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL;
+}
+
 /* Generate a DIE to represent a declared data object.
    Either DECL or ORIGIN must be non-null.  */
 
@@ -19024,7 +21220,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   tree ultimate_origin;
   dw_die_ref var_die;
   dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL;
-  dw_die_ref origin_die;
+  dw_die_ref origin_die = NULL;
   bool declaration = (DECL_EXTERNAL (decl_or_origin)
                      || class_or_namespace_scope_p (context_die));
   bool specialization_p = false;
@@ -19095,7 +21291,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
                 DW_TAG_common_block and DW_TAG_variable.  */
              loc = loc_list_from_tree (com_decl, 2, NULL);
            }
-          else if (DECL_EXTERNAL (decl))
+         else if (DECL_EXTERNAL (decl_or_origin))
            add_AT_flag (com_die, DW_AT_declaration, 1);
          if (want_pubnames ())
            add_pubname_string (cnam, com_die); /* ??? needed? */
@@ -19110,8 +21306,9 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
          remove_AT (com_die, DW_AT_declaration);
        }
       var_die = new_die (DW_TAG_variable, com_die, decl);
-      add_name_and_src_coords_attributes (var_die, decl);
-      add_type_attribute (var_die, TREE_TYPE (decl), decl_quals (decl),
+      add_name_and_src_coords_attributes (var_die, decl_or_origin);
+      add_type_attribute (var_die, TREE_TYPE (decl_or_origin),
+                         decl_quals (decl_or_origin), false,
                          context_die);
       add_AT_flag (var_die, DW_AT_external, 1);
       if (loc)
@@ -19133,18 +21330,45 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
            }
          add_AT_location_description (var_die, DW_AT_location, loc);
        }
-      else if (DECL_EXTERNAL (decl))
+      else if (DECL_EXTERNAL (decl_or_origin))
        add_AT_flag (var_die, DW_AT_declaration, 1);
-      equate_decl_number_to_die (decl, var_die);
+      if (decl)
+       equate_decl_number_to_die (decl, var_die);
       return;
     }
 
-  /* If the compiler emitted a definition for the DECL declaration
-     and if we already emitted a DIE for it, don't emit a second
-     DIE for it again. Allow re-declarations of DECLs that are
-     inside functions, though.  */
-  if (old_die && declaration && !local_scope_p (context_die))
-    return;
+  if (old_die)
+    {
+      if (declaration)
+       {
+         /* A declaration that has been previously dumped, needs no
+            further annotations, since it doesn't need location on
+            the second pass.  */
+         return;
+       }
+      else if (decl_will_get_specification_p (old_die, decl, declaration)
+              && !get_AT (old_die, DW_AT_specification))
+       {
+         /* Fall-thru so we can make a new variable die along with a
+            DW_AT_specification.  */
+       }
+      else if (origin && old_die->die_parent != context_die)
+       {
+         /* If we will be creating an inlined instance, we need a
+            new DIE that will get annotated with
+            DW_AT_abstract_origin.  Clear things so we can get a
+            new DIE.  */
+         gcc_assert (!DECL_ABSTRACT_P (decl));
+         old_die = NULL;
+       }
+      else
+       {
+         /* If a DIE was dumped early, it still needs location info.
+            Skip to where we fill the location bits.  */
+         var_die = old_die;
+         goto gen_variable_die_location;
+       }
+    }
 
   /* For static data members, the declaration in the class is supposed
      to have DW_TAG_member tag; the specification should still be
@@ -19154,7 +21378,6 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   else
     var_die = new_die (DW_TAG_variable, context_die, decl);
 
-  origin_die = NULL;
   if (origin != NULL)
     origin_die = add_abstract_origin_attribute (var_die, origin);
 
@@ -19165,14 +21388,8 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
      copy decls and set the DECL_ABSTRACT_P flag on them instead of
      sharing them.
 
-     ??? Duplicated blocks have been rewritten to use .debug_ranges.
-
-     ??? The declare_in_namespace support causes us to get two DIEs for one
-     variable, both of which are declarations.  We want to avoid considering
-     one to be a specification, so we must test that this DIE is not a
-     declaration.  */
-  else if (old_die && TREE_STATIC (decl) && ! declaration
-          && get_AT_flag (old_die, DW_AT_declaration) == 1)
+     ??? Duplicated blocks have been rewritten to use .debug_ranges.  */
+  else if (decl_will_get_specification_p (old_die, decl, declaration))
     {
       /* This is a definition of a C++ class level static.  */
       add_AT_specification (var_die, old_die);
@@ -19205,10 +21422,10 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
       tree type = TREE_TYPE (decl_or_origin);
 
       if (decl_by_reference_p (decl_or_origin))
-       add_type_attribute (var_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+       add_type_attribute (var_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
                            context_die);
       else
-       add_type_attribute (var_die, type, decl_quals (decl_or_origin),
+       add_type_attribute (var_die, type, decl_quals (decl_or_origin), false,
                            context_die);
     }
 
@@ -19226,9 +21443,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   if (declaration)
     add_AT_flag (var_die, DW_AT_declaration, 1);
 
-  if (decl && (DECL_ABSTRACT_P (decl) || declaration || old_die == NULL))
+  if (decl && (DECL_ABSTRACT_P (decl)
+              || !old_die || is_declaration_die (old_die)))
     equate_decl_number_to_die (decl, var_die);
 
+ gen_variable_die_location:
   if (! declaration
       && (! DECL_ABSTRACT_P (decl_or_origin)
          /* Local static vars are shared between all clones/inlines,
@@ -19241,13 +21460,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
         to add it again.  */
       && (origin_die == NULL || get_AT (origin_die, DW_AT_location) == NULL))
     {
-      if (TREE_CODE (decl_or_origin) == VAR_DECL && TREE_STATIC (decl_or_origin)
-          && !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl_or_origin)))
-       defer_location (decl_or_origin, var_die);
+      if (early_dwarf)
+       add_pubname (decl_or_origin, var_die);
       else
-        add_location_or_const_value_attribute (var_die, decl_or_origin,
-                                              decl == NULL, DW_AT_location);
-      add_pubname (decl_or_origin, var_die);
+       add_location_or_const_value_attribute (var_die, decl_or_origin,
+                                              decl == NULL);
     }
   else
     tree_add_const_value_attribute_for_decl (var_die, decl_or_origin);
@@ -19261,9 +21478,14 @@ gen_const_die (tree decl, dw_die_ref context_die)
   dw_die_ref const_die;
   tree type = TREE_TYPE (decl);
 
+  const_die = lookup_decl_die (decl);
+  if (const_die)
+    return;
+
   const_die = new_die (DW_TAG_constant, context_die, decl);
+  equate_decl_number_to_die (decl, const_die);
   add_name_and_src_coords_attributes (const_die, decl);
-  add_type_attribute (const_die, type, TYPE_QUAL_CONST, context_die);
+  add_type_attribute (const_die, type, TYPE_QUAL_CONST, false, context_die);
   if (TREE_PUBLIC (decl))
     add_AT_flag (const_die, DW_AT_external, 1);
   if (DECL_ARTIFICIAL (decl))
@@ -19277,14 +21499,20 @@ static void
 gen_label_die (tree decl, dw_die_ref context_die)
 {
   tree origin = decl_ultimate_origin (decl);
-  dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl);
+  dw_die_ref lbl_die = lookup_decl_die (decl);
   rtx insn;
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  if (origin != NULL)
-    add_abstract_origin_attribute (lbl_die, origin);
-  else
-    add_name_and_src_coords_attributes (lbl_die, decl);
+  if (!lbl_die)
+    {
+      lbl_die = new_die (DW_TAG_label, context_die, decl);
+      equate_decl_number_to_die (decl, lbl_die);
+
+      if (origin != NULL)
+       add_abstract_origin_attribute (lbl_die, origin);
+      else
+       add_name_and_src_coords_attributes (lbl_die, decl);
+    }
 
   if (DECL_ABSTRACT_P (decl))
     equate_decl_number_to_die (decl, lbl_die);
@@ -19351,7 +21579,7 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
     {
       tree chain, superblock = NULL_TREE;
       dw_die_ref pdie;
-      dw_attr_ref attr = NULL;
+      dw_attr_node *attr = NULL;
 
       if (inlined_function_outer_scope_p (stmt))
        {
@@ -19369,7 +21597,7 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
           BLOCK_SAME_RANGE (chain);
           chain = BLOCK_SUPERCONTEXT (chain))
        {
-         dw_attr_ref new_attr;
+         dw_attr_node *new_attr;
 
          pdie = pdie->die_parent;
          if (pdie == NULL)
@@ -19438,17 +21666,59 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
 static void
 gen_lexical_block_die (tree stmt, dw_die_ref context_die)
 {
-  dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+  dw_die_ref old_die = BLOCK_DIE (stmt);
+  dw_die_ref stmt_die = NULL;
+  if (!old_die)
+    {
+      stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+      BLOCK_DIE (stmt) = stmt_die;
+    }
 
-  if (call_arg_locations)
+  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_map.length () <= BLOCK_NUMBER (stmt))
-       block_map.safe_grow_cleared (BLOCK_NUMBER (stmt) + 1);
-      block_map[BLOCK_NUMBER (stmt)] = stmt_die;
+      /* If this is an inlined instance, create a new lexical die for
+        anything below to attach DW_AT_abstract_origin to.  */
+      if (old_die)
+       {
+         stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+         BLOCK_DIE (stmt) = stmt_die;
+         old_die = NULL;
+       }
+
+      tree origin = block_ultimate_origin (stmt);
+      if (origin != NULL_TREE && origin != stmt)
+       add_abstract_origin_attribute (stmt_die, origin);
     }
 
-  if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
-    add_high_low_attributes (stmt, stmt_die);
+  if (old_die)
+    stmt_die = old_die;
+
+  /* A non abstract block whose blocks have already been reordered
+     should have the instruction range for this block.  If so, set the
+     high/low attributes.  */
+  if (!early_dwarf && !BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
+    {
+      gcc_assert (stmt_die);
+      add_high_low_attributes (stmt, stmt_die);
+    }
 
   decls_for_scope (stmt, stmt_die);
 }
@@ -19466,6 +21736,10 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die)
 
   decl = block_ultimate_origin (stmt);
 
+  /* Make sure any inlined functions are known to be inlineable.  */
+  gcc_checking_assert (DECL_ABSTRACT_P (decl)
+                      || cgraph_function_possibly_inlined_p (decl));
+
   /* Emit info for the abstract instance first, if we haven't yet.  We
      must emit this even if the block is abstract, otherwise when we
      emit the block below (or elsewhere), we may end up trying to emit
@@ -19478,11 +21752,7 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die)
        = new_die (DW_TAG_inlined_subroutine, context_die, stmt);
 
       if (call_arg_locations)
-       {
-         if (block_map.length () <= BLOCK_NUMBER (stmt))
-           block_map.safe_grow_cleared (BLOCK_NUMBER (stmt) + 1);
-         block_map[BLOCK_NUMBER (stmt)] = subr_die;
-       }
+       BLOCK_DIE (stmt) = subr_die;
       add_abstract_origin_attribute (subr_die, decl);
       if (TREE_ASM_WRITTEN (stmt))
         add_high_low_attributes (stmt, subr_die);
@@ -19492,10 +21762,11 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die)
     }
 }
 
-/* Generate a DIE for a field in a record, or structure.  */
+/* Generate a DIE for a field in a record, or structure.  CTX is required: see
+   the comment for VLR_CONTEXT.  */
 
 static void
-gen_field_die (tree decl, dw_die_ref context_die)
+gen_field_die (tree decl, struct vlr_context *ctx, dw_die_ref context_die)
 {
   dw_die_ref decl_die;
 
@@ -19504,18 +21775,24 @@ gen_field_die (tree decl, dw_die_ref context_die)
 
   decl_die = new_die (DW_TAG_member, context_die, decl);
   add_name_and_src_coords_attributes (decl_die, decl);
-  add_type_attribute (decl_die, member_declared_type (decl),
-                     decl_quals (decl), context_die);
+  add_type_attribute (decl_die, member_declared_type (decl), decl_quals (decl),
+                     TYPE_REVERSE_STORAGE_ORDER (DECL_FIELD_CONTEXT (decl)),
+                     context_die);
 
   if (DECL_BIT_FIELD_TYPE (decl))
     {
       add_byte_size_attribute (decl_die, decl);
       add_bit_size_attribute (decl_die, decl);
-      add_bit_offset_attribute (decl_die, decl);
+      add_bit_offset_attribute (decl_die, decl, ctx);
     }
 
+  /* If we have a variant part offset, then we are supposed to process a member
+     of a QUAL_UNION_TYPE, which is how we represent variant parts in
+     trees.  */
+  gcc_assert (ctx->variant_part_offset == NULL_TREE
+             || TREE_CODE (DECL_FIELD_CONTEXT (decl)) != QUAL_UNION_TYPE);
   if (TREE_CODE (DECL_FIELD_CONTEXT (decl)) != UNION_TYPE)
-    add_data_member_location_attribute (decl_die, decl);
+    add_data_member_location_attribute (decl_die, decl, ctx);
 
   if (DECL_ARTIFICIAL (decl))
     add_AT_flag (decl_die, DW_AT_artificial, 1);
@@ -19539,7 +21816,7 @@ gen_pointer_type_die (tree type, dw_die_ref context_die)
     = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type);
 
   equate_type_number_to_die (type, ptr_die);
-  add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+  add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
                      context_die);
   add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
 }
@@ -19560,7 +21837,7 @@ gen_reference_type_die (tree type, dw_die_ref context_die)
     ref_die = new_die (DW_TAG_reference_type, scope_die, type);
 
   equate_type_number_to_die (type, ref_die);
-  add_type_attribute (ref_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+  add_type_attribute (ref_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
                      context_die);
   add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
 }
@@ -19578,12 +21855,10 @@ gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
   equate_type_number_to_die (type, ptr_die);
   add_AT_die_ref (ptr_die, DW_AT_containing_type,
                  lookup_type_die (TYPE_OFFSET_BASETYPE (type)));
-  add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+  add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
                      context_die);
 }
 
-typedef const char *dchar_p; /* For DEF_VEC_P.  */
-
 static char *producer_string;
 
 /* Return a heap allocated producer string including command line options
@@ -19593,7 +21868,7 @@ static char *
 gen_producer_string (void)
 {
   size_t j;
-  auto_vec<dchar_p> switches;
+  auto_vec<const char *> switches;
   const char *language_string = lang_hooks.name;
   char *producer, *tail;
   const char *p;
@@ -19634,6 +21909,9 @@ gen_producer_string (void)
       case OPT_nostdinc:
       case OPT_nostdinc__:
       case OPT_fpreprocessed:
+      case OPT_fltrans_output_list_:
+      case OPT_fresolution_:
+      case OPT_fdebug_prefix_map_:
        /* Ignore these.  */
        continue;
       default:
@@ -19840,12 +22118,15 @@ gen_compile_unit_die (const char *filename)
 /* Generate the DIE for a base class.  */
 
 static void
-gen_inheritance_die (tree binfo, tree access, dw_die_ref context_die)
+gen_inheritance_die (tree binfo, tree access, tree type,
+                    dw_die_ref context_die)
 {
   dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo);
+  struct vlr_context ctx = { type, NULL };
 
-  add_type_attribute (die, BINFO_TYPE (binfo), TYPE_UNQUALIFIED, context_die);
-  add_data_member_location_attribute (die, binfo);
+  add_type_attribute (die, BINFO_TYPE (binfo), TYPE_UNQUALIFIED, false,
+                     context_die);
+  add_data_member_location_attribute (die, binfo, &ctx);
 
   if (BINFO_VIRTUAL_P (binfo))
     add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
@@ -19866,6 +22147,407 @@ gen_inheritance_die (tree binfo, tree access, dw_die_ref context_die)
     add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_private);
 }
 
+/* Return whether DECL is a FIELD_DECL that represents the variant part of a
+   structure.  */
+static bool
+is_variant_part (tree decl)
+{
+  return (TREE_CODE (decl) == FIELD_DECL
+         && TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE);
+}
+
+/* Check that OPERAND is a reference to a field in STRUCT_TYPE.  If it is,
+   return the FIELD_DECL.  Return NULL_TREE otherwise.  */
+
+static tree
+analyze_discr_in_predicate (tree operand, tree struct_type)
+{
+  bool continue_stripping = true;
+  while (continue_stripping)
+    switch (TREE_CODE (operand))
+      {
+      CASE_CONVERT:
+       operand = TREE_OPERAND (operand, 0);
+       break;
+      default:
+       continue_stripping = false;
+       break;
+      }
+
+  /* Match field access to members of struct_type only.  */
+  if (TREE_CODE (operand) == COMPONENT_REF
+      && TREE_CODE (TREE_OPERAND (operand, 0)) == PLACEHOLDER_EXPR
+      && TREE_TYPE (TREE_OPERAND (operand, 0)) == struct_type
+      && TREE_CODE (TREE_OPERAND (operand, 1)) == FIELD_DECL)
+    return TREE_OPERAND (operand, 1);
+  else
+    return NULL_TREE;
+}
+
+/* Check that SRC is a constant integer that can be represented as a native
+   integer constant (either signed or unsigned).  If so, store it into DEST and
+   return true.  Return false otherwise. */
+
+static bool
+get_discr_value (tree src, dw_discr_value *dest)
+{
+  bool is_unsigned = TYPE_UNSIGNED (TREE_TYPE (src));
+
+  if (TREE_CODE (src) != INTEGER_CST
+      || !(is_unsigned ? tree_fits_uhwi_p (src) : tree_fits_shwi_p (src)))
+    return false;
+
+  dest->pos = is_unsigned;
+  if (is_unsigned)
+    dest->v.uval = tree_to_uhwi (src);
+  else
+    dest->v.sval = tree_to_shwi (src);
+
+  return true;
+}
+
+/* Try to extract synthetic properties out of VARIANT_PART_DECL, which is a
+   FIELD_DECL in STRUCT_TYPE that represents a variant part.  If unsuccessful,
+   store NULL_TREE in DISCR_DECL.  Otherwise:
+
+     - store the discriminant field in STRUCT_TYPE that controls the variant
+       part to *DISCR_DECL
+
+     - put in *DISCR_LISTS_P an array where for each variant, the item
+       represents the corresponding matching list of discriminant values.
+
+     - put in *DISCR_LISTS_LENGTH the number of variants, which is the size of
+       the above array.
+
+   Note that when the array is allocated (i.e. when the analysis is
+   successful), it is up to the caller to free the array.  */
+
+static void
+analyze_variants_discr (tree variant_part_decl,
+                       tree struct_type,
+                       tree *discr_decl,
+                       dw_discr_list_ref **discr_lists_p,
+                       unsigned *discr_lists_length)
+{
+  tree variant_part_type = TREE_TYPE (variant_part_decl);
+  tree variant;
+  dw_discr_list_ref *discr_lists;
+  unsigned i;
+
+  /* Compute how many variants there are in this variant part.  */
+  *discr_lists_length = 0;
+  for (variant = TYPE_FIELDS (variant_part_type);
+       variant != NULL_TREE;
+       variant = DECL_CHAIN (variant))
+    ++*discr_lists_length;
+
+  *discr_decl = NULL_TREE;
+  *discr_lists_p
+    = (dw_discr_list_ref *) xcalloc (*discr_lists_length,
+                                    sizeof (**discr_lists_p));
+  discr_lists = *discr_lists_p;
+
+  /* And then analyze all variants to extract discriminant information for all
+     of them.  This analysis is conservative: as soon as we detect something we
+     do not support, abort everything and pretend we found nothing.  */
+  for (variant = TYPE_FIELDS (variant_part_type), i = 0;
+       variant != NULL_TREE;
+       variant = DECL_CHAIN (variant), ++i)
+    {
+      tree match_expr = DECL_QUALIFIER (variant);
+
+      /* Now, try to analyze the predicate and deduce a discriminant for
+        it.  */
+      if (match_expr == boolean_true_node)
+       /* Typically happens for the default variant: it matches all cases that
+          previous variants rejected.  Don't output any matching value for
+          this one.  */
+       continue;
+
+      /* The following loop tries to iterate over each discriminant
+        possibility: single values or ranges.  */
+      while (match_expr != NULL_TREE)
+       {
+         tree next_round_match_expr;
+         tree candidate_discr = NULL_TREE;
+         dw_discr_list_ref new_node = NULL;
+
+         /* Possibilities are matched one after the other by nested
+            TRUTH_ORIF_EXPR expressions.  Process the current possibility and
+            continue with the rest at next iteration.  */
+         if (TREE_CODE (match_expr) == TRUTH_ORIF_EXPR)
+           {
+             next_round_match_expr = TREE_OPERAND (match_expr, 0);
+             match_expr = TREE_OPERAND (match_expr, 1);
+           }
+         else
+           next_round_match_expr = NULL_TREE;
+
+         if (match_expr == boolean_false_node)
+           /* This sub-expression matches nothing: just wait for the next
+              one.  */
+           ;
+
+         else if (TREE_CODE (match_expr) == EQ_EXPR)
+           {
+             /* We are matching:  <discr_field> == <integer_cst>
+                This sub-expression matches a single value.  */
+             tree integer_cst = TREE_OPERAND (match_expr, 1);
+
+             candidate_discr
+              = analyze_discr_in_predicate (TREE_OPERAND (match_expr, 0),
+                                            struct_type);
+
+             new_node = ggc_cleared_alloc<dw_discr_list_node> ();
+             if (!get_discr_value (integer_cst,
+                                   &new_node->dw_discr_lower_bound))
+               goto abort;
+             new_node->dw_discr_range = false;
+           }
+
+         else if (TREE_CODE (match_expr) == TRUTH_ANDIF_EXPR)
+           {
+             /* We are matching:
+                  <discr_field> > <integer_cst>
+                  && <discr_field> < <integer_cst>.
+                This sub-expression matches the range of values between the
+                two matched integer constants.  Note that comparisons can be
+                inclusive or exclusive.  */
+             tree candidate_discr_1, candidate_discr_2;
+             tree lower_cst, upper_cst;
+             bool lower_cst_included, upper_cst_included;
+             tree lower_op = TREE_OPERAND (match_expr, 0);
+             tree upper_op = TREE_OPERAND (match_expr, 1);
+
+             /* When the comparison is exclusive, the integer constant is not
+                the discriminant range bound we are looking for: we will have
+                to increment or decrement it.  */
+             if (TREE_CODE (lower_op) == GE_EXPR)
+               lower_cst_included = true;
+             else if (TREE_CODE (lower_op) == GT_EXPR)
+               lower_cst_included = false;
+             else
+               goto abort;
+
+             if (TREE_CODE (upper_op) == LE_EXPR)
+               upper_cst_included = true;
+             else if (TREE_CODE (upper_op) == LT_EXPR)
+               upper_cst_included = false;
+             else
+               goto abort;
+
+             /* Extract the discriminant from the first operand and check it
+                is consistant with the same analysis in the second
+                operand.  */
+             candidate_discr_1
+               = analyze_discr_in_predicate (TREE_OPERAND (lower_op, 0),
+                                             struct_type);
+             candidate_discr_2
+               = analyze_discr_in_predicate (TREE_OPERAND (upper_op, 0),
+                                             struct_type);
+             if (candidate_discr_1 == candidate_discr_2)
+               candidate_discr = candidate_discr_1;
+             else
+               goto abort;
+
+             /* Extract bounds from both.  */
+             new_node = ggc_cleared_alloc<dw_discr_list_node> ();
+             lower_cst = TREE_OPERAND (lower_op, 1);
+             upper_cst = TREE_OPERAND (upper_op, 1);
+
+             if (!lower_cst_included)
+               lower_cst
+                 = fold (build2 (PLUS_EXPR, TREE_TYPE (lower_cst),
+                                 lower_cst,
+                                 build_int_cst (TREE_TYPE (lower_cst), 1)));
+             if (!upper_cst_included)
+               upper_cst
+                 = fold (build2 (MINUS_EXPR, TREE_TYPE (upper_cst),
+                                 upper_cst,
+                                 build_int_cst (TREE_TYPE (upper_cst), 1)));
+
+             if (!get_discr_value (lower_cst,
+                                   &new_node->dw_discr_lower_bound)
+                 || !get_discr_value (upper_cst,
+                                      &new_node->dw_discr_upper_bound))
+               goto abort;
+
+             new_node->dw_discr_range = true;
+           }
+
+         else
+           /* Unsupported sub-expression: we cannot determine the set of
+              matching discriminant values.  Abort everything.  */
+           goto abort;
+
+         /* If the discriminant info is not consistant with what we saw so
+            far, consider the analysis failed and abort everything.  */
+         if (candidate_discr == NULL_TREE
+             || (*discr_decl != NULL_TREE && candidate_discr != *discr_decl))
+           goto abort;
+         else
+           *discr_decl = candidate_discr;
+
+         if (new_node != NULL)
+           {
+             new_node->dw_discr_next = discr_lists[i];
+             discr_lists[i] = new_node;
+           }
+         match_expr = next_round_match_expr;
+       }
+    }
+
+  /* If we reach this point, we could match everything we were interested
+     in.  */
+  return;
+
+abort:
+  /* Clean all data structure and return no result.  */
+  free (*discr_lists_p);
+  *discr_lists_p = NULL;
+  *discr_decl = NULL_TREE;
+}
+
+/* Generate a DIE to represent VARIANT_PART_DECL, a variant part that is part
+   of STRUCT_TYPE, a record type.  This new DIE is emitted as the next child
+   under CONTEXT_DIE.
+
+   Variant parts are supposed to be implemented as a FIELD_DECL whose type is a
+   QUAL_UNION_TYPE: this is the VARIANT_PART_DECL parameter.  The members for
+   this type, which are record types, represent the available variants and each
+   has a DECL_QUALIFIER attribute.  The discriminant and the discriminant
+   values are inferred from these attributes.
+
+   In trees, the offsets for the fields inside these sub-records are relative
+   to the variant part itself, whereas the corresponding DIEs should have
+   offset attributes that are relative to the embedding record base address.
+   This is why the caller must provide a VARIANT_PART_OFFSET expression: it
+   must be an expression that computes the offset of the variant part to
+   describe in DWARF.  */
+
+static void
+gen_variant_part (tree variant_part_decl, struct vlr_context *vlr_ctx,
+                 dw_die_ref context_die)
+{
+  const tree variant_part_type = TREE_TYPE (variant_part_decl);
+  tree variant_part_offset = vlr_ctx->variant_part_offset;
+  struct loc_descr_context ctx = {
+    vlr_ctx->struct_type, /* context_type */
+    NULL_TREE,           /* base_decl */
+    NULL                 /* dpi */
+  };
+
+  /* The FIELD_DECL node in STRUCT_TYPE that acts as the discriminant, or
+     NULL_TREE if there is no such field.  */
+  tree discr_decl = NULL_TREE;
+  dw_discr_list_ref *discr_lists;
+  unsigned discr_lists_length = 0;
+  unsigned i;
+
+  dw_die_ref dwarf_proc_die = NULL;
+  dw_die_ref variant_part_die
+    = new_die (DW_TAG_variant_part, context_die, variant_part_type);
+
+  equate_decl_number_to_die (variant_part_decl, variant_part_die);
+
+  analyze_variants_discr (variant_part_decl, vlr_ctx->struct_type,
+                         &discr_decl, &discr_lists, &discr_lists_length);
+
+  if (discr_decl != NULL_TREE)
+    {
+      dw_die_ref discr_die = lookup_decl_die (discr_decl);
+
+      if (discr_die)
+       add_AT_die_ref (variant_part_die, DW_AT_discr, discr_die);
+      else
+       /* We have no DIE for the discriminant, so just discard all
+          discrimimant information in the output.  */
+       discr_decl = NULL_TREE;
+    }
+
+  /* If the offset for this variant part is more complex than a constant,
+     create a DWARF procedure for it so that we will not have to generate DWARF
+     expressions for it for each member.  */
+  if (TREE_CODE (variant_part_offset) != INTEGER_CST
+      && (dwarf_version >= 3 || !dwarf_strict))
+    {
+      const tree dwarf_proc_fndecl
+        = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, NULL_TREE,
+                     build_function_type (TREE_TYPE (variant_part_offset),
+                                          NULL_TREE));
+      const tree dwarf_proc_call = build_call_expr (dwarf_proc_fndecl, 0);
+      const dw_loc_descr_ref dwarf_proc_body
+        = loc_descriptor_from_tree (variant_part_offset, 0, &ctx);
+
+      dwarf_proc_die = new_dwarf_proc_die (dwarf_proc_body,
+                                          dwarf_proc_fndecl, context_die);
+      if (dwarf_proc_die != NULL)
+       variant_part_offset = dwarf_proc_call;
+    }
+
+  /* Output DIEs for all variants.  */
+  i = 0;
+  for (tree variant = TYPE_FIELDS (variant_part_type);
+       variant != NULL_TREE;
+       variant = DECL_CHAIN (variant), ++i)
+    {
+      tree variant_type = TREE_TYPE (variant);
+      dw_die_ref variant_die;
+
+      /* All variants (i.e. members of a variant part) are supposed to be
+        encoded as structures.  Sub-variant parts are QUAL_UNION_TYPE fields
+        under these records.  */
+      gcc_assert (TREE_CODE (variant_type) == RECORD_TYPE);
+
+      variant_die = new_die (DW_TAG_variant, variant_part_die, variant_type);
+      equate_decl_number_to_die (variant, variant_die);
+
+      /* Output discriminant values this variant matches, if any.  */
+      if (discr_decl == NULL || discr_lists[i] == NULL)
+       /* In the case we have discriminant information at all, this is
+          probably the default variant: as the standard says, don't
+          output any discriminant value/list attribute.  */
+       ;
+      else if (discr_lists[i]->dw_discr_next == NULL
+              && !discr_lists[i]->dw_discr_range)
+       /* If there is only one accepted value, don't bother outputting a
+          list.  */
+       add_discr_value (variant_die, &discr_lists[i]->dw_discr_lower_bound);
+      else
+       add_discr_list (variant_die, discr_lists[i]);
+
+      for (tree member = TYPE_FIELDS (variant_type);
+          member != NULL_TREE;
+          member = DECL_CHAIN (member))
+       {
+         struct vlr_context vlr_sub_ctx = {
+           vlr_ctx->struct_type, /* struct_type */
+           NULL                  /* variant_part_offset */
+         };
+         if (is_variant_part (member))
+           {
+             /* All offsets for fields inside variant parts are relative to
+                the top-level embedding RECORD_TYPE's base address.  On the
+                other hand, offsets in GCC's types are relative to the
+                nested-most variant part.  So we have to sum offsets each time
+                we recurse.  */
+
+             vlr_sub_ctx.variant_part_offset
+               = fold (build2 (PLUS_EXPR, TREE_TYPE (variant_part_offset),
+                               variant_part_offset, byte_position (member)));
+             gen_variant_part (member, &vlr_sub_ctx, variant_die);
+           }
+         else
+           {
+             vlr_sub_ctx.variant_part_offset = variant_part_offset;
+             gen_decl_die (member, NULL, &vlr_sub_ctx, variant_die);
+           }
+       }
+    }
+
+  free (discr_lists);
+}
+
 /* Generate a DIE for a class member.  */
 
 static void
@@ -19897,12 +22579,15 @@ gen_member_die (tree type, dw_die_ref context_die)
       for (i = 0; BINFO_BASE_ITERATE (binfo, i, base); i++)
        gen_inheritance_die (base,
                             (accesses ? (*accesses)[i] : access_public_node),
+                            type,
                             context_die);
     }
 
   /* Now output info about the data members and type members.  */
   for (member = TYPE_FIELDS (type); member; member = DECL_CHAIN (member))
     {
+      struct vlr_context vlr_ctx = { type, NULL_TREE };
+
       /* If we thought we were generating minimal debug info for TYPE
         and then changed our minds, some of the member declarations
         may have already been defined.  Don't define them again, but
@@ -19911,23 +22596,43 @@ gen_member_die (tree type, dw_die_ref context_die)
       child = lookup_decl_die (member);
       if (child)
        splice_child_die (context_die, child);
+
+      /* Do not generate standard DWARF for variant parts if we are generating
+        the corresponding GNAT encodings: DIEs generated for both would
+        conflict in our mappings.  */
+      else if (is_variant_part (member)
+              && gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL)
+       {
+         vlr_ctx.variant_part_offset = byte_position (member);
+         gen_variant_part (member, &vlr_ctx, context_die);
+       }
       else
-       gen_decl_die (member, NULL, context_die);
+       {
+         vlr_ctx.variant_part_offset = NULL_TREE;
+         gen_decl_die (member, NULL, &vlr_ctx, context_die);
+       }
     }
 
+  /* We do not keep type methods in type variants.  */
+  gcc_assert (TYPE_MAIN_VARIANT (type) == type);
   /* Now output info about the function members (if any).  */
-  for (member = TYPE_METHODS (type); member; member = DECL_CHAIN (member))
-    {
-      /* Don't include clones in the member list.  */
-      if (DECL_ABSTRACT_ORIGIN (member))
-       continue;
+  if (TYPE_METHODS (type) != error_mark_node)
+    for (member = TYPE_METHODS (type); member; member = DECL_CHAIN (member))
+      {
+       /* Don't include clones in the member list.  */
+       if (DECL_ABSTRACT_ORIGIN (member))
+         continue;
+       /* Nor constructors for anonymous classes.  */
+       if (DECL_ARTIFICIAL (member)
+           && dwarf2_name (member, 0) == NULL)
+         continue;
 
-      child = lookup_decl_die (member);
-      if (child)
-       splice_child_die (context_die, child);
-      else
-       gen_decl_die (member, NULL, context_die);
-    }
+       child = lookup_decl_die (member);
+       if (child)
+         splice_child_die (context_die, child);
+       else
+         gen_decl_die (member, NULL, NULL, context_die);
+      }
 }
 
 /* Generate a DIE for a structure or union type.  If TYPE_DECL_SUPPRESS_DEBUG
@@ -19938,6 +22643,18 @@ static void
 gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
                                enum debug_info_usage usage)
 {
+  if (TREE_ASM_WRITTEN (type))
+    {
+      /* Fill in the bound of variable-length fields in late dwarf if
+        still incomplete.  */
+      if (!early_dwarf && variably_modified_type_p (type, NULL))
+       for (tree member = TYPE_FIELDS (type);
+            member;
+            member = DECL_CHAIN (member))
+         fill_variable_array_bounds (TREE_TYPE (member));
+      return;
+    }
+
   dw_die_ref type_die = lookup_type_die (type);
   dw_die_ref scope_die = 0;
   int nested = 0;
@@ -20041,7 +22758,8 @@ gen_subroutine_type_die (tree type, dw_die_ref context_die)
 
   equate_type_number_to_die (type, subr_die);
   add_prototyped_attribute (subr_die, type);
-  add_type_attribute (subr_die, return_type, TYPE_UNQUALIFIED, context_die);
+  add_type_attribute (subr_die, return_type, TYPE_UNQUALIFIED, false,
+                     context_die);
   gen_formal_types_die (type, subr_die);
 
   if (get_AT (subr_die, DW_AT_name))
@@ -20057,7 +22775,11 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
   tree origin;
 
   if (TREE_ASM_WRITTEN (decl))
-    return;
+    {
+      if (DECL_ORIGINAL_TYPE (decl))
+       fill_variable_array_bounds (DECL_ORIGINAL_TYPE (decl));
+      return;
+    }
 
   TREE_ASM_WRITTEN (decl) = 1;
   type_die = new_die (DW_TAG_typedef, context_die, decl);
@@ -20073,6 +22795,9 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
        {
          type = DECL_ORIGINAL_TYPE (decl);
 
+         if (type == error_mark_node)
+           return;
+
          gcc_assert (type != TREE_TYPE (decl));
          equate_type_number_to_die (TREE_TYPE (decl), type_die);
        }
@@ -20080,6 +22805,9 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
        {
          type = TREE_TYPE (decl);
 
+         if (type == error_mark_node)
+           return;
+
          if (is_naming_typedef_decl (TYPE_NAME (type)))
            {
              /* Here, we are in the case of decl being a typedef naming
@@ -20105,11 +22833,12 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
                 is the name of the typedef decl naming the anonymous
                 struct.  This greatly eases the work of consumers of
                 this debug info.  */
-             add_linkage_attr (lookup_type_die (type), decl);
+             add_linkage_name_raw (lookup_type_die (type), decl);
            }
        }
 
-      add_type_attribute (type_die, type, decl_quals (decl), context_die);
+      add_type_attribute (type_die, type, decl_quals (decl), false,
+                         context_die);
 
       if (is_naming_typedef_decl (decl))
        /* We want that all subsequent calls to lookup_type_die with
@@ -20140,13 +22869,15 @@ gen_tagged_type_die (tree type,
       || !is_tagged_type (type))
     return;
 
+  if (TREE_ASM_WRITTEN (type))
+    need_pop = 0;
   /* If this is a nested type whose containing class hasn't been written
      out yet, writing it out will cover this one, too.  This does not apply
      to instantiations of member class templates; they need to be added to
      the containing class as they are generated.  FIXME: This hurts the
      idea of combining type decls from multiple TUs, since we can't predict
      what set of template instantiations we'll get.  */
-  if (TYPE_CONTEXT (type)
+  else if (TYPE_CONTEXT (type)
       && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
       && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
     {
@@ -20208,6 +22939,9 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   if (type == NULL_TREE || type == error_mark_node)
     return;
 
+  if (flag_checking && type)
+     verify_type (type);
+
   if (TYPE_NAME (type) != NULL_TREE
       && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
       && is_redundant_typedef (TYPE_NAME (type))
@@ -20233,7 +22967,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
 
       TREE_ASM_WRITTEN (type) = 1;
 
-      gen_decl_die (TYPE_NAME (type), NULL, context_die);
+      gen_decl_die (TYPE_NAME (type), NULL, NULL, context_die);
       return;
     }
 
@@ -20246,17 +22980,18 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       if (DECL_CONTEXT (TYPE_NAME (type))
          && TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL)
        context_die = get_context_die (DECL_CONTEXT (TYPE_NAME (type)));
-      
-      gen_decl_die (TYPE_NAME (type), NULL, context_die);
+
+      gen_decl_die (TYPE_NAME (type), NULL, NULL, context_die);
       return;
     }
 
   /* We are going to output a DIE to represent the unqualified version
      of this type (i.e. without any const or volatile qualifiers) so
      get the main variant (i.e. the unqualified version) of this type
-     now.  (Vectors are special because the debugging info is in the
+     now.  (Vectors and arrays are special because the debugging info is in the
      cloned type itself).  */
-  if (TREE_CODE (type) != VECTOR_TYPE)
+  if (TREE_CODE (type) != VECTOR_TYPE
+      && TREE_CODE (type) != ARRAY_TYPE)
     type = type_main_variant (type);
 
   /* If this is an array type with hidden descriptor, handle it first.  */
@@ -20266,6 +23001,10 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       memset (&info, 0, sizeof (info));
       if (lang_hooks.types.get_array_descr_info (type, &info))
        {
+         /* Fortran sometimes emits array types with no dimension.  */
+         gcc_assert (info.ndimensions >= 0
+                     && (info.ndimensions
+                         <= DWARF2OUT_ARRAY_DESCR_INFO_MAX_DIMEN));
          gen_descr_array_type_die (type, &info, context_die);
          TREE_ASM_WRITTEN (type) = 1;
          return;
@@ -20273,7 +23012,18 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
     }
 
   if (TREE_ASM_WRITTEN (type))
-    return;
+    {
+      /* Variable-length types may be incomplete even if
+        TREE_ASM_WRITTEN.  For such types, fall through to
+        gen_array_type_die() and possibly fill in
+        DW_AT_{upper,lower}_bound attributes.  */
+      if ((TREE_CODE (type) != ARRAY_TYPE
+          && TREE_CODE (type) != RECORD_TYPE
+          && TREE_CODE (type) != UNION_TYPE
+          && TREE_CODE (type) != QUAL_UNION_TYPE)
+         || !variably_modified_type_p (type, NULL))
+       return;
+    }
 
   switch (TREE_CODE (type))
     {
@@ -20325,9 +23075,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       break;
 
     case ARRAY_TYPE:
-      gen_array_type_die (type, context_die);
-      break;
-
     case VECTOR_TYPE:
       gen_array_type_die (type, context_die);
       break;
@@ -20389,7 +23136,16 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
 static void
 gen_type_die (tree type, dw_die_ref context_die)
 {
-  gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
+  if (type != error_mark_node)
+    {
+      gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
+      if (flag_checking)
+       {
+         dw_die_ref die = lookup_type_die (type);
+         if (die)
+           check_die (die);
+       }
+    }
 }
 
 /* Generate a DW_TAG_lexical_block DIE followed by DIEs to represent all of the
@@ -20498,10 +23254,13 @@ process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die)
   if (die != NULL && die->die_parent == NULL)
     add_child_die (context_die, die);
   else if (TREE_CODE (decl_or_origin) == IMPORTED_DECL)
-    dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
-                                        stmt, context_die);
+    {
+      if (early_dwarf)
+       dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
+                                            stmt, context_die);
+    }
   else
-    gen_decl_die (decl, origin, context_die);
+    gen_decl_die (decl, origin, NULL, context_die);
 }
 
 /* Generate all of the decls declared within a given scope and (recursively)
@@ -20545,11 +23304,11 @@ decls_for_scope (tree stmt, dw_die_ref context_die)
 
 /* Is this a typedef we can avoid emitting?  */
 
-static inline int
+bool
 is_redundant_typedef (const_tree decl)
 {
   if (TYPE_DECL_IS_STUB (decl))
-    return 1;
+    return true;
 
   if (DECL_ARTIFICIAL (decl)
       && DECL_CONTEXT (decl)
@@ -20557,9 +23316,9 @@ is_redundant_typedef (const_tree decl)
       && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
       && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
     /* Also ignore the artificial member typedef for the class name.  */
-    return 1;
+    return true;
 
-  return 0;
+  return false;
 }
 
 /* Return TRUE if TYPE is a typedef that names a type for linkage
@@ -20577,6 +23336,7 @@ is_naming_typedef_decl (const_tree decl)
 {
   if (decl == NULL_TREE
       || TREE_CODE (decl) != TYPE_DECL
+      || DECL_NAMELESS (decl)
       || !is_tagged_type (TREE_TYPE (decl))
       || DECL_IS_BUILTIN (decl)
       || is_redundant_typedef (decl)
@@ -20592,6 +23352,28 @@ is_naming_typedef_decl (const_tree decl)
              != TYPE_NAME (TREE_TYPE (decl))));
 }
 
+/* Looks up the DIE for a context.  */
+
+static inline dw_die_ref
+lookup_context_die (tree context)
+{
+  if (context)
+    {
+      /* Find die that represents this context.  */
+      if (TYPE_P (context))
+       {
+         context = TYPE_MAIN_VARIANT (context);
+         dw_die_ref ctx = lookup_type_die (context);
+         if (!ctx)
+           return NULL;
+         return strip_naming_typedef (context, ctx);
+       }
+      else
+       return lookup_decl_die (context);
+    }
+  return comp_unit_die ();
+}
+
 /* Returns the DIE for a context.  */
 
 static inline dw_die_ref
@@ -20645,7 +23427,7 @@ force_decl_die (tree decl)
           gen_decl_die() call.  */
          saved_external_flag = DECL_EXTERNAL (decl);
          DECL_EXTERNAL (decl) = 1;
-         gen_decl_die (decl, NULL, context_die);
+         gen_decl_die (decl, NULL, NULL, context_die);
          DECL_EXTERNAL (decl) = saved_external_flag;
          break;
 
@@ -20688,7 +23470,7 @@ force_type_die (tree type)
       dw_die_ref context_die = get_context_die (TYPE_CONTEXT (type));
 
       type_die = modified_type_die (type, TYPE_QUALS_NO_ADDR_SPACE (type),
-                                   context_die);
+                                   false, context_die);
       gcc_assert (type_die);
     }
   return type_die;
@@ -20713,7 +23495,9 @@ setup_namespace_context (tree thing, dw_die_ref context_die)
    type) within its namespace, if appropriate.
 
    For compatibility with older debuggers, namespace DIEs only contain
-   declarations; all definitions are emitted at CU scope.  */
+   declarations; all definitions are emitted at CU scope, with
+   DW_AT_specification pointing to the declaration (like with class
+   members).  */
 
 static dw_die_ref
 declare_in_namespace (tree thing, dw_die_ref context_die)
@@ -20756,7 +23540,7 @@ declare_in_namespace (tree thing, dw_die_ref context_die)
       if (is_fortran ())
        return ns_context;
       if (DECL_P (thing))
-       gen_decl_die (thing, NULL, ns_context);
+       gen_decl_die (thing, NULL, NULL, ns_context);
       else
        gen_type_die (thing, ns_context);
     }
@@ -20816,10 +23600,14 @@ gen_namespace_die (tree decl, dw_die_ref context_die)
 
 /* Generate Dwarf debug information for a decl described by DECL.
    The return value is currently only meaningful for PARM_DECLs,
-   for all other decls it returns NULL.  */
+   for all other decls it returns NULL.
+
+   If DECL is a FIELD_DECL, CTX is required: see the comment for VLR_CONTEXT.
+   It can be NULL otherwise.  */
 
 static dw_die_ref
-gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
+gen_decl_die (tree decl, tree origin, struct vlr_context *ctx,
+             dw_die_ref context_die)
 {
   tree decl_or_origin = decl ? decl : origin;
   tree class_origin = NULL, ultimate_origin;
@@ -20990,6 +23778,7 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
       break;
 
     case FIELD_DECL:
+      gcc_assert (ctx != NULL && ctx->struct_type != NULL);
       /* Ignore the nameless fields that are used to skip bits but handle C++
         anonymous unions and structs.  */
       if (DECL_NAME (decl) != NULL_TREE
@@ -20997,7 +23786,7 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
          || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
        {
          gen_type_die (member_declared_type (decl), context_die);
-         gen_field_die (decl, context_die);
+         gen_field_die (decl, ctx, context_die);
        }
       break;
 
@@ -21011,11 +23800,15 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
                                       context_die);
 
     case NAMESPACE_DECL:
-    case IMPORTED_DECL:
       if (dwarf_version >= 3 || !dwarf_strict)
        gen_namespace_die (decl, context_die);
       break;
 
+    case IMPORTED_DECL:
+      dwarf2out_imported_module_or_decl_1 (decl, DECL_NAME (decl),
+                                          DECL_CONTEXT (decl), context_die);
+      break;
+
     case NAMELIST_DECL:
       gen_namelist_decl (DECL_NAME (decl), context_die,
                         NAMELIST_DECL_ASSOCIATED_DECL (decl));
@@ -21030,19 +23823,73 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
   return NULL;
 }
 \f
-/* Output debug information for global decl DECL.  Called from toplev.c after
-   compilation proper has finished.  */
+/* Output initial debug information for global DECL.  Called at the
+   end of the parsing process.
+
+   This is the initial debug generation process.  As such, the DIEs
+   generated may be incomplete.  A later debug generation pass
+   (dwarf2out_late_global_decl) will augment the information generated
+   in this pass (e.g., with complete location info).  */
+
+static void
+dwarf2out_early_global_decl (tree decl)
+{
+  set_early_dwarf s;
+
+  /* gen_decl_die() will set DECL_ABSTRACT because
+     cgraph_function_possibly_inlined_p() returns true.  This is in
+     turn will cause DW_AT_inline attributes to be set.
+
+     This happens because at early dwarf generation, there is no
+     cgraph information, causing cgraph_function_possibly_inlined_p()
+     to return true.  Trick cgraph_function_possibly_inlined_p()
+     while we generate dwarf early.  */
+  bool save = symtab->global_info_ready;
+  symtab->global_info_ready = true;
+
+  /* We don't handle TYPE_DECLs.  If required, they'll be reached via
+     other DECLs and they can point to template types or other things
+     that dwarf2out can't handle when done via dwarf2out_decl.  */
+  if (TREE_CODE (decl) != TYPE_DECL
+      && TREE_CODE (decl) != PARM_DECL)
+    {
+      tree save_fndecl = current_function_decl;
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       {
+         /* No cfun means the symbol has no body, so there's nothing
+            to emit.  */
+         if (!DECL_STRUCT_FUNCTION (decl))
+           goto early_decl_exit;
+
+         current_function_decl = decl;
+       }
+      dwarf2out_decl (decl);
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       current_function_decl = save_fndecl;
+    }
+ early_decl_exit:
+  symtab->global_info_ready = save;
+}
+
+/* Output debug information for global decl DECL.  Called from
+   toplev.c after compilation proper has finished.  */
 
 static void
-dwarf2out_global_decl (tree decl)
+dwarf2out_late_global_decl (tree decl)
 {
-  /* Output DWARF2 information for file-scope tentative data object
-     declarations, file-scope (extern) function declarations (which
-     had no corresponding body) and file-scope tagged type declarations
-     and definitions which have not yet been forced out.  */
-  if ((TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))
+  /* We have to generate early debug late for LTO.  */
+  if (in_lto_p)
+    dwarf2out_early_global_decl (decl);
+
+    /* Fill-in any location information we were unable to determine
+       on the first pass.  */
+  if (TREE_CODE (decl) == VAR_DECL
       && !POINTER_BOUNDS_P (decl))
-    dwarf2out_decl (decl);
+    {
+      dw_die_ref die = lookup_decl_die (decl);
+      if (die)
+       add_location_or_const_value_attribute (die, decl, false);
+    }
 }
 
 /* Output debug information for type decl DECL.  Called from toplev.c
@@ -21051,7 +23898,10 @@ static void
 dwarf2out_type_decl (tree decl, int local)
 {
   if (!local)
-    dwarf2out_decl (decl);
+    {
+      set_early_dwarf s;
+      dwarf2out_decl (decl);
+    }
 }
 
 /* Output debug information for imported module or decl DECL.
@@ -21159,6 +24009,8 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
 
   gcc_assert (decl);
 
+  set_early_dwarf s;
+
   /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs.
      We need decl DIE for reference and scope die. First, get DIE for the decl
      itself.  */
@@ -21185,7 +24037,6 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
 
   /* OK, now we have DIEs for decl as well as scope. Emit imported die.  */
   dwarf2out_imported_module_or_decl_1 (decl, name, context, scope_die);
-
 }
 
 /* Output debug information for namelists.   */
@@ -21225,7 +24076,7 @@ gen_namelist_decl (tree name, dw_die_ref scope_die, tree item_decls)
 }
 
 
-/* Write the debugging output for DECL.  */
+/* Write the debugging output for DECL and return the DIE.  */
 
 static void
 dwarf2out_decl (tree decl)
@@ -21284,21 +24135,8 @@ dwarf2out_decl (tree decl)
       break;
 
     case VAR_DECL:
-      /* Ignore this VAR_DECL if it refers to a file-scope extern data object
-        declaration and if the declaration was never even referenced from
-        within this entire compilation unit.  We suppress these DIEs in
-        order to save space in the .debug section (by eliminating entries
-        which are probably useless).  Note that we must not suppress
-        block-local extern declarations (whether used or not) because that
-        would screw-up the debugger's name lookup mechanism and cause it to
-        miss things which really ought to be in scope at a given point.  */
-      if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
-       return;
-
       /* For local statics lookup proper context die.  */
-      if (TREE_STATIC (decl)
-         && DECL_CONTEXT (decl)
-         && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
+      if (local_function_static (decl))
        context_die = lookup_decl_die (DECL_CONTEXT (decl));
 
       /* If we are in terse mode, don't generate any DIEs to represent any
@@ -21352,7 +24190,14 @@ dwarf2out_decl (tree decl)
       return;
     }
 
-  gen_decl_die (decl, NULL, context_die);
+  gen_decl_die (decl, NULL, NULL, context_die);
+
+  if (flag_checking)
+    {
+      dw_die_ref die = lookup_decl_die (decl);
+      if (die)
+       check_die (die);
+    }
 }
 
 /* Write the debugging output for DECL.  */
@@ -21365,7 +24210,6 @@ dwarf2out_function_decl (tree decl)
   call_arg_loc_last = NULL;
   call_site_count = -1;
   tail_call_site_count = -1;
-  block_map.release ();
   decl_loc_table->empty ();
   cached_dw_loc_list_table->empty ();
 }
@@ -21438,25 +24282,18 @@ dwarf_file_hasher::hash (dwarf_file_data *p)
    just a unique number which is associated with only that one filename.  We
    need such numbers for the sake of generating labels (in the .debug_sfnames
    section) and references to those files numbers (in the .debug_srcinfo
-   and.debug_macinfo sections).  If the filename given as an argument is not
+   and .debug_macinfo sections).  If the filename given as an argument is not
    found in our current list, add it to the list and assign it the next
-   available unique index number.  In order to speed up searches, we remember
-   the index of the filename was looked up last.  This handles the majority of
-   all searches.  */
+   available unique index number.  */
 
 static struct dwarf_file_data *
 lookup_filename (const char *file_name)
 {
   struct dwarf_file_data * created;
 
-  /* Check to see if the file name that was searched on the previous
-     call matches this file name.  If so, return the index.  */
-  if (file_table_last_lookup
-      && (file_name == file_table_last_lookup->filename
-         || filename_cmp (file_table_last_lookup->filename, file_name) == 0))
-    return file_table_last_lookup;
+  if (!file_name)
+    return NULL;
 
-  /* Didn't match the previous lookup, search the table.  */
   dwarf_file_data **slot
     = file_table->find_slot_with_hash (file_name, htab_hash_string (file_name),
                                       INSERT);
@@ -21511,6 +24348,8 @@ append_entry_to_tmpl_value_parm_die_table (dw_die_ref die, tree arg)
   if (!die || !arg)
     return;
 
+  gcc_assert (early_dwarf);
+
   if (!tmpl_value_parm_die_table)
     vec_alloc (tmpl_value_parm_die_table, 32);
 
@@ -21540,6 +24379,8 @@ schedule_generic_params_dies_gen (tree t)
   if (!generic_type_p (t))
     return;
 
+  gcc_assert (early_dwarf);
+
   if (!generic_type_instances)
     vec_alloc (generic_type_instances, 256);
 
@@ -21555,11 +24396,30 @@ gen_remaining_tmpl_value_param_die_attribute (void)
 {
   if (tmpl_value_parm_die_table)
     {
-      unsigned i;
+      unsigned i, j;
       die_arg_entry *e;
 
+      /* We do this in two phases - first get the cases we can
+        handle during early-finish, preserving those we cannot
+        (containing symbolic constants where we don't yet know
+        whether we are going to output the referenced symbols).
+        For those we try again at late-finish.  */
+      j = 0;
       FOR_EACH_VEC_ELT (*tmpl_value_parm_die_table, i, e)
-       tree_add_const_value_attribute (e->die, e->arg);
+       {
+         if (!tree_add_const_value_attribute (e->die, e->arg))
+           {
+             dw_loc_descr_ref loc = NULL;
+             if (! early_dwarf
+                 && (dwarf_version >= 5 || !dwarf_strict))
+               loc = loc_descriptor_from_tree (e->arg, 2, NULL);
+             if (loc)
+               add_AT_loc (e->die, DW_AT_location, loc);
+             else
+               (*tmpl_value_parm_die_table)[j++] = *e;
+           }
+       }
+      tmpl_value_parm_die_table->truncate (j);
     }
 }
 
@@ -21580,6 +24440,8 @@ gen_scheduled_generic_parms_dies (void)
   FOR_EACH_VEC_ELT (*generic_type_instances, i, t)
     if (COMPLETE_TYPE_P (t))
       gen_generic_params_dies (t);
+
+  generic_type_instances = NULL;
 }
 
 
@@ -21589,7 +24451,7 @@ static void
 dwarf2out_set_name (tree decl, tree name)
 {
   dw_die_ref die;
-  dw_attr_ref attr;
+  dw_attr_node *attr;
   const char *dname;
 
   die = TYPE_SYMTAB_DIE (decl);
@@ -21632,6 +24494,7 @@ dwarf2out_var_location (rtx_insn *loc_note)
   char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
   struct var_loc_node *newloc;
   rtx_insn *next_real, *next_note;
+  rtx_insn *call_insn = NULL;
   static const char *last_label;
   static const char *last_postcall_label;
   static bool last_in_cold_section_p;
@@ -21646,6 +24509,35 @@ dwarf2out_var_location (rtx_insn *loc_note)
          call_site_count++;
          if (SIBLING_CALL_P (loc_note))
            tail_call_site_count++;
+         if (optimize == 0 && !flag_var_tracking)
+           {
+             /* When the var-tracking pass is not running, there is no note
+                for indirect calls whose target is compile-time known. In this
+                case, process such calls specifically so that we generate call
+                sites for them anyway.  */
+             rtx x = PATTERN (loc_note);
+             if (GET_CODE (x) == PARALLEL)
+               x = XVECEXP (x, 0, 0);
+             if (GET_CODE (x) == SET)
+               x = SET_SRC (x);
+             if (GET_CODE (x) == CALL)
+               x = XEXP (x, 0);
+             if (!MEM_P (x)
+                 || GET_CODE (XEXP (x, 0)) != SYMBOL_REF
+                 || !SYMBOL_REF_DECL (XEXP (x, 0))
+                 || (TREE_CODE (SYMBOL_REF_DECL (XEXP (x, 0)))
+                     != FUNCTION_DECL))
+               {
+                 call_insn = loc_note;
+                 loc_note = NULL;
+                 var_loc_p = false;
+
+                 next_real = next_real_insn (call_insn);
+                 next_note = NULL;
+                 cached_next_real_insn = NULL;
+                 goto create_label;
+               }
+           }
        }
       return;
     }
@@ -21691,6 +24583,8 @@ dwarf2out_var_location (rtx_insn *loc_note)
       && !NOTE_DURING_CALL_P (loc_note))
     return;
 
+create_label:
+
   if (next_real == NULL_RTX)
     next_real = get_last_insn ();
 
@@ -21770,12 +24664,16 @@ dwarf2out_var_location (rtx_insn *loc_note)
        }
     }
 
+  gcc_assert ((loc_note == NULL_RTX && call_insn != NULL_RTX)
+             || (loc_note != NULL_RTX && call_insn == NULL_RTX));
+
   if (!var_loc_p)
     {
       struct call_arg_loc_node *ca_loc
        = ggc_cleared_alloc<call_arg_loc_node> ();
-      rtx_insn *prev = prev_real_insn (loc_note);
-      rtx x;
+      rtx_insn *prev
+        = loc_note != NULL_RTX ? prev_real_insn (loc_note) : call_insn;
+
       ca_loc->call_arg_loc_note = loc_note;
       ca_loc->next = NULL;
       ca_loc->label = last_label;
@@ -21787,15 +24685,27 @@ dwarf2out_var_location (rtx_insn *loc_note)
       if (!CALL_P (prev))
        prev = as_a <rtx_sequence *> (PATTERN (prev))->insn (0);
       ca_loc->tail_call_p = SIBLING_CALL_P (prev);
-      x = get_call_rtx_from (PATTERN (prev));
+
+      /* Look for a SYMBOL_REF in the "prev" instruction.  */
+      rtx x = get_call_rtx_from (PATTERN (prev));
       if (x)
        {
-         x = XEXP (XEXP (x, 0), 0);
-         if (GET_CODE (x) == SYMBOL_REF
-             && SYMBOL_REF_DECL (x)
-             && TREE_CODE (SYMBOL_REF_DECL (x)) == FUNCTION_DECL)
-           ca_loc->symbol_ref = x;
+         /* Try to get the call symbol, if any.  */
+         if (MEM_P (XEXP (x, 0)))
+           x = XEXP (x, 0);
+         /* First, look for a memory access to a symbol_ref.  */
+         if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+             && SYMBOL_REF_DECL (XEXP (x, 0))
+             && TREE_CODE (SYMBOL_REF_DECL (XEXP (x, 0))) == FUNCTION_DECL)
+           ca_loc->symbol_ref = XEXP (x, 0);
+         /* Otherwise, look at a compile-time known user-level function
+            declaration.  */
+         else if (MEM_P (x)
+                  && MEM_EXPR (x)
+                  && TREE_CODE (MEM_EXPR (x)) == FUNCTION_DECL)
+           ca_loc->symbol_ref = XEXP (DECL_RTL (MEM_EXPR (x)), 0);
        }
+
       ca_loc->block = insn_scope (prev);
       if (call_arg_locations)
        call_arg_loc_last->next = ca_loc;
@@ -21803,7 +24713,7 @@ dwarf2out_var_location (rtx_insn *loc_note)
        call_arg_locations = ca_loc;
       call_arg_loc_last = ca_loc;
     }
-  else if (!NOTE_DURING_CALL_P (loc_note))
+  else if (loc_note != NULL_RTX && !NOTE_DURING_CALL_P (loc_note))
     newloc->label = last_label;
   else
     {
@@ -21819,6 +24729,16 @@ dwarf2out_var_location (rtx_insn *loc_note)
   last_in_cold_section_p = in_cold_section_p;
 }
 
+/* Called from finalize_size_functions for size functions so that their body
+   can be encoded in the debug info to describe the layout of variable-length
+   structures.  */
+
+static void
+dwarf2out_size_function (tree decl)
+{
+  function_to_dwarf_procedure (decl);
+}
+
 /* Note in one location list that text section has changed.  */
 
 int
@@ -21849,7 +24769,7 @@ new_line_info_table (void)
 {
   dw_line_info_table *table;
 
-  table = ggc_cleared_alloc<dw_line_info_table_struct> ();
+  table = ggc_cleared_alloc<dw_line_info_table> ();
   table->file_num = 1;
   table->line_num = 1;
   table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
@@ -21989,6 +24909,26 @@ dwarf2out_end_function (unsigned int)
   maybe_at_text_label_p = false;
 }
 
+/* Temporary holder for dwarf2out_register_main_translation_unit.  Used to let
+   front-ends register a translation unit even before dwarf2out_init is
+   called.  */
+static tree main_translation_unit = NULL_TREE;
+
+/* Hook called by front-ends after they built their main translation unit.
+   Associate comp_unit_die to UNIT.  */
+
+static void
+dwarf2out_register_main_translation_unit (tree unit)
+{
+  gcc_assert (TREE_CODE (unit) == TRANSLATION_UNIT_DECL
+             && main_translation_unit == NULL_TREE);
+  main_translation_unit = unit;
+  /* If dwarf2out_init has not been called yet, it will perform the association
+     itself looking at main_translation_unit.  */
+  if (decl_die_table != NULL)
+    equate_decl_number_to_die (unit, comp_unit_die ());
+}
+
 /* Add OPCODE+VAL as an entry at the end of the opcode array in TABLE.  */
 
 static void
@@ -22197,23 +25137,21 @@ dwarf2out_undef (unsigned int lineno ATTRIBUTE_UNUSED,
 
 /* Helpers to manipulate hash table of CUs.  */
 
-struct macinfo_entry_hasher : typed_noop_remove <macinfo_entry>
+struct macinfo_entry_hasher : nofree_ptr_hash <macinfo_entry>
 {
-  typedef macinfo_entry value_type;
-  typedef macinfo_entry compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  static inline hashval_t hash (const macinfo_entry *);
+  static inline bool equal (const macinfo_entry *, const macinfo_entry *);
 };
 
 inline hashval_t
-macinfo_entry_hasher::hash (const value_type *entry)
+macinfo_entry_hasher::hash (const macinfo_entry *entry)
 {
   return htab_hash_string (entry->info);
 }
 
 inline bool
-macinfo_entry_hasher::equal (const value_type *entry1,
-                            const compare_type *entry2)
+macinfo_entry_hasher::equal (const macinfo_entry *entry1,
+                            const macinfo_entry *entry2)
 {
   return !strcmp (entry1->info, entry2->info);
 }
@@ -22596,9 +25534,18 @@ output_macinfo (void)
 static void
 dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
 {
+  /* This option is currently broken, see (PR53118 and PR46102).  */
+  if (flag_eliminate_dwarf2_dups
+      && strstr (lang_hooks.name, "C++"))
+    {
+      warning (0, "-feliminate-dwarf2-dups is broken for C++, ignoring");
+      flag_eliminate_dwarf2_dups = 0;
+    }
+
   /* Allocate the file_table.  */
   file_table = hash_table<dwarf_file_hasher>::create_ggc (50);
 
+#ifndef DWARF2_LINENO_DEBUGGING_INFO
   /* Allocate the decl_die_table.  */
   decl_die_table = hash_table<decl_die_hasher>::create_ggc (10);
 
@@ -22618,6 +25565,9 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   /* Zero-th entry is allocated, but unused.  */
   abbrev_die_table_in_use = 1;
 
+  /* Allocate the dwarf_proc_stack_usage_map.  */
+  dwarf_proc_stack_usage_map = new hash_map<dw_die_ref, int>;
+
   /* Allocate the pubtypes and pubnames vectors.  */
   vec_alloc (pubname_table, 32);
   vec_alloc (pubtype_table, 32);
@@ -22714,10 +25664,20 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
 
   switch_to_section (text_section);
   ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
+#endif
 
   /* Make sure the line number table for .text always exists.  */
   text_section_line_info = new_line_info_table ();
   text_section_line_info->end_label = text_end_label;
+
+#ifdef DWARF2_LINENO_DEBUGGING_INFO
+  cur_line_info_table = text_section_line_info;
+#endif
+
+  /* If front-ends already registered a main translation unit but we were not
+     ready to perform the association, do this now.  */
+  if (main_translation_unit != NULL_TREE)
+    equate_decl_number_to_die (main_translation_unit, comp_unit_die ());
 }
 
 /* Called before compile () starts outputtting functions, variables
@@ -22917,30 +25877,86 @@ prune_unmark_dies (dw_die_ref die)
   FOR_EACH_CHILD (die, c, prune_unmark_dies (c));
 }
 
+/* Given LOC that is referenced by a DIE we're marking as used, find all
+   referenced DWARF procedures it references and mark them as used.  */
+
+static void
+prune_unused_types_walk_loc_descr (dw_loc_descr_ref loc)
+{
+  for (; loc != NULL; loc = loc->dw_loc_next)
+    switch (loc->dw_loc_opc)
+      {
+      case DW_OP_GNU_implicit_pointer:
+      case DW_OP_GNU_convert:
+      case DW_OP_GNU_reinterpret:
+       if (loc->dw_loc_oprnd1.val_class == dw_val_class_die_ref)
+         prune_unused_types_mark (loc->dw_loc_oprnd1.v.val_die_ref.die, 1);
+       break;
+      case DW_OP_call2:
+      case DW_OP_call4:
+      case DW_OP_call_ref:
+      case DW_OP_GNU_const_type:
+      case DW_OP_GNU_parameter_ref:
+       gcc_assert (loc->dw_loc_oprnd1.val_class == dw_val_class_die_ref);
+       prune_unused_types_mark (loc->dw_loc_oprnd1.v.val_die_ref.die, 1);
+       break;
+      case DW_OP_GNU_regval_type:
+      case DW_OP_GNU_deref_type:
+       gcc_assert (loc->dw_loc_oprnd2.val_class == dw_val_class_die_ref);
+       prune_unused_types_mark (loc->dw_loc_oprnd2.v.val_die_ref.die, 1);
+       break;
+      case DW_OP_GNU_entry_value:
+       gcc_assert (loc->dw_loc_oprnd1.val_class == dw_val_class_loc);
+       prune_unused_types_walk_loc_descr (loc->dw_loc_oprnd1.v.val_loc);
+       break;
+      default:
+       break;
+      }
+}
+
 /* Given DIE that we're marking as used, find any other dies
    it references as attributes and mark them as used.  */
 
 static void
 prune_unused_types_walk_attribs (dw_die_ref die)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     {
-      if (a->dw_attr_val.val_class == dw_val_class_die_ref)
+      switch (AT_class (a))
        {
+       /* Make sure DWARF procedures referenced by location descriptions will
+          get emitted.  */
+       case dw_val_class_loc:
+         prune_unused_types_walk_loc_descr (AT_loc (a));
+         break;
+       case dw_val_class_loc_list:
+         for (dw_loc_list_ref list = AT_loc_list (a);
+              list != NULL;
+              list = list->dw_loc_next)
+           prune_unused_types_walk_loc_descr (list->expr);
+         break;
+
+       case 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 (! 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);
+         break;
+
+       case dw_val_class_str:
+         /* Set the string's refcount to 0 so that prune_unused_types_mark
+            accounts properly for it.  */
+         a->dw_attr_val.v.val_str->refcount = 0;
+         break;
+
+       default:
+         break;
        }
-      /* Set the string's refcount to 0 so that prune_unused_types_mark
-        accounts properly for it.  */
-      if (AT_class (a) == dw_val_class_str)
-       a->dw_attr_val.v.val_str->refcount = 0;
     }
 }
 
@@ -23091,7 +26107,6 @@ prune_unused_types_walk (dw_die_ref die)
     case DW_TAG_array_type:
     case DW_TAG_interface_type:
     case DW_TAG_friend:
-    case DW_TAG_variant_part:
     case DW_TAG_enumeration_type:
     case DW_TAG_subroutine_type:
     case DW_TAG_string_type:
@@ -23099,10 +26114,16 @@ prune_unused_types_walk (dw_die_ref die)
     case DW_TAG_subrange_type:
     case DW_TAG_ptr_to_member_type:
     case DW_TAG_file_type:
+      /* Type nodes are useful only when other DIEs reference them --- don't
+        mark them.  */
+      /* FALLTHROUGH */
+
+    case DW_TAG_dwarf_procedure:
+      /* Likewise for DWARF procedures.  */
+
       if (die->die_perennial_p)
        break;
 
-      /* It's a type node --- don't mark it.  */
       return;
 
     default:
@@ -23130,7 +26151,7 @@ prune_unused_types_walk (dw_die_ref die)
 static void
 prune_unused_types_update_strings (dw_die_ref die)
 {
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -23198,7 +26219,7 @@ prune_unused_types (void)
   unsigned int i;
   limbo_die_node *node;
   comdat_type_node *ctnode;
-  pubname_ref pub;
+  pubname_entry *pub;
   dw_die_ref base_type;
 
 #if ENABLE_ASSERT_CHECKING
@@ -23238,8 +26259,17 @@ prune_unused_types (void)
   if (skeleton_debug_str_hash)
     skeleton_debug_str_hash->empty ();
   prune_unused_types_prune (comp_unit_die ());
-  for (node = limbo_die_list; node; node = node->next)
-    prune_unused_types_prune (node->die);
+  for (limbo_die_node **pnode = &limbo_die_list; *pnode; )
+    {
+      node = *pnode;
+      if (!node->die->die_mark)
+       *pnode = node->next;
+      else
+       {
+         prune_unused_types_prune (node->die);
+         pnode = &node->next;
+       }
+    }
   for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next)
     prune_unused_types_prune (ctnode->root_die);
 
@@ -23267,16 +26297,14 @@ file_table_relative_p (dwarf_file_data **slot, bool *p)
 
 /* Helpers to manipulate hash table of comdat type units.  */
 
-struct comdat_type_hasher : typed_noop_remove <comdat_type_node>
+struct comdat_type_hasher : nofree_ptr_hash <comdat_type_node>
 {
-  typedef comdat_type_node value_type;
-  typedef comdat_type_node compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  static inline hashval_t hash (const comdat_type_node *);
+  static inline bool equal (const comdat_type_node *, const comdat_type_node *);
 };
 
 inline hashval_t
-comdat_type_hasher::hash (const value_type *type_node)
+comdat_type_hasher::hash (const comdat_type_node *type_node)
 {
   hashval_t h;
   memcpy (&h, type_node->signature, sizeof (h));
@@ -23284,8 +26312,8 @@ comdat_type_hasher::hash (const value_type *type_node)
 }
 
 inline bool
-comdat_type_hasher::equal (const value_type *type_node_1,
-                          const compare_type *type_node_2)
+comdat_type_hasher::equal (const comdat_type_node *type_node_1,
+                          const comdat_type_node *type_node_2)
 {
   return (! memcmp (type_node_1->signature, type_node_2->signature,
                     DWARF_TYPE_SIGNATURE_SIZE));
@@ -23791,6 +26819,175 @@ optimize_location_into_implicit_ptr (dw_die_ref die, tree decl)
     }
 }
 
+/* Return NULL if l is a DWARF expression, or first op that is not
+   valid DWARF expression.  */
+
+static dw_loc_descr_ref
+non_dwarf_expression (dw_loc_descr_ref l)
+{
+  while (l)
+    {
+      if (l->dw_loc_opc >= DW_OP_reg0 && l->dw_loc_opc <= DW_OP_reg31)
+       return l;
+      switch (l->dw_loc_opc)
+       {
+       case DW_OP_regx:
+       case DW_OP_implicit_value:
+       case DW_OP_stack_value:
+       case DW_OP_GNU_implicit_pointer:
+       case DW_OP_GNU_parameter_ref:
+       case DW_OP_piece:
+       case DW_OP_bit_piece:
+         return l;
+       default:
+         break;
+       }
+      l = l->dw_loc_next;
+    }
+  return NULL;
+}
+
+/* Return adjusted copy of EXPR:
+   If it is empty DWARF expression, return it.
+   If it is valid non-empty DWARF expression,
+   return copy of EXPR with copy of DEREF appended to it.
+   If it is DWARF expression followed by DW_OP_reg{N,x}, return
+   copy of the DWARF expression with DW_OP_breg{N,x} <0> appended
+   and no DEREF.
+   If it is DWARF expression followed by DW_OP_stack_value, return
+   copy of the DWARF expression without anything appended.
+   Otherwise, return NULL.  */
+
+static dw_loc_descr_ref
+copy_deref_exprloc (dw_loc_descr_ref expr, dw_loc_descr_ref deref)
+{
+  
+  if (expr == NULL)
+    return NULL;
+
+  dw_loc_descr_ref l = non_dwarf_expression (expr);
+  if (l && l->dw_loc_next)
+    return NULL;
+
+  if (l)
+    {
+      if (l->dw_loc_opc >= DW_OP_reg0 && l->dw_loc_opc <= DW_OP_reg31)
+       deref = new_loc_descr ((enum dwarf_location_atom)
+                              (DW_OP_breg0 + (l->dw_loc_opc - DW_OP_reg0)),
+                              0, 0);
+      else
+       switch (l->dw_loc_opc)
+         {
+         case DW_OP_regx:
+           deref = new_loc_descr (DW_OP_bregx,
+                                  l->dw_loc_oprnd1.v.val_unsigned, 0);
+           break;
+         case DW_OP_stack_value:
+           deref = NULL;
+           break;
+         default:
+           return NULL;
+         }
+    }
+  else
+    deref = new_loc_descr (deref->dw_loc_opc,
+                          deref->dw_loc_oprnd1.v.val_int, 0);
+
+  dw_loc_descr_ref ret = NULL, *p = &ret;
+  while (expr != l)
+    {
+      *p = new_loc_descr (expr->dw_loc_opc, 0, 0);
+      (*p)->dw_loc_oprnd1 = expr->dw_loc_oprnd1;
+      (*p)->dw_loc_oprnd2 = expr->dw_loc_oprnd2;
+      p = &(*p)->dw_loc_next;
+      expr = expr->dw_loc_next;
+    }
+  *p = deref;
+  return ret;
+}
+
+/* For DW_AT_string_length attribute with DW_OP_call4 reference to a variable
+   or argument, adjust it if needed and return:
+   -1 if the DW_AT_string_length attribute and DW_AT_{string_length_,}byte_size
+      attribute if present should be removed
+   0 keep the attribute as is if the referenced var or argument has
+     only DWARF expression that covers all ranges
+   1 if the attribute has been successfully adjusted.  */
+
+static int
+optimize_string_length (dw_attr_node *a)
+{
+  dw_loc_descr_ref l = AT_loc (a), lv;
+  dw_die_ref die = l->dw_loc_oprnd1.v.val_die_ref.die;
+  dw_attr_node *av = get_AT (die, DW_AT_location);
+  dw_loc_list_ref d;
+  bool non_dwarf_expr = false;
+
+  if (av == NULL)
+    return -1;
+  switch (AT_class (av))
+    {
+    case dw_val_class_loc_list:
+      for (d = AT_loc_list (av); d != NULL; d = d->dw_loc_next)
+       if (d->expr && non_dwarf_expression (d->expr))
+         non_dwarf_expr = true;
+      break;
+    case dw_val_class_loc:
+      lv = AT_loc (av);
+      if (lv == NULL)
+       return -1;
+      if (non_dwarf_expression (lv))
+       non_dwarf_expr = true;
+      break;
+    default:
+      return -1;
+    }
+
+  /* If it is safe to keep DW_OP_call4 in, keep it.  */
+  if (!non_dwarf_expr
+      && (l->dw_loc_next == NULL || AT_class (av) == dw_val_class_loc))
+    return 0;
+
+  /* If not dereferencing the DW_OP_call4 afterwards, we can just
+     copy over the DW_AT_location attribute from die to a.  */
+  if (l->dw_loc_next == NULL)
+    {
+      a->dw_attr_val = av->dw_attr_val;
+      return 1;
+    }
+
+  dw_loc_list_ref list, *p;
+  switch (AT_class (av))
+    {
+    case dw_val_class_loc_list:
+      p = &list;
+      list = NULL;
+      for (d = AT_loc_list (av); d != NULL; d = d->dw_loc_next)
+       {
+         lv = copy_deref_exprloc (d->expr, l->dw_loc_next);
+         if (lv)
+           {
+             *p = new_loc_list (lv, d->begin, d->end, d->section);
+             p = &(*p)->dw_loc_next;
+           }
+       }
+      if (list == NULL)
+       return -1;
+      a->dw_attr_val.val_class = dw_val_class_loc_list;
+      gen_llsym (list);
+      *AT_loc_list_ptr (a) = list;
+      return 1;
+    case dw_val_class_loc:
+      lv = copy_deref_exprloc (AT_loc (av), l->dw_loc_next);
+      if (lv == NULL)
+       return -1;
+      a->dw_attr_val.v.val_loc = lv;
+      return 1;
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* Resolve DW_OP_addr and DW_AT_const_value CONST_STRING arguments to
    an address in .rodata section if the string literal is emitted there,
    or remove the containing location list or replace DW_AT_const_value
@@ -23802,9 +26999,10 @@ static void
 resolve_addr (dw_die_ref die)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   dw_loc_list_ref *curr, *start, loc;
   unsigned ix;
+  bool remove_AT_byte_size = false;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     switch (AT_class (a))
@@ -23865,6 +27063,38 @@ resolve_addr (dw_die_ref die)
       case dw_val_class_loc:
        {
          dw_loc_descr_ref l = AT_loc (a);
+         /* Using DW_OP_call4 or DW_OP_call4 DW_OP_deref in
+            DW_AT_string_length is only a rough approximation; unfortunately
+            DW_AT_string_length can't be a reference to a DIE.  DW_OP_call4
+            needs a DWARF expression, while DW_AT_location of the referenced
+            variable or argument might be any location description.  */
+         if (a->dw_attr == DW_AT_string_length
+             && l
+             && l->dw_loc_opc == DW_OP_call4
+             && l->dw_loc_oprnd1.val_class == dw_val_class_die_ref
+             && (l->dw_loc_next == NULL
+                 || (l->dw_loc_next->dw_loc_next == NULL
+                     && (l->dw_loc_next->dw_loc_opc == DW_OP_deref
+                         || l->dw_loc_next->dw_loc_opc != DW_OP_deref_size))))
+           {
+             switch (optimize_string_length (a))
+               {
+               case -1:
+                 remove_AT (die, a->dw_attr);
+                 ix--;
+                 /* If we drop DW_AT_string_length, we need to drop also
+                    DW_AT_{string_length_,}byte_size.  */
+                 remove_AT_byte_size = true;
+                 continue;
+               default:
+                 break;
+               case 1:
+                 /* Even if we keep the optimized DW_AT_string_length,
+                    it might have changed AT_class, so process it again.  */
+                 ix--;
+                 continue;
+               }
+           }
          /* For -gdwarf-2 don't attempt to optimize
             DW_AT_data_member_location containing
             DW_OP_plus_uconst - older consumers might
@@ -23913,12 +27143,22 @@ resolve_addr (dw_die_ref die)
          {
            tree tdecl = SYMBOL_REF_DECL (a->dw_attr_val.v.val_addr);
            dw_die_ref tdie = lookup_decl_die (tdecl);
+           dw_die_ref cdie;
            if (tdie == NULL
                && DECL_EXTERNAL (tdecl)
-               && DECL_ABSTRACT_ORIGIN (tdecl) == NULL_TREE)
+               && DECL_ABSTRACT_ORIGIN (tdecl) == NULL_TREE
+               && (cdie = lookup_context_die (DECL_CONTEXT (tdecl))))
              {
-               force_decl_die (tdecl);
-               tdie = lookup_decl_die (tdecl);
+               /* Creating a full DIE for tdecl is overly expensive and
+                  at this point even wrong when in the LTO phase
+                  as it can end up generating new type DIEs we didn't
+                  output and thus optimize_external_refs will crash.  */
+               tdie = new_die (DW_TAG_subprogram, cdie, NULL_TREE);
+               add_AT_flag (tdie, DW_AT_external, 1);
+               add_AT_flag (tdie, DW_AT_declaration, 1);
+               add_linkage_attr (tdie, tdecl);
+               add_name_and_src_coords_attributes (tdie, tdecl);
+               equate_decl_number_to_die (tdecl, tdie);
              }
            if (tdie)
              {
@@ -23939,6 +27179,11 @@ resolve_addr (dw_die_ref die)
        break;
       }
 
+  if (remove_AT_byte_size)
+    remove_AT (die, dwarf_version >= 5
+                   ? DW_AT_string_length_byte_size
+                   : DW_AT_byte_size);
+
   FOR_EACH_CHILD (die, c, resolve_addr (c));
 }
 \f
@@ -24370,18 +27615,17 @@ compare_locs (dw_loc_descr_ref x, dw_loc_descr_ref y)
 
 /* Hashtable helpers.  */
 
-struct loc_list_hasher : typed_noop_remove <dw_loc_list_struct>
+struct loc_list_hasher : nofree_ptr_hash <dw_loc_list_struct>
 {
-  typedef dw_loc_list_struct value_type;
-  typedef dw_loc_list_struct compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  static inline hashval_t hash (const dw_loc_list_struct *);
+  static inline bool equal (const dw_loc_list_struct *,
+                           const dw_loc_list_struct *);
 };
 
 /* Return precomputed hash of location list X.  */
 
 inline hashval_t
-loc_list_hasher::hash (const value_type *x)
+loc_list_hasher::hash (const dw_loc_list_struct *x)
 {
   return x->hash;
 }
@@ -24389,7 +27633,8 @@ loc_list_hasher::hash (const value_type *x)
 /* Return true if location lists A and B are the same.  */
 
 inline bool
-loc_list_hasher::equal (const value_type *a, const compare_type *b)
+loc_list_hasher::equal (const dw_loc_list_struct *a,
+                       const dw_loc_list_struct *b)
 {
   if (a == b)
     return 1;
@@ -24415,7 +27660,7 @@ static void
 optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type *htab)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
   dw_loc_list_struct **slot;
 
@@ -24444,7 +27689,7 @@ static void
 index_location_lists (dw_die_ref die)
 {
   dw_die_ref c;
-  dw_attr_ref a;
+  dw_attr_node *a;
   unsigned ix;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -24479,60 +27724,24 @@ optimize_location_lists (dw_die_ref die)
   optimize_location_lists_1 (die, &htab);
 }
 \f
-/* Output stuff that dwarf requires at the end of every file,
-   and generate the DWARF-2 debugging info.  */
+/* Traverse the limbo die list, and add parent/child links.  The only
+   dies without parents that should be here are concrete instances of
+   inline functions, and the comp_unit_die.  We can ignore the comp_unit_die.
+   For concrete instances, we can get the parent die from the abstract
+   instance.  */
 
 static void
-dwarf2out_finish (const char *filename)
+flush_limbo_die_list (void)
 {
-  limbo_die_node *node, *next_node;
-  comdat_type_node *ctnode;
-  unsigned int i;
-  dw_die_ref main_comp_unit_die;
-
-  /* PCH might result in DW_AT_producer string being restored from the
-     header compilation, so always fill it with empty string initially
-     and overwrite only here.  */
-  dw_attr_ref producer = get_AT (comp_unit_die (), DW_AT_producer);
-  producer_string = gen_producer_string ();
-  producer->dw_attr_val.v.val_str->refcount--;
-  producer->dw_attr_val.v.val_str = find_AT_string (producer_string);
-
-  gen_scheduled_generic_parms_dies ();
-  gen_remaining_tmpl_value_param_die_attribute ();
-
-  /* Add the name for the main input file now.  We delayed this from
-     dwarf2out_init to avoid complications with PCH.  */
-  add_name_attribute (comp_unit_die (), remap_debug_filename (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)
-    {
-      bool p = false;
-      file_table->traverse<bool *, file_table_relative_p> (&p);
-      if (p)
-       add_comp_dir_attribute (comp_unit_die ());
-    }
-
-  if (deferred_locations_list)
-    for (i = 0; i < deferred_locations_list->length (); i++)
-      {
-       add_location_or_const_value_attribute (
-           (*deferred_locations_list)[i].die,
-           (*deferred_locations_list)[i].variable,
-           false,
-           DW_AT_location);
-      }
+  limbo_die_node *node;
 
-  /* Traverse the limbo die list, and add parent/child links.  The only
-     dies without parents that should be here are concrete instances of
-     inline functions, and the comp_unit_die.  We can ignore the comp_unit_die.
-     For concrete instances, we can get the parent die from the abstract
-     instance.  */
-  for (node = limbo_die_list; node; node = next_node)
+  /* get_context_die calls force_decl_die, which can put new DIEs on the
+     limbo list in LTO mode when nested functions are put in a different
+     partition than that of their parent function.  */
+  while ((node = limbo_die_list))
     {
       dw_die_ref die = node->die;
-      next_node = node->next;
+      limbo_die_list = node->next;
 
       if (die->die_parent == NULL)
        {
@@ -24570,8 +27779,51 @@ dwarf2out_finish (const char *filename)
            }
        }
     }
+}
 
-  limbo_die_list = NULL;
+/* Output stuff that dwarf requires at the end of every file,
+   and generate the DWARF-2 debugging info.  */
+
+static void
+dwarf2out_finish (const char *filename)
+{
+  comdat_type_node *ctnode;
+  dw_die_ref main_comp_unit_die;
+
+  /* Flush out any latecomers to the limbo party.  */
+  flush_limbo_die_list ();
+
+  /* We shouldn't have any symbols with delayed asm names for
+     DIEs generated after early finish.  */
+  gcc_assert (deferred_asm_name == NULL);
+
+  /* PCH might result in DW_AT_producer string being restored from the
+     header compilation, so always fill it with empty string initially
+     and overwrite only here.  */
+  dw_attr_node *producer = get_AT (comp_unit_die (), DW_AT_producer);
+  producer_string = gen_producer_string ();
+  producer->dw_attr_val.v.val_str->refcount--;
+  producer->dw_attr_val.v.val_str = find_AT_string (producer_string);
+
+  gen_remaining_tmpl_value_param_die_attribute ();
+
+  /* Add the name for the main input file now.  We delayed this from
+     dwarf2out_init to avoid complications with PCH.
+     For LTO produced units use a fixed artificial name to avoid
+     leaking tempfile names into the dwarf.  */
+  if (!in_lto_p)
+    add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
+  else
+    add_name_attribute (comp_unit_die (), "<artificial>");
+  if (!IS_ABSOLUTE_PATH (filename) || targetm.force_at_comp_dir)
+    add_comp_dir_attribute (comp_unit_die ());
+  else if (get_AT (comp_unit_die (), DW_AT_comp_dir) == NULL)
+    {
+      bool p = false;
+      file_table->traverse<bool *, file_table_relative_p> (&p);
+      if (p)
+       add_comp_dir_attribute (comp_unit_die ());
+    }
 
 #if ENABLE_ASSERT_CHECKING
   {
@@ -24582,27 +27834,6 @@ dwarf2out_finish (const char *filename)
   resolve_addr (comp_unit_die ());
   move_marked_base_types ();
 
-  for (node = deferred_asm_name; node; node = node->next)
-    {
-      tree decl = node->created_for;
-      /* When generating LTO bytecode we can not generate new assembler
-         names at this point and all important decls got theirs via
-        free-lang-data.  */
-      if (((!flag_generate_lto && !flag_generate_offload)
-          || DECL_ASSEMBLER_NAME_SET_P (decl))
-         && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
-       {
-         add_linkage_attr (node->die, decl);
-         move_linkage_attr (node->die);
-       }
-    }
-
-  deferred_asm_name = NULL;
-
-  /* Walk through the list of incomplete types again, trying once more to
-     emit full debugging info for them.  */
-  retry_incomplete_types ();
-
   if (flag_eliminate_unused_debug_types)
     prune_unused_types ();
 
@@ -24634,9 +27865,10 @@ dwarf2out_finish (const char *filename)
   if (flag_eliminate_dwarf2_dups)
     break_out_includes (comp_unit_die ());
 
-  /* Traverse the DIE's and add add sibling attributes to those DIE's
-     that have children.  */
+  /* Traverse the DIE's and add sibling attributes to those DIE's that
+     have children.  */
   add_sibling_attributes (comp_unit_die ());
+  limbo_die_node *node;
   for (node = limbo_die_list; node; node = node->next)
     add_sibling_attributes (node->die);
   for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
@@ -24852,10 +28084,8 @@ dwarf2out_finish (const char *filename)
      generate a table that would have contained data.  */
   if (info_section_emitted)
     {
-      unsigned long aranges_length = size_of_aranges ();
-
       switch_to_section (debug_aranges_section);
-      output_aranges (aranges_length);
+      output_aranges ();
     }
 
   /* Output ranges section if necessary.  */
@@ -24898,6 +28128,42 @@ dwarf2out_finish (const char *filename)
     output_indirect_strings ();
 }
 
+/* Perform any cleanups needed after the early debug generation pass
+   has run.  */
+
+static void
+dwarf2out_early_finish (void)
+{
+  set_early_dwarf s;
+
+  /* Walk through the list of incomplete types again, trying once more to
+     emit full debugging info for them.  */
+  retry_incomplete_types ();
+
+  /* The point here is to flush out the limbo list so that it is empty
+     and we don't need to stream it for LTO.  */
+  flush_limbo_die_list ();
+
+  gen_scheduled_generic_parms_dies ();
+  gen_remaining_tmpl_value_param_die_attribute ();
+
+  /* Add DW_AT_linkage_name for all deferred DIEs.  */
+  for (limbo_die_node *node = deferred_asm_name; node; node = node->next)
+    {
+      tree decl = node->created_for;
+      if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
+         /* A missing DECL_ASSEMBLER_NAME can be a constant DIE that
+            ended up in deferred_asm_name before we knew it was
+            constant and never written to disk.  */
+         && DECL_ASSEMBLER_NAME (decl))
+       {
+         add_linkage_attr (node->die, decl);
+         move_linkage_attr (node->die);
+       }
+    }
+  deferred_asm_name = NULL;
+}
+
 /* Reset all state within dwarf2out.c so that we can rerun the compiler
    within the same process.  For use by toplev::finalize.  */
 
@@ -24936,13 +28202,10 @@ dwarf2out_c_finalize (void)
   cold_text_section = NULL;
   current_unit_personality = NULL;
 
-  deferred_locations_list = NULL;
-
   next_die_offset = 0;
   single_comp_unit_die = NULL;
   comdat_type_list = NULL;
   limbo_die_list = NULL;
-  deferred_asm_name = NULL;
   file_table = NULL;
   decl_die_table = NULL;
   common_block_die_table = NULL;
@@ -24951,11 +28214,12 @@ dwarf2out_c_finalize (void)
   call_arg_loc_last = NULL;
   call_site_count = -1;
   tail_call_site_count = -1;
-  //block_map = NULL;
   cached_dw_loc_list_table = NULL;
   abbrev_die_table = NULL;
   abbrev_die_table_allocated = 0;
   abbrev_die_table_in_use = 0;
+  delete dwarf_proc_stack_usage_map;
+  dwarf_proc_stack_usage_map = NULL;
   line_info_label_num = 0;
   cur_line_info_table = NULL;
   text_section_line_info = NULL;
@@ -24976,7 +28240,6 @@ dwarf2out_c_finalize (void)
   poc_label_num = 0;
   last_emitted_file = NULL;
   label_num = 0;
-  file_table_last_lookup = NULL;
   tmpl_value_parm_die_table = NULL;
   generic_type_instances = NULL;
   frame_pointer_fb_offset = 0;