public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][2/2] early LTO debug, main part
@ 2017-05-19 10:44 Richard Biener
  2017-06-07  8:21 ` Richard Biener
  2017-08-02  4:30 ` Jason Merrill
  0 siblings, 2 replies; 22+ messages in thread
From: Richard Biener @ 2017-05-19 10:44 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason


This is a repost of the main part of the early LTO debug support.
The only changes relative to the last post is in the dwarf2out.c
pieces due to Jasons review and Jakubs introduction of
DW_OP_GNU_variable_value.

I've also adjusted testcases for fallout (the asan backtraces do
give files / line numbers because libbacktrace doesn't understand
the DWARF) plus added a -flto run over the libstdc++ pretty printer
testsuite -- after all the goal was to make those work with LTO,
and they now nicely do.

[LTO-]bootstrapped and tested on x86_64-unknown-linux-gnu.

I've also tested with -flto -g and compared to before the patch and
the outcome doesn't contain any surprises.

I've also ran the gdb testsuite with no differences (but I guess
it doesn't exercise LTO).

I've also built SPEC 2k6 with -flto -g.

I've also debugged optimized LTO bootstrapped cc1 a bit - not that
debugging (LTO) optimized cc1 is a pleasant experience, but at least
gdb doesn't crash.

Ok for trunk?

Both darwin and mingw maintainers were not concerned about LTO with -g
being broken for them.

This patch allows us to go forward with freeing more stuff after
the frontend finished, in particular remove LTO streaming of a lot
of type information that is referenced from trees (and, as a first
step, enable free-lang-data for non-LTO compiles).

Thanks,
Richard.

2017-05-19  Richard Biener  <rguenther@suse.de>

        * debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and
        register_external_die hooks.
        (debug_false_tree_charstarstar_uhwistar): Declare.
        (debug_nothing_tree_charstar_uhwi): Likewise.
        * debug.c (do_nothing_debug_hooks): Adjust.
        (debug_false_tree_charstarstar_uhwistar): New do nothing.
        (debug_nothing_tree_charstar_uhwi): Likewise.
        * dbxout.c (dbx_debug_hooks): Adjust.
        (xcoff_debug_hooks): Likewise.
        * sdbout.c (sdb_debug_hooks): Likewise.
        * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.

        * dwarf2out.c (macinfo_label_base): New global.
	(dwarf2out_register_external_die): New function for the
	register_external_die hook.
        (dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl.
        (dwarf2_debug_hooks): Use them.
        (dwarf2_lineno_debug_hooks): Adjust.
        (struct die_struct): Add with_offset flag.
        (DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION,
        DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION,
        DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION,
        DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION,
        DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
        DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros
        defining section names for the early LTO debug variants.
	(reset_indirect_string): New helper.
        (add_AT_external_die_ref): Helper for dwarf2out_register_external_die.
        (print_dw_val): Add support for offsetted symbol references.
        (compute_section_prefix_1): Split out worker to distinguish
        the comdat from the LTO case.
        (compute_section_prefix): Wrap old comdat case here.
        (output_die): Skip DIE symbol output for the LTO added one.
        Handle DIE symbol references with offset.
        (output_comp_unit): Guard section name mangling properly.
        For LTO debug sections emit a symbol at the section beginning
        which we use to refer to its DIEs.
        (add_abstract_origin_attribute): For DIEs registered via
        dwarf2out_register_external_die directly refer to the early
        DIE rather than indirectly through the shadow one we created.
        (gen_array_type_die): When generating early LTO debug do
        not emit DW_AT_string_length.
        (gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs
        late when in LTO.
        (gen_subprogram_die): Adjust the check for whether we face
        a concrete instance DIE for an inline we can reuse for the
        late LTO case.  Likewise avoid another specification DIE
        for early built declarations/definitions for the late LTO case.
        (gen_variable_die): Add type references for late duplicated VLA dies
        when in late LTO.
        (gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function,
        we have the abstract instance already.
        (process_scope_var): Adjust decl DIE contexts in LTO which
        first puts them in limbo.
        (gen_decl_die): Do not generate type DIEs late apart from
        types for VLAs or for decls we do not yet have a DIE.
        (dwarf2out_early_global_decl): Make sure to create DIEs
        for abstract instances of a decl first.
        (dwarf2out_late_global_decl): Adjust comment.
        (output_macinfo_op): With multiple macro sections use
	macinfo_label_base to distinguish labels.
        (output_macinfo): Likewise.  Update macinfo_label_base.
	Pass in the line info label.
	(note_variable_value_in_expr): When generating LTO resolve
	all variable values here by generating DIEs as needed.
        (init_sections_and_labels): Add early LTO debug flag parameter
        and generate different sections and names if set.  Add generation
        counter for the labels so we can have multiple of them.
        (reset_dies): Helper to allow DIEs to be output multiple times.
        (dwarf2out_finish): When outputting DIEs to the fat part of an
	LTO object first reset DIEs.
        (dwarf2out_early_finish): Output early DIEs when generating LTO.

Cleanups we can do (and need) when removing the "old" LTO path and add
the early LTO path.

        (set_decl_abstract_flags): Remove.
        (set_block_abstract_flags): Likewise.
        (dwarf2out_abstract_function): Treat the early generated DIEs
        as the abstract copy and only add DW_AT_inline and
        DW_AT_artificial here.

	* tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL
	if we have none yet (Go fails to build one, PR78628).
        * lto-streamer-in.c: Include debug.h.
        (dref_queue): New global.
        (lto_read_tree_1): Stream in DIE references.
        (lto_input_tree): Register DIE references.
	(input_function): Stream DECL_DEBUG_ARGS.
        * lto-streamer-out.c: Include debug.h.
        (lto_write_tree_1): Output DIE references.
        (DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN.
	Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls.
	(output_function): Stream DECL_DEBUG_ARGS.
        * tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers):
        Stream DECL_ABSTRACT_ORIGIN.
        * tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise.
	(write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL
	DECL_CONTEXT for file-scope decls.
        * lto-streamer.h (struct dref_entry): Declare.
        (dref_queue): Likewise.

        * lto-wrapper.c (debug_obj): New global.
        (tool_cleanup): Unlink it if required.
        (debug_objcopy): New function.
        (run_gcc): Handle early debug sections in the IL files by
        extracting them to separate files, partially linkin them and
        feeding the result back as result to the linker.

        * config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION,
        DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION,
        DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug
        sections into a separate segment.
        * config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO
        segments.
        (darwin_asm_dwarf_section): Likewise.
        (darwin_asm_output_dwarf_offset): Likewise.

	* config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P.

        lto/
        * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
        (lto_read_decls): Process TRANSLATION_UNIT_DECLs.  Remove
        TYPE_DECL debug processing, register DIE references from
        prevailing SCCs with the debug machinery.
        (lto_section_with_id): Handle LTO debug sections.

	libstdc++/
	* testsuite/libstdc++-prettyprinters/prettyprinters.exp: Run all
	tests with -flto as well if supported.

	* c-c++-common/asan/global-overflow-1.c: Adjust diagnostic location
	regex to handle the LTO case.
	* c-c++-common/asan/heap-overflow-1.c: Likewise.
	* c-c++-common/asan/misalign-1.c: Likewise.
	* c-c++-common/asan/misalign-2.c: Likewise.
	* c-c++-common/asan/null-deref-1.c: Likewise.
	* c-c++-common/asan/stack-overflow-1.c: Likewise.
	* c-c++-common/asan/strncpy-overflow-1.c: Likewise.
	* c-c++-common/asan/use-after-free-1.c: Likewise.
	* g++.dg/asan/large-func-test-1.C: Likewise.
	* gfortran.dg/save_6.f90: Add -flto -g variant of save_5.f90.

Index: early-lto-debug/gcc/dwarf2out.c
===================================================================
*** early-lto-debug.orig/gcc/dwarf2out.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/dwarf2out.c	2017-05-19 12:29:43.933873285 +0200
*************** static GTY(()) section *debug_aranges_se
*** 162,167 ****
--- 162,168 ----
  static GTY(()) section *debug_addr_section;
  static GTY(()) section *debug_macinfo_section;
  static const char *debug_macinfo_section_name;
+ static unsigned macinfo_label_base = 1;
  static GTY(()) section *debug_line_section;
  static GTY(()) section *debug_skeleton_line_section;
  static GTY(()) section *debug_loc_section;
*************** static void dwarf2out_begin_function (tr
*** 2686,2691 ****
--- 2687,2696 ----
  static void dwarf2out_end_function (unsigned int);
  static void dwarf2out_register_main_translation_unit (tree unit);
  static void dwarf2out_set_name (tree, tree);
+ static void dwarf2out_register_external_die (tree decl, const char *sym,
+ 					     unsigned HOST_WIDE_INT off);
+ static bool dwarf2out_die_ref_for_decl (tree decl, const char **sym,
+ 					unsigned HOST_WIDE_INT *off);
  
  /* The debug hooks structure.  */
  
*************** const struct gcc_debug_hooks dwarf2_debu
*** 2720,2725 ****
--- 2725,2732 ----
    dwarf2out_late_global_decl,
    dwarf2out_type_decl,		/* type_decl */
    dwarf2out_imported_module_or_decl,
+   dwarf2out_die_ref_for_decl,
+   dwarf2out_register_external_die,
    debug_nothing_tree,		/* deferred_inline_function */
    /* The DWARF 2 backend tries to reduce debugging bloat by not
       emitting the abstract description of inline functions until
*************** const struct gcc_debug_hooks dwarf2_line
*** 2761,2766 ****
--- 2768,2775 ----
    debug_nothing_tree,		         /* late_global_decl */
    debug_nothing_tree_int,		 /* type_decl */
    debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
+   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
+   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
    debug_nothing_tree,		         /* deferred_inline_function */
    debug_nothing_tree,		         /* outlining_inline_function */
    debug_nothing_rtx_code_label,	         /* label */
*************** typedef struct GTY((chain_circular ("%h.
*** 2889,2894 ****
--- 2898,2906 ----
    /* Die is used and must not be pruned as unused.  */
    BOOL_BITFIELD die_perennial_p : 1;
    BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
+   /* For an external ref to die_symbol if die_offset contains an extra
+      offset to that symbol.  */
+   BOOL_BITFIELD with_offset : 1;
    /* Whether this DIE was removed from the DIE tree, for example via
       prune_unused_types.  We don't consider those present from the
       DIE lookup routines.  */
*************** new_addr_loc_descr (rtx addr, enum dtpre
*** 3692,3703 ****
--- 3704,3727 ----
  #ifndef DEBUG_DWO_INFO_SECTION
  #define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
  #endif
+ #ifndef DEBUG_LTO_DWO_INFO_SECTION
+ #define DEBUG_LTO_DWO_INFO_SECTION ".gnu.debuglto_.debug_info.dwo"
+ #endif
+ #ifndef DEBUG_LTO_INFO_SECTION
+ #define DEBUG_LTO_INFO_SECTION	".gnu.debuglto_.debug_info"
+ #endif
  #ifndef DEBUG_ABBREV_SECTION
  #define DEBUG_ABBREV_SECTION	".debug_abbrev"
  #endif
  #ifndef DEBUG_DWO_ABBREV_SECTION
  #define DEBUG_DWO_ABBREV_SECTION ".debug_abbrev.dwo"
  #endif
+ #ifndef DEBUG_LTO_DWO_ABBREV_SECTION
+ #define DEBUG_LTO_DWO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev.dwo"
+ #endif
+ #ifndef DEBUG_LTO_ABBREV_SECTION
+ #define DEBUG_LTO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev"
+ #endif
  #ifndef DEBUG_ARANGES_SECTION
  #define DEBUG_ARANGES_SECTION	".debug_aranges"
  #endif
*************** new_addr_loc_descr (rtx addr, enum dtpre
*** 3710,3727 ****
--- 3734,3766 ----
  #ifndef DEBUG_DWO_MACINFO_SECTION
  #define DEBUG_DWO_MACINFO_SECTION      ".debug_macinfo.dwo"
  #endif
+ #ifndef DEBUG_LTO_DWO_MACINFO_SECTION
+ #define DEBUG_LTO_DWO_MACINFO_SECTION  ".gnu.debuglto_.debug_macinfo.dwo"
+ #endif
+ #ifndef DEBUG_LTO_MACINFO_SECTION
+ #define DEBUG_LTO_MACINFO_SECTION      ".gnu.debuglto_.debug_macinfo"
+ #endif
  #ifndef DEBUG_DWO_MACRO_SECTION
  #define DEBUG_DWO_MACRO_SECTION        ".debug_macro.dwo"
  #endif
  #ifndef DEBUG_MACRO_SECTION
  #define DEBUG_MACRO_SECTION	".debug_macro"
  #endif
+ #ifndef DEBUG_LTO_DWO_MACRO_SECTION
+ #define DEBUG_LTO_DWO_MACRO_SECTION    ".gnu.debuglto_.debug_macro.dwo"
+ #endif
+ #ifndef DEBUG_LTO_MACRO_SECTION
+ #define DEBUG_LTO_MACRO_SECTION ".gnu.debuglto_.debug_macro"
+ #endif
  #ifndef DEBUG_LINE_SECTION
  #define DEBUG_LINE_SECTION	".debug_line"
  #endif
  #ifndef DEBUG_DWO_LINE_SECTION
  #define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
  #endif
+ #ifndef DEBUG_LTO_LINE_SECTION
+ #define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
+ #endif
  #ifndef DEBUG_LOC_SECTION
  #define DEBUG_LOC_SECTION	".debug_loc"
  #endif
*************** new_addr_loc_descr (rtx addr, enum dtpre
*** 3750,3761 ****
--- 3789,3809 ----
  #ifndef DEBUG_DWO_STR_OFFSETS_SECTION
  #define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo"
  #endif
+ #ifndef DEBUG_LTO_DWO_STR_OFFSETS_SECTION
+ #define DEBUG_LTO_DWO_STR_OFFSETS_SECTION ".gnu.debuglto_.debug_str_offsets.dwo"
+ #endif
  #ifndef DEBUG_STR_DWO_SECTION
  #define DEBUG_STR_DWO_SECTION   ".debug_str.dwo"
  #endif
+ #ifndef DEBUG_LTO_STR_DWO_SECTION
+ #define DEBUG_LTO_STR_DWO_SECTION ".gnu.debuglto_.debug_str.dwo"
+ #endif
  #ifndef DEBUG_STR_SECTION
  #define DEBUG_STR_SECTION  ".debug_str"
  #endif
+ #ifndef DEBUG_LTO_STR_SECTION
+ #define DEBUG_LTO_STR_SECTION ".gnu.debuglto_.debug_str"
+ #endif
  #ifndef DEBUG_RANGES_SECTION
  #define DEBUG_RANGES_SECTION	".debug_ranges"
  #endif
*************** new_addr_loc_descr (rtx addr, enum dtpre
*** 3780,3785 ****
--- 3828,3837 ----
  /* Section flags for .debug_str.dwo section.  */
  #define DEBUG_STR_DWO_SECTION_FLAGS (SECTION_DEBUG | SECTION_EXCLUDE)
  
+ /* Attribute used to refer to the macro section.  */
+ #define DEBUG_MACRO_ATTRIBUTE (dwarf_version >= 5 ? DW_AT_macros \
+ 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros)
+ 
  /* Labels we insert at beginning sections we can reference instead of
     the section names themselves.  */
  
*************** set_indirect_string (struct indirect_str
*** 4368,4373 ****
--- 4420,4443 ----
      }
  }
  
+ /* A helper function for dwarf2out_finish, called to reset indirect
+    string decisions done for early LTO dwarf output before fat object
+    dwarf output.  */
+ 
+ int
+ reset_indirect_string (indirect_string_node **h, void *)
+ {
+   struct indirect_string_node *node = *h;
+   if (node->form == DW_FORM_strp || node->form == DW_FORM_GNU_str_index)
+     {
+       free (node->label);
+       node->label = NULL;
+       node->form = (dwarf_form) 0;
+       node->index = 0;
+     }
+   return 1;
+ }
+ 
  /* Find out whether a string should be output inline in DIE
     or out-of-line in .debug_str section.  */
  
*************** lookup_decl_die (tree decl)
*** 5413,5418 ****
--- 5483,5668 ----
    return *die;
  }
  
+ 
+ /* For DECL which might have early dwarf output query a SYMBOL + OFFSET
+    style reference.  Return true if we found one refering to a DIE for
+    DECL, otherwise return false.  */
+ 
+ static bool
+ dwarf2out_die_ref_for_decl (tree decl, const char **sym,
+ 			    unsigned HOST_WIDE_INT *off)
+ {
+   dw_die_ref die;
+ 
+   if (flag_wpa && !decl_die_table)
+     return false;
+ 
+   if (TREE_CODE (decl) == BLOCK)
+     die = BLOCK_DIE (decl);
+   else
+     die = lookup_decl_die (decl);
+   if (!die)
+     return false;
+ 
+   /* During WPA stage we currently use DIEs to store the
+      decl <-> label + offset map.  That's quite inefficient but it
+      works for now.  */
+   if (flag_wpa)
+     {
+       dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
+       if (!ref)
+ 	{
+ 	  gcc_assert (die == comp_unit_die ());
+ 	  return false;
+ 	}
+       *off = ref->die_offset;
+       *sym = ref->die_id.die_symbol;
+       return true;
+     }
+ 
+   /* Similar to get_ref_die_offset_label, but using the "correct"
+      label.  */
+   *off = die->die_offset;
+   while (die->die_parent)
+     die = die->die_parent;
+   /* For the containing CU DIE we compute a die_symbol in
+      compute_section_prefix.  */
+   gcc_assert (die->die_tag == DW_TAG_compile_unit
+ 	      && die->die_id.die_symbol != NULL);
+   *sym = die->die_id.die_symbol;
+   return true;
+ }
+ 
+ /* Add a reference of kind ATTR_KIND to a DIE at SYMBOL + OFFSET to DIE.  */
+ 
+ static void
+ add_AT_external_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind,
+ 			 const char *symbol, HOST_WIDE_INT offset)
+ {
+   /* Create a fake DIE that contains the reference.  Don't use
+      new_die because we don't want to end up in the limbo list.  */
+   dw_die_ref ref = ggc_cleared_alloc<die_node> ();
+   ref->die_tag = die->die_tag;
+   ref->die_id.die_symbol = IDENTIFIER_POINTER (get_identifier (symbol));
+   ref->die_offset = offset;
+   ref->with_offset = 1;
+   add_AT_die_ref (die, attr_kind, ref);
+ }
+ 
+ /* Create a DIE for DECL if required and add a reference to a DIE
+    at SYMBOL + OFFSET which contains attributes dumped early.  */
+ 
+ static void
+ dwarf2out_register_external_die (tree decl, const char *sym,
+ 				 unsigned HOST_WIDE_INT off)
+ {
+   if (debug_info_level == DINFO_LEVEL_NONE)
+     return;
+ 
+   if (flag_wpa && !decl_die_table)
+     decl_die_table = hash_table<decl_die_hasher>::create_ggc (1000);
+ 
+   dw_die_ref die
+     = TREE_CODE (decl) == BLOCK ? BLOCK_DIE (decl) : lookup_decl_die (decl);
+   gcc_assert (!die);
+ 
+   tree ctx;
+   dw_die_ref parent = NULL;
+   /* Need to lookup a DIE for the decls context - the containing
+      function or translation unit.  */
+   if (TREE_CODE (decl) == BLOCK)
+     {
+       ctx = BLOCK_SUPERCONTEXT (decl);
+       /* ???  We do not output DIEs for all scopes thus skip as
+ 	 many DIEs as needed.  */
+       while (TREE_CODE (ctx) == BLOCK
+ 	     && !BLOCK_DIE (ctx))
+ 	ctx = BLOCK_SUPERCONTEXT (ctx);
+     }
+   else
+     ctx = DECL_CONTEXT (decl);
+   while (ctx && TYPE_P (ctx))
+     ctx = TYPE_CONTEXT (ctx);
+   if (ctx)
+     {
+       if (TREE_CODE (ctx) == BLOCK)
+ 	parent = BLOCK_DIE (ctx);
+       else if (TREE_CODE (ctx) == TRANSLATION_UNIT_DECL
+ 	       /* Keep the 1:1 association during WPA.  */
+ 	       && !flag_wpa)
+ 	/* Otherwise all late annotations go to the main CU which
+ 	   imports the original CUs.  */
+ 	parent = comp_unit_die ();
+       else if (TREE_CODE (ctx) == FUNCTION_DECL
+ 	       && TREE_CODE (decl) != PARM_DECL
+ 	       && TREE_CODE (decl) != BLOCK)
+ 	/* Leave function local entities parent determination to when
+ 	   we process scope vars.  */
+ 	;
+       else
+ 	parent = lookup_decl_die (ctx);
+     }
+   else
+     /* ???  In some cases the C++ FE (at least) fails to
+        set DECL_CONTEXT properly.  Simply globalize stuff
+        in this case.  For example
+        __dso_handle created via iostream line 74 col 25.  */
+     parent = comp_unit_die ();
+   /* Create a DIE "stub".  */
+   switch (TREE_CODE (decl))
+     {
+     case TRANSLATION_UNIT_DECL:
+       if (! flag_wpa)
+ 	{
+ 	  die = comp_unit_die ();
+ 	  dw_die_ref import = new_die (DW_TAG_imported_unit, die, NULL_TREE);
+ 	  add_AT_external_die_ref (import, DW_AT_import, sym, off);
+ 	  /* We re-target all CU decls to the LTRANS CU DIE, so no need
+ 	     to create a DIE for the original CUs.  */
+ 	  return;
+ 	}
+       /* Keep the 1:1 association during WPA.  */
+       die = new_die (DW_TAG_compile_unit, NULL, decl);
+       break;
+     case NAMESPACE_DECL:
+       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
+ 	 at the input language (if we have enough DECL_CONTEXT to follow)
+ 	 or use a bit in tree_decl_with_vis to record the distinction.  */
+       die = new_die (DW_TAG_namespace, parent, decl);
+       break;
+     case FUNCTION_DECL:
+       die = new_die (DW_TAG_subprogram, parent, decl);
+       break;
+     case VAR_DECL:
+       die = new_die (DW_TAG_variable, parent, decl);
+       break;
+     case RESULT_DECL:
+       die = new_die (DW_TAG_variable, parent, decl);
+       break;
+     case PARM_DECL:
+       die = new_die (DW_TAG_formal_parameter, parent, decl);
+       break;
+     case CONST_DECL:
+       die = new_die (DW_TAG_constant, parent, decl);
+       break;
+     case LABEL_DECL:
+       die = new_die (DW_TAG_label, parent, decl);
+       break;
+     case BLOCK:
+       die = new_die (DW_TAG_lexical_block, parent, decl);
+       break;
+     default:
+       gcc_unreachable ();
+     }
+   if (TREE_CODE (decl) == BLOCK)
+     BLOCK_DIE (decl) = die;
+   else
+     equate_decl_number_to_die (decl, die);
+ 
+   /* Add a reference to the DIE providing early debug at $sym + off.  */
+   add_AT_external_die_ref (die, DW_AT_abstract_origin, sym, off);
+ }
+ 
  /* Returns a hash value for X (which really is a var_loc_list).  */
  
  inline hashval_t
*************** print_dw_val (dw_val_node *val, bool rec
*** 5900,5906 ****
  			       die->die_id.die_type_node->signature);
  	    }
  	  else if (die->die_id.die_symbol)
! 	    fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
  	  else
  	    fprintf (outfile, "die -> %ld", die->die_offset);
  	  fprintf (outfile, " (%p)", (void *) die);
--- 6150,6160 ----
  			       die->die_id.die_type_node->signature);
  	    }
  	  else if (die->die_id.die_symbol)
! 	    {
! 	      fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
! 	      if (die->with_offset)
! 		fprintf (outfile, " + %ld", die->die_offset);
! 	    }
  	  else
  	    fprintf (outfile, "die -> %ld", die->die_offset);
  	  fprintf (outfile, " (%p)", (void *) die);
*************** static unsigned int comdat_symbol_number
*** 7216,7222 ****
     children, and set comdat_symbol_id accordingly.  */
  
  static void
! compute_section_prefix (dw_die_ref unit_die)
  {
    const char *die_name = get_AT_string (unit_die, DW_AT_name);
    const char *base = die_name ? lbasename (die_name) : "anonymous";
--- 7470,7476 ----
     children, and set comdat_symbol_id accordingly.  */
  
  static void
! compute_section_prefix_1 (dw_die_ref unit_die, bool comdat_p)
  {
    const char *die_name = get_AT_string (unit_die, DW_AT_name);
    const char *base = die_name ? lbasename (die_name) : "anonymous";
*************** compute_section_prefix (dw_die_ref unit_
*** 7235,7241 ****
    unmark_all_dies (unit_die);
    md5_finish_ctx (&ctx, checksum);
  
!   sprintf (name, "%s.", base);
    clean_symbol_name (name);
  
    p = name + strlen (name);
--- 7489,7499 ----
    unmark_all_dies (unit_die);
    md5_finish_ctx (&ctx, checksum);
  
!   /* When we this for comp_unit_die () we have a DW_AT_name that might
!      not start with a letter but with anything valid for filenames and
!      clean_symbol_name doesn't fix that up.  Prepend 'g' if the first
!      character is not a letter.  */
!   sprintf (name, "%s%s.", ISALPHA (*base) ? "" : "g", base);
    clean_symbol_name (name);
  
    p = name + strlen (name);
*************** compute_section_prefix (dw_die_ref unit_
*** 7245,7251 ****
        p += 2;
      }
  
!   comdat_symbol_id = unit_die->die_id.die_symbol = xstrdup (name);
    comdat_symbol_number = 0;
  }
  
--- 7503,7517 ----
        p += 2;
      }
  
!   unit_die->die_id.die_symbol = xstrdup (name);
!   unit_die->comdat_type_p = comdat_p;
! }
! 
! static void
! compute_section_prefix (dw_die_ref unit_die)
! {
!   compute_section_prefix_1 (unit_die, true);
!   comdat_symbol_id = unit_die->die_id.die_symbol;
    comdat_symbol_number = 0;
  }
  
*************** output_die (dw_die_ref die)
*** 9971,9977 ****
  
    /* If someone in another CU might refer to us, set up a symbol for
       them to point to.  */
!   if (! die->comdat_type_p && die->die_id.die_symbol)
      output_die_symbol (die);
  
    dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
--- 10237,10247 ----
  
    /* If someone in another CU might refer to us, set up a symbol for
       them to point to.  */
!   if (! die->comdat_type_p && die->die_id.die_symbol
!       /* Don't output the symbol twice.  For LTO we want the label
!          on the section beginning, not on the actual DIE.  */
!       && (!flag_generate_lto
! 	  || die->die_tag != DW_TAG_compile_unit))
      output_die_symbol (die);
  
    dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
*************** output_die (dw_die_ref die)
*** 10164,10171 ****
  		    size = DWARF2_ADDR_SIZE;
  		  else
  		    size = DWARF_OFFSET_SIZE;
! 		  dw2_asm_output_offset (size, sym, debug_info_section, "%s",
! 					 name);
  		}
  	    }
  	  else
--- 10434,10453 ----
  		    size = DWARF2_ADDR_SIZE;
  		  else
  		    size = DWARF_OFFSET_SIZE;
! 		  /* ???  We cannot unconditionally output die_offset if
! 		     non-zero - at least -feliminate-dwarf2-dups will
! 		     create references to those DIEs via symbols.  And we
! 		     do not clear its DIE offset after outputting it
! 		     (and the label refers to the actual DIEs, not the
! 		     DWARF CU unit header which is when using label + offset
! 		     would be the correct thing to do).
! 		     ???  This is the reason for the with_offset flag.  */
! 		  if (AT_ref (a)->with_offset)
! 		    dw2_asm_output_offset (size, sym, AT_ref (a)->die_offset,
! 					   debug_info_section, "%s", name);
! 		  else
! 		    dw2_asm_output_offset (size, sym, debug_info_section, "%s",
! 					   name);
  		}
  	    }
  	  else
*************** output_comp_unit (dw_die_ref die, int ou
*** 10391,10397 ****
    calc_die_sizes (die);
  
    oldsym = die->die_id.die_symbol;
!   if (oldsym)
      {
        tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
  
--- 10673,10679 ----
    calc_die_sizes (die);
  
    oldsym = die->die_id.die_symbol;
!   if (oldsym && die->comdat_type_p)
      {
        tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
  
*************** output_comp_unit (dw_die_ref die, int ou
*** 10407,10412 ****
--- 10689,10721 ----
        info_section_emitted = true;
      }
  
+   /* For LTO cross unit DIE refs we want a symbol on the start of the
+      debuginfo section, not on the CU DIE.
+      ???  We could simply use the symbol as it would be output by output_die
+      and account for the extra offset produced by the CU header which has fixed
+      size.  OTOH it currently only supports linkonce globals which would
+      be less than ideal?.  */
+   if (flag_generate_lto && oldsym)
+     {
+       /* ???  No way to get visibility assembled without a decl.  */
+       tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ 			      get_identifier (oldsym), char_type_node);
+       TREE_PUBLIC (decl) = true;
+       TREE_STATIC (decl) = true;
+       DECL_ARTIFICIAL (decl) = true;
+       DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+       DECL_VISIBILITY_SPECIFIED (decl) = true;
+       targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
+ #ifdef ASM_WEAKEN_LABEL
+       /* We prefer a .weak because that handles duplicates from duplicate
+          archive members in a graceful way.  */
+       ASM_WEAKEN_LABEL (asm_out_file, oldsym);
+ #else
+       targetm.asm_out.globalize_label (asm_out_file, oldsym);
+ #endif
+       ASM_OUTPUT_LABEL (asm_out_file, oldsym);
+     }
+ 
    /* Output debugging information.  */
    output_compilation_unit_header (dwo_id
  				  ? DW_UT_split_compile : DW_UT_compile);
*************** parameter_ref_descriptor (rtx rtl)
*** 14523,14528 ****
--- 14832,14840 ----
    if (dwarf_strict)
      return NULL;
    gcc_assert (TREE_CODE (DEBUG_PARAMETER_REF_DECL (rtl)) == PARM_DECL);
+   /* With LTO during LTRANS we get the late DIE that refers to the early
+      DIE, thus we add another indirection here.  This seems to confuse
+      gdb enough to make gcc.dg/guality/pr68860-1.c FAIL with LTO.  */
    ref = lookup_decl_die (DEBUG_PARAMETER_REF_DECL (rtl));
    ret = new_loc_descr (DW_OP_GNU_parameter_ref, 0, 0);
    if (ref)
*************** add_abstract_origin_attribute (dw_die_re
*** 20216,20222 ****
      }
  
    if (DECL_P (origin))
!     origin_die = lookup_decl_die (origin);
    else if (TYPE_P (origin))
      origin_die = lookup_type_die (origin);
    else if (TREE_CODE (origin) == BLOCK)
--- 20528,20547 ----
      }
  
    if (DECL_P (origin))
!     {
!       dw_die_ref c;
!       origin_die = lookup_decl_die (origin);
!       /* "Unwrap" the decls DIE which we put in the imported unit context.
!           ???  If we finish dwarf2out_function_decl refactoring we can
! 	  do this in a better way from the start and only lazily emit
! 	  the early DIE references.  */
!       if (in_lto_p
! 	  && origin_die
! 	  && (c = get_AT_ref (origin_die, DW_AT_abstract_origin))
! 	  /* ???  Identify this better.  */
! 	  && c->with_offset)
! 	origin_die = c;
!     }
    else if (TYPE_P (origin))
      origin_die = lookup_type_die (origin);
    else if (TREE_CODE (origin) == BLOCK)
*************** gen_array_type_die (tree type, dw_die_re
*** 20775,20781 ****
        size = int_size_in_bytes (type);
        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)
  	{
  	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
--- 21100,21109 ----
        size = int_size_in_bytes (type);
        if (size >= 0)
  	add_AT_unsigned (array_die, DW_AT_byte_size, size);
!       /* ???  We can't annotate types late, but for LTO we may not
! 	 generate a location early either (gfortran.dg/save_6.f90).  */
!       else if (! (early_dwarf && flag_generate_lto)
! 	       && TYPE_DOMAIN (type) != NULL_TREE
  	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE)
  	{
  	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
*************** gen_formal_parameter_die (tree node, tre
*** 21188,21194 ****
  	 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
--- 21516,21524 ----
  	 thing.  */
        if (parm_die && parm_die->die_parent != context_die)
  	{
! 	  /* ???  The DIE parent is the "abstract" copy and the context_die
! 	     is the specification "copy".  */
! 	  if (!DECL_ABSTRACT_P (node) && !in_lto_p)
  	    {
  	      /* This can happen when creating an inlined instance, in
  		 which case we need to create a new DIE that will get
*************** gen_type_die_for_member (tree type, tree
*** 21462,21468 ****
  /* 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, 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
--- 21792,21797 ----
*************** set_decl_origin_self (tree decl)
*** 21535,21685 ****
      }
  }
  \f
! /* 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, vec<tree> &abstract_vec)
! {
!   tree local_decl;
!   tree subblock;
!   unsigned int i;
! 
!   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, abstract_vec);
! 
!   for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
!     {
!       local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i);
!       if ((VAR_P (local_decl) && !TREE_STATIC (local_decl))
! 	  || TREE_CODE (local_decl) == PARM_DECL)
! 	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, abstract_vec);
! }
! 
! /* 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, vec<tree> &abstract_vec)
! {
!   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))
! 	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), 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.
! 
!    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)
  {
    dw_die_ref old_die;
-   tree save_fn;
-   tree context;
-   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;
-   struct call_arg_loc_node *old_call_arg_locations;
  
    /* Make sure we have the actual abstract inline, not a clone.  */
    decl = DECL_ORIGIN (decl);
  
    old_die = lookup_decl_die (decl);
!   if (old_die && get_AT (old_die, DW_AT_inline))
      /* We've already generated the abstract instance.  */
      return;
  
!   /* We can be called while recursively when seeing block defining inlined subroutine
!      DIE.  Be sure to not clobber the outer location table nor use it or we would
!      get locations in abstract instantces.  */
!   old_decl_loc_table = decl_loc_table;
!   decl_loc_table = NULL;
!   old_cached_dw_loc_list_table = cached_dw_loc_list_table;
!   cached_dw_loc_list_table = NULL;
!   old_call_arg_locations = call_arg_locations;
!   call_arg_locations = NULL;
!   old_call_site_count = call_site_count;
!   call_site_count = -1;
!   old_tail_call_site_count = tail_call_site_count;
!   tail_call_site_count = -1;
! 
!   /* Be sure we've emitted the in-class declaration DIE (if any) first, so
!      we don't get confused by DECL_ABSTRACT_P.  */
!   if (debug_info_level > DINFO_LEVEL_TERSE)
      {
!       context = decl_class_context (decl);
!       if (context)
! 	gen_type_die_for_member
! 	  (context, decl, decl_function_context (decl) ? NULL : comp_unit_die ());
      }
  
!   /* Pretend we've just finished compiling this function.  */
!   save_fn = current_function_decl;
!   current_function_decl = decl;
! 
!   auto_vec<tree, 64> abstract_vec;
!   set_decl_abstract_flags (decl, abstract_vec);
!   dwarf2out_decl (decl);
!   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;
!   cached_dw_loc_list_table = old_cached_dw_loc_list_table;
!   call_arg_locations = old_call_arg_locations;
!   call_site_count = old_call_site_count;
!   tail_call_site_count = old_tail_call_site_count;
  }
  
  /* Helper function of premark_used_types() which gets called through
--- 21864,21908 ----
      }
  }
  \f
! /* Mark the early DIE for DECL as the abstract instance.  */
  
  static void
  dwarf2out_abstract_function (tree decl)
  {
    dw_die_ref old_die;
  
    /* Make sure we have the actual abstract inline, not a clone.  */
    decl = DECL_ORIGIN (decl);
  
+   if (DECL_IGNORED_P (decl))
+     return;
+ 
    old_die = lookup_decl_die (decl);
!   /* With early debug we always have an old DIE.  */
!   gcc_assert (old_die != NULL);
!   if (get_AT (old_die, DW_AT_inline))
      /* We've already generated the abstract instance.  */
      return;
  
!   /* Go ahead and put DW_AT_inline on the DIE.  */
!   if (DECL_DECLARED_INLINE_P (decl))
      {
!       if (cgraph_function_possibly_inlined_p (decl))
! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_inlined);
!       else
! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_not_inlined);
!     }
!   else
!     {
!       if (cgraph_function_possibly_inlined_p (decl))
! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_inlined);
!       else
! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_not_inlined);
      }
  
!   if (DECL_DECLARED_INLINE_P (decl)
!       && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
!     add_AT_flag (old_die, DW_AT_artificial, 1);
  }
  
  /* Helper function of premark_used_types() which gets called through
*************** gen_subprogram_die (tree decl, dw_die_re
*** 21901,21907 ****
        if (old_die && old_die->die_parent == NULL)
  	add_child_die (context_die, old_die);
  
!       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.  */
--- 22124,22135 ----
        if (old_die && old_die->die_parent == NULL)
  	add_child_die (context_die, old_die);
  
!       dw_die_ref c;
!       if (old_die
! 	  && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
! 	  /* ???  In LTO all origin DIEs still refer to the early
! 	     debug copy.  Detect that.  */
! 	  && get_AT (c, DW_AT_inline))
  	{
  	  /* If we have a DW_AT_abstract_origin we have a working
  	     cached version.  */
*************** gen_subprogram_die (tree decl, dw_die_re
*** 21969,21975 ****
  	   || (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)
--- 22197,22204 ----
  	   || (old_die->die_parent
  	       && old_die->die_parent->die_tag == DW_TAG_module)
  	   || context_die == NULL)
! 	  /* ???  In LTO we do not see any of the location attributes.  */
! 	   && ((DECL_ARTIFICIAL (decl) || in_lto_p)
  	       || (get_AT_file (old_die, DW_AT_decl_file) == file_index
  		   && (get_AT_unsigned (old_die, DW_AT_decl_line)
  		       == (unsigned) s.line)
*************** gen_variable_die (tree decl, tree origin
*** 22836,22841 ****
--- 23065,23088 ----
  	  /* If a DIE was dumped early, it still needs location info.
  	     Skip to where we fill the location bits.  */
  	  var_die = old_die;
+ 
+ 	  /* ???  In LTRANS we cannot annotate early created variably
+ 	     modified type DIEs without copying them and adjusting all
+ 	     references to them.  Thus we dumped them again, also add a
+ 	     reference to them.  */
+ 	  tree type = TREE_TYPE (decl_or_origin);
+ 	  if (in_lto_p
+ 	      && variably_modified_type_p
+ 		   (type, decl_function_context (decl_or_origin)))
+ 	    {
+ 	      if (decl_by_reference_p (decl_or_origin))
+ 		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),
+ 				    false, context_die);
+ 	    }
+ 
  	  goto gen_variable_die_location;
  	}
      }
*************** gen_inlined_subroutine_die (tree stmt, d
*** 23236,23247 ****
    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
-      a die whose origin die hasn't been emitted, and crashing.  */
-   dwarf2out_abstract_function (decl);
- 
    if (! BLOCK_ABSTRACT (stmt))
      {
        dw_die_ref subr_die
--- 23483,23488 ----
*************** process_scope_var (tree stmt, tree decl,
*** 24868,24874 ****
  					     stmt, context_die);
      }
    else
!     gen_decl_die (decl, origin, NULL, context_die);
  }
  
  /* Generate all of the decls declared within a given scope and (recursively)
--- 25109,25128 ----
  					     stmt, context_die);
      }
    else
!     {
!       if (decl && DECL_P (decl))
! 	{
! 	  die = lookup_decl_die (decl);
! 
! 	  /* Early created DIEs do not have a parent as the decls refer
! 	     to the function as DECL_CONTEXT rather than the BLOCK.  */
! 	  if (in_lto_p
! 	      && die && die->die_parent == NULL)
! 	    add_child_die (context_die, die);
! 	}
! 
!       gen_decl_die (decl, origin, NULL, context_die);
!     }
  }
  
  /* Generate all of the decls declared within a given scope and (recursively)
*************** gen_decl_die (tree decl, tree origin, st
*** 25288,25295 ****
  				     ? DECL_ORIGIN (origin)
  				     : DECL_ABSTRACT_ORIGIN (decl));
  
!       /* If we're emitting an out-of-line copy of an inline function,
! 	 emit info for the abstract instance and set up to refer to it.  */
        else if (cgraph_function_possibly_inlined_p (decl)
  	       && ! DECL_ABSTRACT_P (decl)
  	       && ! class_or_namespace_scope_p (context_die)
--- 25542,25549 ----
  				     ? DECL_ORIGIN (origin)
  				     : DECL_ABSTRACT_ORIGIN (decl));
  
!       /* If we're emitting a possibly inlined function emit it as
!          abstract instance.  */
        else if (cgraph_function_possibly_inlined_p (decl)
  	       && ! DECL_ABSTRACT_P (decl)
  	       && ! class_or_namespace_scope_p (context_die)
*************** gen_decl_die (tree decl, tree origin, st
*** 25303,25309 ****
  	}
  
        /* Otherwise we're emitting the primary DIE for this decl.  */
!       else if (debug_info_level > DINFO_LEVEL_TERSE)
  	{
  	  /* Before we describe the FUNCTION_DECL itself, make sure that we
  	     have its containing type.  */
--- 25557,25565 ----
  	}
  
        /* Otherwise we're emitting the primary DIE for this decl.  */
!       else if (debug_info_level > DINFO_LEVEL_TERSE
! 	       /* Do not generate stray type DIEs in late LTO dumping.  */
! 	       && early_dwarf)
  	{
  	  /* Before we describe the FUNCTION_DECL itself, make sure that we
  	     have its containing type.  */
*************** gen_decl_die (tree decl, tree origin, st
*** 25370,25389 ****
        if (debug_info_level <= DINFO_LEVEL_TERSE)
  	break;
  
!       /* Output any DIEs that are needed to specify the type of this data
! 	 object.  */
!       if (decl_by_reference_p (decl_or_origin))
! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
!       else
! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
  
!       /* And its containing type.  */
!       class_origin = decl_class_context (decl_or_origin);
!       if (class_origin != NULL_TREE)
! 	gen_type_die_for_member (class_origin, decl_or_origin, context_die);
  
!       /* And its containing namespace.  */
!       context_die = declare_in_namespace (decl_or_origin, context_die);
  
        /* Now output the DIE to represent the data object itself.  This gets
  	 complicated because of the possibility that the VAR_DECL really
--- 25626,25661 ----
        if (debug_info_level <= DINFO_LEVEL_TERSE)
  	break;
  
!       /* Avoid generating stray type DIEs during late dwarf dumping.
!          All types have been dumped early.  */
!       if (! lookup_decl_die (decl_or_origin)
! 	  /* ???  But in LTRANS we cannot annotate early created variably
! 	     modified type DIEs without copying them and adjusting all
! 	     references to them.  Dump them again as happens for inlining
! 	     which copies both the decl and the types.  */
! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
! 	     in VLA bound information for example.  */
! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
! 						current_function_decl)))
! 	{
! 	  /* Output any DIEs that are needed to specify the type of this data
! 	     object.  */
! 	  if (decl_by_reference_p (decl_or_origin))
! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
! 	  else
! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
! 	}
  
!       if (early_dwarf)
! 	{
! 	  /* And its containing type.  */
! 	  class_origin = decl_class_context (decl_or_origin);
! 	  if (class_origin != NULL_TREE)
! 	    gen_type_die_for_member (class_origin, decl_or_origin, context_die);
  
! 	  /* And its containing namespace.  */
! 	  context_die = declare_in_namespace (decl_or_origin, context_die);
! 	}
  
        /* Now output the DIE to represent the data object itself.  This gets
  	 complicated because of the possibility that the VAR_DECL really
*************** gen_decl_die (tree decl, tree origin, st
*** 25413,25422 ****
        break;
  
      case PARM_DECL:
!       if (DECL_BY_REFERENCE (decl_or_origin))
! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
!       else
! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
        return gen_formal_parameter_die (decl, origin,
  				       true /* Emit name attribute.  */,
  				       context_die);
--- 25685,25707 ----
        break;
  
      case PARM_DECL:
!       /* Avoid generating stray type DIEs during late dwarf dumping.
!          All types have been dumped early.  */
!       if (! lookup_decl_die (decl_or_origin)
! 	  /* ???  But in LTRANS we cannot annotate early created variably
! 	     modified type DIEs without copying them and adjusting all
! 	     references to them.  Dump them again as happens for inlining
! 	     which copies both the decl and the types.  */
! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
! 	     in VLA bound information for example.  */
! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
! 						current_function_decl)))
! 	{
! 	  if (DECL_BY_REFERENCE (decl_or_origin))
! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
! 	  else
! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
! 	}
        return gen_formal_parameter_die (decl, origin,
  				       true /* Emit name attribute.  */,
  				       context_die);
*************** dwarf2out_early_global_decl (tree decl)
*** 25493,25498 ****
--- 25778,25793 ----
  	      dwarf2out_decl (context);
  	    }
  
+ 	  /* Emit an abstract origin of a function first.  This happens
+ 	     with C++ constructor clones for example and makes
+ 	     dwarf2out_abstract_function happy which requires the early
+ 	     DIE of the abstract instance to be present.  */
+ 	  if (DECL_ABSTRACT_ORIGIN (decl))
+ 	    {
+ 	      current_function_decl = DECL_ABSTRACT_ORIGIN (decl);
+ 	      dwarf2out_decl (DECL_ABSTRACT_ORIGIN (decl));
+ 	    }
+ 
  	  current_function_decl = decl;
  	}
        dwarf2out_decl (decl);
*************** dwarf2out_late_global_decl (tree decl)
*** 25515,25521 ****
      {
        dw_die_ref die = lookup_decl_die (decl);
  
!       /* We have to generate early debug late for LTO.  */
        if (! die && in_lto_p)
  	{
  	  dwarf2out_decl (decl);
--- 25810,25818 ----
      {
        dw_die_ref die = lookup_decl_die (decl);
  
!       /* We may have to generate early debug late for LTO in case debug
!          was not enabled at compile-time or the target doesn't support
! 	 the LTO early debug scheme.  */
        if (! die && in_lto_p)
  	{
  	  dwarf2out_decl (decl);
*************** output_macinfo_op (macinfo_entry *ref)
*** 26892,26898 ****
      case DW_MACRO_import:
        dw2_asm_output_data (1, ref->code, "Import");
        ASM_GENERATE_INTERNAL_LABEL (label,
! 				   DEBUG_MACRO_SECTION_LABEL, ref->lineno);
        dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
        break;
      default:
--- 27189,27196 ----
      case DW_MACRO_import:
        dw2_asm_output_data (1, ref->code, "Import");
        ASM_GENERATE_INTERNAL_LABEL (label,
! 				   DEBUG_MACRO_SECTION_LABEL,
! 				   ref->lineno + macinfo_label_base);
        dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
        break;
      default:
*************** save_macinfo_strings (void)
*** 27066,27072 ****
  /* Output macinfo section(s).  */
  
  static void
! output_macinfo (void)
  {
    unsigned i;
    unsigned long length = vec_safe_length (macinfo_table);
--- 27364,27370 ----
  /* Output macinfo section(s).  */
  
  static void
! output_macinfo (const char *debug_line_label, bool early_lto_debug)
  {
    unsigned i;
    unsigned long length = vec_safe_length (macinfo_table);
*************** output_macinfo (void)
*** 27092,27100 ****
  	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
        else
  	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
!       dw2_asm_output_offset (DWARF_OFFSET_SIZE,
!                              (!dwarf_split_debug_info ? debug_line_section_label
!                               : debug_skeleton_line_section_label),
                               debug_line_section, NULL);
      }
  
--- 27390,27396 ----
  	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
        else
  	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
!       dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_line_label,
                               debug_line_section, NULL);
      }
  
*************** output_macinfo (void)
*** 27148,27153 ****
--- 27444,27453 ----
    if (!macinfo_htab)
      return;
  
+   /* Save the number of transparent includes so we can adjust the
+      label number for the fat LTO object DWARF.  */
+   unsigned macinfo_label_base_adj = macinfo_htab->elements ();
+ 
    delete macinfo_htab;
    macinfo_htab = NULL;
  
*************** output_macinfo (void)
*** 27167,27177 ****
  	  dw2_asm_output_data (1, 0, "End compilation unit");
  	  targetm.asm_out.named_section (debug_macinfo_section_name,
  					 SECTION_DEBUG
! 					 | SECTION_LINKONCE,
  					 comdat_key);
  	  ASM_GENERATE_INTERNAL_LABEL (label,
  				       DEBUG_MACRO_SECTION_LABEL,
! 				       ref->lineno);
  	  ASM_OUTPUT_LABEL (asm_out_file, label);
  	  ref->code = 0;
  	  ref->info = NULL;
--- 27467,27479 ----
  	  dw2_asm_output_data (1, 0, "End compilation unit");
  	  targetm.asm_out.named_section (debug_macinfo_section_name,
  					 SECTION_DEBUG
! 					 | SECTION_LINKONCE
! 					 | (early_lto_debug
! 					    ? SECTION_EXCLUDE : 0),
  					 comdat_key);
  	  ASM_GENERATE_INTERNAL_LABEL (label,
  				       DEBUG_MACRO_SECTION_LABEL,
! 				       ref->lineno + macinfo_label_base);
  	  ASM_OUTPUT_LABEL (asm_out_file, label);
  	  ref->code = 0;
  	  ref->info = NULL;
*************** output_macinfo (void)
*** 27192,27300 ****
        default:
  	gcc_unreachable ();
        }
  }
  
! /* Initialize the various sections and labels for dwarf output.  */
  
  static void
! init_sections_and_labels (void)
  {
!   if (!dwarf_split_debug_info)
      {
!       debug_info_section = get_section (DEBUG_INFO_SECTION,
!                                         SECTION_DEBUG, NULL);
!       debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
!                                           SECTION_DEBUG, NULL);
!       debug_loc_section = get_section (dwarf_version >= 5
! 				       ? DEBUG_LOCLISTS_SECTION
! 				       : DEBUG_LOC_SECTION,
!                                        SECTION_DEBUG, NULL);
!       debug_macinfo_section_name
! 	= (dwarf_strict && dwarf_version < 5)
! 	  ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
!       debug_macinfo_section = get_section (debug_macinfo_section_name,
! 					   SECTION_DEBUG, NULL);
      }
    else
      {
!       debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
!                                         SECTION_DEBUG | SECTION_EXCLUDE, NULL);
!       debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
!                                           SECTION_DEBUG | SECTION_EXCLUDE,
!                                           NULL);
!       debug_addr_section = get_section (DEBUG_ADDR_SECTION,
!                                         SECTION_DEBUG, NULL);
!       debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
!                                                  SECTION_DEBUG, NULL);
!       debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
!                                                    SECTION_DEBUG, NULL);
!       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
!                                   DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0);
! 
!       /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
!          the main .o, but the skeleton_line goes into the split off dwo.  */
!       debug_skeleton_line_section
!         = get_section (DEBUG_DWO_LINE_SECTION,
! 		       SECTION_DEBUG | SECTION_EXCLUDE, NULL);
!       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
!                                    DEBUG_SKELETON_LINE_SECTION_LABEL, 0);
!       debug_str_offsets_section = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
!                                                SECTION_DEBUG | SECTION_EXCLUDE,
!                                                NULL);
!       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
!                                    DEBUG_SKELETON_INFO_SECTION_LABEL, 0);
!       debug_loc_section = get_section (dwarf_version >= 5
! 				       ? DEBUG_DWO_LOCLISTS_SECTION
! 				       : DEBUG_DWO_LOC_SECTION,
!                                        SECTION_DEBUG | SECTION_EXCLUDE, NULL);
!       debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
!                                            DEBUG_STR_DWO_SECTION_FLAGS, NULL);
!       debug_macinfo_section_name
! 	= (dwarf_strict && dwarf_version < 5)
! 	  ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
!       debug_macinfo_section = get_section (debug_macinfo_section_name,
  					   SECTION_DEBUG | SECTION_EXCLUDE,
  					   NULL);
!     }
!   debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
! 				       SECTION_DEBUG, NULL);
!   debug_line_section = get_section (DEBUG_LINE_SECTION,
! 				    SECTION_DEBUG, NULL);
!   debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
! 					SECTION_DEBUG, NULL);
!   debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
  					SECTION_DEBUG, NULL);
!   debug_str_section = get_section (DEBUG_STR_SECTION,
! 				   DEBUG_STR_SECTION_FLAGS, NULL);
!   if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
!     debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
! 					  DEBUG_STR_SECTION_FLAGS, NULL);
! 
!   debug_ranges_section = get_section (dwarf_version >= 5
! 				      ? DEBUG_RNGLISTS_SECTION
! 				      : DEBUG_RANGES_SECTION,
! 				      SECTION_DEBUG, NULL);
!   debug_frame_section = get_section (DEBUG_FRAME_SECTION,
! 				     SECTION_DEBUG, NULL);
  
    ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
! 			       DEBUG_ABBREV_SECTION_LABEL, 0);
    ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
! 			       DEBUG_INFO_SECTION_LABEL, 0);
    ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
! 			       DEBUG_LINE_SECTION_LABEL, 0);
    ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
! 			       DEBUG_RANGES_SECTION_LABEL, 0);
    if (dwarf_version >= 5 && dwarf_split_debug_info)
      ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
! 				 DEBUG_RANGES_SECTION_LABEL, 1);
    ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
!                                DEBUG_ADDR_SECTION_LABEL, 0);
    ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
  			       (dwarf_strict && dwarf_version < 5)
  			       ? DEBUG_MACINFO_SECTION_LABEL
! 			       : DEBUG_MACRO_SECTION_LABEL, 0);
!   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0);
  }
  
  /* Set up for Dwarf output at the start of compilation.  */
--- 27494,27685 ----
        default:
  	gcc_unreachable ();
        }
+ 
+   macinfo_label_base += macinfo_label_base_adj;
  }
  
! /* Initialize the various sections and labels for dwarf output and prefix
!    them with PREFIX if non-NULL.  */
  
  static void
! init_sections_and_labels (bool early_lto_debug)
  {
!   /* As we may get called multiple times have a generation count for labels.  */
!   static unsigned generation = 0;
! 
!   if (early_lto_debug)
      {
!       if (!dwarf_split_debug_info)
! 	{
! 	  debug_info_section = get_section (DEBUG_LTO_INFO_SECTION,
! 					    SECTION_DEBUG | SECTION_EXCLUDE,
! 					    NULL);
! 	  debug_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
! 					      SECTION_DEBUG | SECTION_EXCLUDE,
! 					      NULL);
! 	  debug_macinfo_section_name = ((dwarf_strict && dwarf_version < 5)
! 					? DEBUG_LTO_MACINFO_SECTION
! 					: DEBUG_LTO_MACRO_SECTION);
! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
! 					       SECTION_DEBUG
! 					       | SECTION_EXCLUDE, NULL);
! 	  /* For macro info we have to refer to a debug_line section, so similar
! 	     to split-dwarf emit a skeleton one for early debug.  */
! 	  debug_skeleton_line_section
! 	    = get_section (DEBUG_LTO_LINE_SECTION,
! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
! 				       generation);
! 	}
!       else
! 	{
! 	  /* ???  Which of the following do we need early?  */
! 	  debug_info_section = get_section (DEBUG_LTO_DWO_INFO_SECTION,
! 					    SECTION_DEBUG | SECTION_EXCLUDE,
! 					    NULL);
! 	  debug_abbrev_section = get_section (DEBUG_LTO_DWO_ABBREV_SECTION,
! 					      SECTION_DEBUG | SECTION_EXCLUDE,
! 					      NULL);
! 	  debug_skeleton_info_section = get_section (DEBUG_LTO_INFO_SECTION,
! 						     SECTION_DEBUG
! 						     | SECTION_EXCLUDE, NULL);
! 	  debug_skeleton_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
! 						       SECTION_DEBUG
! 						       | SECTION_EXCLUDE, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
! 				       generation);
! 
! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
! 	     the main .o, but the skeleton_line goes into the split off dwo.  */
! 	  debug_skeleton_line_section
! 	    = get_section (DEBUG_LTO_LINE_SECTION,
! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
! 				       generation);
! 	  debug_str_offsets_section
! 	    = get_section (DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
! 			   SECTION_DEBUG | SECTION_EXCLUDE,
! 			   NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
! 				       generation);
! 	  debug_str_dwo_section = get_section (DEBUG_LTO_STR_DWO_SECTION,
! 					       DEBUG_STR_DWO_SECTION_FLAGS, NULL);
! 	  debug_macinfo_section_name
! 	    = (dwarf_strict
! 	       ? DEBUG_LTO_DWO_MACINFO_SECTION : DEBUG_LTO_DWO_MACRO_SECTION);
! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
! 					       SECTION_DEBUG | SECTION_EXCLUDE,
! 					       NULL);
! 	}
!       debug_str_section = get_section (DEBUG_LTO_STR_SECTION,
! 				       DEBUG_STR_SECTION_FLAGS
! 				       | SECTION_EXCLUDE, NULL);
      }
    else
      {
!       if (!dwarf_split_debug_info)
! 	{
! 	  debug_info_section = get_section (DEBUG_INFO_SECTION,
! 					    SECTION_DEBUG, NULL);
! 	  debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
! 					      SECTION_DEBUG, NULL);
! 	  debug_loc_section = get_section (DEBUG_LOC_SECTION,
! 					   SECTION_DEBUG, NULL);
! 	  debug_macinfo_section_name
! 	      = dwarf_strict ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
! 					       SECTION_DEBUG, NULL);
! 	}
!       else
! 	{
! 	  debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
! 					    SECTION_DEBUG | SECTION_EXCLUDE,
! 					    NULL);
! 	  debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
! 					      SECTION_DEBUG | SECTION_EXCLUDE,
! 					      NULL);
! 	  debug_addr_section = get_section (DEBUG_ADDR_SECTION,
! 					    SECTION_DEBUG, NULL);
! 	  debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
! 						     SECTION_DEBUG, NULL);
! 	  debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
! 						       SECTION_DEBUG, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
! 				       generation);
! 
! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections
! 	     stay in the main .o, but the skeleton_line goes into the
! 	     split off dwo.  */
! 	  debug_skeleton_line_section
! 	      = get_section (DEBUG_DWO_LINE_SECTION,
! 			     SECTION_DEBUG | SECTION_EXCLUDE, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
! 				       generation);
! 	  debug_str_offsets_section
! 	    = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
! 				       generation);
! 	  debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION,
  					   SECTION_DEBUG | SECTION_EXCLUDE,
  					   NULL);
! 	  debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
! 					       DEBUG_STR_DWO_SECTION_FLAGS,
! 					       NULL);
! 	  debug_macinfo_section_name
! 	    = (dwarf_strict && dwarf_version < 5)
! 	      ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
! 					       SECTION_DEBUG | SECTION_EXCLUDE,
! 					       NULL);
! 	}
!       debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
! 					   SECTION_DEBUG, NULL);
!       debug_line_section = get_section (DEBUG_LINE_SECTION,
  					SECTION_DEBUG, NULL);
!       debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
! 					    SECTION_DEBUG, NULL);
!       debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
! 					    SECTION_DEBUG, NULL);
!       debug_str_section = get_section (DEBUG_STR_SECTION,
! 				       DEBUG_STR_SECTION_FLAGS, NULL);
!       debug_ranges_section = get_section (dwarf_version >= 5
! 					  ? DEBUG_RNGLISTS_SECTION
! 					  : DEBUG_RANGES_SECTION,
! 					  SECTION_DEBUG, NULL);
!       debug_frame_section = get_section (DEBUG_FRAME_SECTION,
! 					 SECTION_DEBUG, NULL);
!     }
  
    ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
! 			       DEBUG_ABBREV_SECTION_LABEL, generation);
    ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
! 			       DEBUG_INFO_SECTION_LABEL, generation);
!   info_section_emitted = false;
    ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
! 			       DEBUG_LINE_SECTION_LABEL, generation);
    ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
! 			       DEBUG_RANGES_SECTION_LABEL, generation);
    if (dwarf_version >= 5 && dwarf_split_debug_info)
      ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
! 				 DEBUG_RANGES_SECTION_LABEL, 2 + generation);
    ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
!                                DEBUG_ADDR_SECTION_LABEL, generation);
    ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
  			       (dwarf_strict && dwarf_version < 5)
  			       ? DEBUG_MACINFO_SECTION_LABEL
! 			       : DEBUG_MACRO_SECTION_LABEL, generation);
!   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL,
! 			       generation);
! 
!   ++generation;
  }
  
  /* Set up for Dwarf output at the start of compilation.  */
*************** flush_limbo_die_list (void)
*** 29641,29646 ****
--- 30026,30047 ----
      }
  }
  
+ /* Reset DIEs so we can output them again.  */
+ 
+ static void
+ reset_dies (dw_die_ref die)
+ {
+   dw_die_ref c;
+ 
+   /* Remove stuff we re-generate.  */
+   die->die_mark = 0;
+   die->die_offset = 0;
+   die->die_abbrev = 0;
+   remove_AT (die, DW_AT_sibling);
+ 
+   FOR_EACH_CHILD (die, c, reset_dies (c));
+ }
+ 
  /* Output stuff that dwarf requires at the end of every file,
     and generate the DWARF-2 debugging info.  */
  
*************** dwarf2out_finish (const char *)
*** 29667,29672 ****
--- 30068,30113 ----
  
    gen_remaining_tmpl_value_param_die_attribute ();
  
+   if (flag_generate_lto)
+     {
+       gcc_assert (flag_fat_lto_objects);
+ 
+       /* Prune stuff so that dwarf2out_finish runs successfully
+ 	 for the fat part of the object.  */
+       reset_dies (comp_unit_die ());
+       for (limbo_die_node *node = cu_die_list; node; node = node->next)
+ 	reset_dies (node->die);
+ 
+       hash_table<comdat_type_hasher> comdat_type_table (100);
+       for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
+ 	{
+ 	  comdat_type_node **slot
+ 	      = comdat_type_table.find_slot (ctnode, INSERT);
+ 
+ 	  /* Don't reset types twice.  */
+ 	  if (*slot != HTAB_EMPTY_ENTRY)
+ 	    continue;
+ 
+ 	  /* Add a pointer to the line table for the main compilation unit
+ 	     so that the debugger can make sense of DW_AT_decl_file
+ 	     attributes.  */
+ 	  if (debug_info_level >= DINFO_LEVEL_TERSE)
+ 	    reset_dies (ctnode->root_die);
+ 
+ 	  *slot = ctnode;
+ 	}
+ 
+       /* Reset die CU symbol so we don't output it twice.  */
+       comp_unit_die ()->die_id.die_symbol = NULL;
+ 
+       /* Remove DW_AT_macro from the early output.  */
+       if (have_macinfo)
+ 	remove_AT (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE);
+ 
+       /* Remove indirect string decisions.  */
+       debug_str_hash->traverse<void *, reset_indirect_string> (NULL);
+     }
+ 
  #if ENABLE_ASSERT_CHECKING
    {
      dw_die_ref die = comp_unit_die (), c;
*************** dwarf2out_finish (const char *)
*** 29677,29683 ****
    move_marked_base_types ();
  
    /* Initialize sections and labels used for actual assembler output.  */
!   init_sections_and_labels ();
  
    /* Traverse the DIE's and add sibling attributes to those DIE's that
       have children.  */
--- 30118,30124 ----
    move_marked_base_types ();
  
    /* Initialize sections and labels used for actual assembler output.  */
!   init_sections_and_labels (false);
  
    /* Traverse the DIE's and add sibling attributes to those DIE's that
       have children.  */
*************** dwarf2out_finish (const char *)
*** 29772,29780 ****
  		    debug_line_section_label);
  
    if (have_macinfo)
!     add_AT_macptr (comp_unit_die (),
! 		   dwarf_version >= 5 ? DW_AT_macros
! 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
  		   macinfo_section_label);
  
    if (dwarf_split_debug_info)
--- 30213,30219 ----
  		    debug_line_section_label);
  
    if (have_macinfo)
!     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
  		   macinfo_section_label);
  
    if (dwarf_split_debug_info)
*************** dwarf2out_finish (const char *)
*** 29979,29985 ****
      {
        switch_to_section (debug_macinfo_section);
        ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
!       output_macinfo ();
        dw2_asm_output_data (1, 0, "End compilation unit");
      }
  
--- 30418,30425 ----
      {
        switch_to_section (debug_macinfo_section);
        ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
!       output_macinfo (!dwarf_split_debug_info ? debug_line_section_label
! 		      : debug_skeleton_line_section_label, false);
        dw2_asm_output_data (1, 0, "End compilation unit");
      }
  
*************** note_variable_value_in_expr (dw_die_ref
*** 30200,30205 ****
--- 30640,30659 ----
        {
  	tree decl = loc->dw_loc_oprnd1.v.val_decl_ref;
  	dw_die_ref ref = lookup_decl_die (decl);
+ 	if (! ref && flag_generate_lto)
+ 	  {
+ 	    /* ???  This is somewhat a hack because we do not create DIEs
+ 	       for variables not in BLOCK trees early but when generating
+ 	       early LTO output we need the dw_val_class_decl_ref to be
+ 	       fully resolved.  For fat LTO objects we'd also like to
+ 	       undo this after LTO dwarf output.  */
+ 	    gcc_assert (DECL_CONTEXT (decl));
+ 	    dw_die_ref ctx = lookup_decl_die (DECL_CONTEXT (decl));
+ 	    gcc_assert (ctx != NULL);
+ 	    gen_decl_die (decl, NULL_TREE, NULL, ctx);
+ 	    ref = lookup_decl_die (decl);
+ 	    gcc_assert (ref != NULL);
+ 	  }
  	if (ref)
  	  {
  	    loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
*************** dwarf2out_early_finish (const char *file
*** 30410,30415 ****
--- 30864,30982 ----
  
    /* The early debug phase is now finished.  */
    early_dwarf_finished = true;
+ 
+   /* Do not generate DWARF assembler now when not producing LTO bytecode.  */
+   if (!flag_generate_lto)
+     return;
+ 
+   /* Now as we are going to output for LTO initialize sections and labels
+      to the LTO variants.  We don't need a random-seed postfix as other
+      LTO sections as linking the LTO debug sections into one in a partial
+      link is fine.  */
+   init_sections_and_labels (true);
+ 
+   /* The output below is modeled after dwarf2out_finish with all
+      location related output removed and some LTO specific changes.
+      Some refactoring might make both smaller and easier to match up.  */
+ 
+   /* Traverse the DIE's and add add sibling attributes to those DIE's
+      that have children.  */
+   add_sibling_attributes (comp_unit_die ());
+   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
+     add_sibling_attributes (node->die);
+   for (comdat_type_node *ctnode = comdat_type_list;
+        ctnode != NULL; ctnode = ctnode->next)
+     add_sibling_attributes (ctnode->root_die);
+ 
+   if (have_macinfo)
+     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
+ 		   macinfo_section_label);
+ 
+   save_macinfo_strings ();
+ 
+   /* Output all of the compilation units.  We put the main one last so that
+      the offsets are available to output_pubnames.  */
+   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
+     output_comp_unit (node->die, 0, NULL);
+ 
+   hash_table<comdat_type_hasher> comdat_type_table (100);
+   for (comdat_type_node *ctnode = comdat_type_list;
+        ctnode != NULL; ctnode = ctnode->next)
+     {
+       comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT);
+ 
+       /* Don't output duplicate types.  */
+       if (*slot != HTAB_EMPTY_ENTRY)
+         continue;
+ 
+       /* Add a pointer to the line table for the main compilation unit
+          so that the debugger can make sense of DW_AT_decl_file
+          attributes.  */
+       if (debug_info_level >= DINFO_LEVEL_TERSE)
+         add_AT_lineptr (ctnode->root_die, DW_AT_stmt_list,
+                         (!dwarf_split_debug_info
+                          ? debug_line_section_label
+                          : debug_skeleton_line_section_label));
+ 
+       output_comdat_type_unit (ctnode);
+       *slot = ctnode;
+     }
+ 
+   /* The AT_pubnames attribute needs to go in all skeleton dies, including
+      both the main_cu and all skeleton TUs.  Making this call unconditional
+      would end up either adding a second copy of the AT_pubnames attribute, or
+      requiring a special case in add_top_level_skeleton_die_attrs.  */
+   if (!dwarf_split_debug_info)
+     add_AT_pubnames (comp_unit_die ());
+ 
+   /* Stick a unique symbol to the main debuginfo section.  */
+   compute_section_prefix_1 (comp_unit_die (), false);
+ 
+   /* Output the main compilation unit.  We always need it if only for
+      the CU symbol.  */
+   output_comp_unit (comp_unit_die (), true, NULL);
+ 
+   /* Output the abbreviation table.  */
+   if (vec_safe_length (abbrev_die_table) != 1)
+     {
+       switch_to_section (debug_abbrev_section);
+       ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
+       output_abbrev_section ();
+     }
+ 
+   /* Have to end the macro section.  */
+   if (have_macinfo)
+     {
+       /* We have to save macinfo state if we need to output it again
+ 	 for the FAT part of the object.  */
+       vec<macinfo_entry, va_gc> *saved_macinfo_table = macinfo_table;
+       if (flag_fat_lto_objects)
+ 	macinfo_table = macinfo_table->copy ();
+ 
+       switch_to_section (debug_macinfo_section);
+       ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
+       output_macinfo (debug_skeleton_line_section_label, true);
+       dw2_asm_output_data (1, 0, "End compilation unit");
+ 
+       /* Emit a skeleton debug_line section.  */
+       switch_to_section (debug_skeleton_line_section);
+       ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_line_section_label);
+       output_line_info (true);
+ 
+       if (flag_fat_lto_objects)
+ 	{
+ 	  vec_free (macinfo_table);
+ 	  macinfo_table = saved_macinfo_table;
+ 	}
+     }
+ 
+ 
+   /* If we emitted any indirect strings, output the string table too.  */
+   if (debug_str_hash || skeleton_debug_str_hash)
+     output_indirect_strings ();
+ 
+   /* Switch back to the text section.  */
+   switch_to_section (text_section);
  }
  
  /* Reset all state within dwarf2out.c so that we can rerun the compiler
Index: early-lto-debug/gcc/debug.h
===================================================================
*** early-lto-debug.orig/gcc/debug.h	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/debug.h	2017-05-16 13:10:49.774239353 +0200
*************** struct gcc_debug_hooks
*** 147,152 ****
--- 147,160 ----
    void (* imported_module_or_decl) (tree decl, tree name,
  				    tree context, bool child);
  
+   /* Return true if a DIE for the tree is available and return a symbol
+      and offset that can be used to refer to it externally.  */
+   bool (* die_ref_for_decl) (tree, const char **, unsigned HOST_WIDE_INT *);
+ 
+   /* Early debug information for the tree is available at symbol plus
+      offset externally.  */
+   void (* register_external_die) (tree, const char *, unsigned HOST_WIDE_INT);
+ 
    /* DECL is an inline function, whose body is present, but which is
       not being output at this point.  */
    void (* deferred_inline_function) (tree decl);
*************** extern void debug_nothing_tree_tree_tree
*** 210,215 ****
--- 218,227 ----
  extern bool debug_true_const_tree (const_tree);
  extern void debug_nothing_rtx_insn (rtx_insn *);
  extern void debug_nothing_rtx_code_label (rtx_code_label *);
+ extern bool debug_false_tree_charstarstar_uhwistar (tree, const char **,
+ 						    unsigned HOST_WIDE_INT *);
+ extern void debug_nothing_tree_charstar_uhwi (tree, const char *,
+ 					      unsigned HOST_WIDE_INT);
  
  /* Hooks for various debug formats.  */
  extern const struct gcc_debug_hooks do_nothing_debug_hooks;
Index: early-lto-debug/gcc/debug.c
===================================================================
*** early-lto-debug.orig/gcc/debug.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/debug.c	2017-05-16 13:10:49.774239353 +0200
*************** const struct gcc_debug_hooks do_nothing_
*** 48,53 ****
--- 48,55 ----
    debug_nothing_tree,	         	 /* late_global_decl */
    debug_nothing_tree_int,		 /* type_decl */
    debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
+   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
+   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
    debug_nothing_tree,		         /* deferred_inline_function */
    debug_nothing_tree,		         /* outlining_inline_function */
    debug_nothing_rtx_code_label,	         /* label */
*************** debug_nothing_tree_int (tree decl ATTRIB
*** 146,148 ****
--- 148,163 ----
  			int local ATTRIBUTE_UNUSED)
  {
  }
+ 
+ bool
+ debug_false_tree_charstarstar_uhwistar (tree, const char **,
+ 					unsigned HOST_WIDE_INT *)
+ {
+   return false;
+ }
+ 
+ void
+ debug_nothing_tree_charstar_uhwi (tree, const char *,
+ 				  unsigned HOST_WIDE_INT)
+ {
+ }
Index: early-lto-debug/gcc/dbxout.c
===================================================================
*** early-lto-debug.orig/gcc/dbxout.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/dbxout.c	2017-05-16 13:10:49.778239419 +0200
*************** const struct gcc_debug_hooks dbx_debug_h
*** 372,377 ****
--- 372,379 ----
    dbxout_late_global_decl,		 /* late_global_decl */
    dbxout_type_decl,			 /* type_decl */
    debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
+   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
+   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
    debug_nothing_tree,		         /* deferred_inline_function */
    debug_nothing_tree,		         /* outlining_inline_function */
    debug_nothing_rtx_code_label,	         /* label */
*************** const struct gcc_debug_hooks xcoff_debug
*** 412,417 ****
--- 414,421 ----
    dbxout_late_global_decl,		 /* late_global_decl */
    dbxout_type_decl,			 /* type_decl */
    debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
+   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
+   debug_nothing_tree_charstar_uhwi,      /* register_external_die */
    debug_nothing_tree,		         /* deferred_inline_function */
    debug_nothing_tree,		         /* outlining_inline_function */
    debug_nothing_rtx_code_label,	         /* label */
Index: early-lto-debug/gcc/sdbout.c
===================================================================
*** early-lto-debug.orig/gcc/sdbout.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/sdbout.c	2017-05-16 13:10:49.778239419 +0200
*************** const struct gcc_debug_hooks sdb_debug_h
*** 302,307 ****
--- 302,309 ----
    sdbout_late_global_decl,		 /* late_global_decl */
    sdbout_symbol,			 /* type_decl */
    debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
+   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
+   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
    debug_nothing_tree,		         /* deferred_inline_function */
    debug_nothing_tree,		         /* outlining_inline_function */
    sdbout_label,			         /* label */
Index: early-lto-debug/gcc/lto/lto.c
===================================================================
*** early-lto-debug.orig/gcc/lto/lto.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/lto/lto.c	2017-05-16 13:10:49.778239419 +0200
*************** unify_scc (struct data_in *data_in, unsi
*** 1632,1637 ****
--- 1632,1640 ----
  	      free_node (scc->entries[i]);
  	    }
  
+ 	  /* Drop DIE references.  */
+ 	  dref_queue.truncate (0);
+ 
  	  break;
  	}
  
*************** lto_read_decls (struct lto_file_decl_dat
*** 1707,1714 ****
  						     from);
  	  if (len == 1
  	      && (TREE_CODE (first) == IDENTIFIER_NODE
! 		  || TREE_CODE (first) == INTEGER_CST
! 		  || TREE_CODE (first) == TRANSLATION_UNIT_DECL))
  	    continue;
  
  	  /* Try to unify the SCC with already existing ones.  */
--- 1710,1716 ----
  						     from);
  	  if (len == 1
  	      && (TREE_CODE (first) == IDENTIFIER_NODE
! 		  || TREE_CODE (first) == INTEGER_CST))
  	    continue;
  
  	  /* Try to unify the SCC with already existing ones.  */
*************** lto_read_decls (struct lto_file_decl_dat
*** 1747,1762 ****
  	      if (TREE_CODE (t) == INTEGER_CST
  		  && !TREE_OVERFLOW (t))
  		cache_integer_cst (t);
- 	      /* Register TYPE_DECLs with the debuginfo machinery.  */
- 	      if (!flag_wpa
- 		  && TREE_CODE (t) == TYPE_DECL)
- 		{
- 		  /* Dwarf2out needs location information.
- 		     TODO: Moving this out of the streamer loop may noticealy
- 		     improve ltrans linemap memory use.  */
- 		  data_in->location_cache.apply_location_cache ();
- 		  debug_hooks->type_decl (t, !DECL_FILE_SCOPE_P (t));
- 		}
  	      if (!flag_ltrans)
  		{
  		  /* Register variables and functions with the
--- 1749,1754 ----
*************** lto_read_decls (struct lto_file_decl_dat
*** 1772,1777 ****
--- 1764,1777 ----
  		    vec_safe_push (tree_with_vars, t);
  		}
  	    }
+ 
+ 	  /* Register DECLs with the debuginfo machinery.  */
+ 	  while (!dref_queue.is_empty ())
+ 	    {
+ 	      dref_entry e = dref_queue.pop ();
+ 	      debug_hooks->register_external_die (e.decl, e.sym, e.off);
+ 	    }
+ 
  	  if (seen_type)
  	    num_type_scc_trees += len;
  	}
*************** lto_section_with_id (const char *name, u
*** 1951,1957 ****
    if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
      return 0;
    s = strrchr (name, '.');
!   return s && sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
  }
  
  /* Create file_data of each sub file id */
--- 1951,1962 ----
    if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
      return 0;
    s = strrchr (name, '.');
!   if (!s)
!     return 0;
!   /* If the section is not suffixed with an ID return.  */
!   if ((size_t)(s - name) == strlen (section_name_prefix))
!     return 0;
!   return sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
  }
  
  /* Create file_data of each sub file id */
Index: early-lto-debug/gcc/lto-streamer-in.c
===================================================================
*** early-lto-debug.orig/gcc/lto-streamer-in.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/lto-streamer-in.c	2017-05-16 13:10:49.858240736 +0200
*************** along with GCC; see the file COPYING3.
*** 41,46 ****
--- 41,47 ----
  #include "except.h"
  #include "cgraph.h"
  #include "cfgloop.h"
+ #include "debug.h"
  
  
  struct freeing_string_slot_hasher : string_slot_hasher
*************** input_function (tree fn_decl, struct dat
*** 1038,1043 ****
--- 1039,1054 ----
    DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in);
    DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in);
  
+   /* Read debug args if available.  */
+   unsigned n_debugargs = streamer_read_uhwi (ib);
+   if (n_debugargs)
+     {
+       vec<tree, va_gc> **debugargs = decl_debug_args_insert (fn_decl);
+       vec_safe_grow (*debugargs, n_debugargs);
+       for (unsigned i = 0; i < n_debugargs; ++i)
+ 	(**debugargs)[i] = stream_read_tree (ib, data_in);
+     }
+ 
    /* Read the tree of lexical scopes for the function.  */
    DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
    unsigned block_leaf_count = streamer_read_uhwi (ib);
*************** lto_input_variable_constructor (struct l
*** 1318,1323 ****
--- 1329,1338 ----
  }
  
  
+ /* Queue of acummulated decl -> DIE mappings.  Similar to locations those
+    are only applied to prevailing tree nodes during tree merging.  */
+ vec<dref_entry> dref_queue;
+ 
  /* Read the physical representation of a tree node EXPR from
     input block IB using the per-file context in DATA_IN.  */
  
*************** lto_read_tree_1 (struct lto_input_block
*** 1337,1342 ****
--- 1352,1374 ----
        && TREE_CODE (expr) != FUNCTION_DECL
        && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
      DECL_INITIAL (expr) = stream_read_tree (ib, data_in);
+ 
+   /* Stream references to early generated DIEs.  Keep in sync with the
+      trees handled in dwarf2out_register_external_die.  */
+   if ((DECL_P (expr)
+        && TREE_CODE (expr) != FIELD_DECL
+        && TREE_CODE (expr) != DEBUG_EXPR_DECL
+        && TREE_CODE (expr) != TYPE_DECL)
+       || TREE_CODE (expr) == BLOCK)
+     {
+       const char *str = streamer_read_string (data_in, ib);
+       if (str)
+ 	{
+ 	  unsigned HOST_WIDE_INT off = streamer_read_uhwi (ib);
+ 	  dref_entry e = { expr, str, off };
+ 	  dref_queue.safe_push (e);
+ 	}
+     }
  }
  
  /* Read the physical representation of a tree node with tag TAG from
*************** lto_input_tree (struct lto_input_block *
*** 1482,1487 ****
--- 1514,1526 ----
      {
        unsigned len, entry_len;
        lto_input_scc (ib, data_in, &len, &entry_len);
+ 
+       /* Register DECLs with the debuginfo machinery.  */
+       while (!dref_queue.is_empty ())
+ 	{
+ 	  dref_entry e = dref_queue.pop ();
+ 	  debug_hooks->register_external_die (e.decl, e.sym, e.off);
+ 	}
      }
    return lto_input_tree_1 (ib, data_in, tag, 0);
  }
Index: early-lto-debug/gcc/lto-streamer-out.c
===================================================================
*** early-lto-debug.orig/gcc/lto-streamer-out.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/lto-streamer-out.c	2017-05-16 13:10:49.858240736 +0200
*************** along with GCC; see the file COPYING3.
*** 40,45 ****
--- 40,46 ----
  #include "cfgloop.h"
  #include "builtins.h"
  #include "gomp-constants.h"
+ #include "debug.h"
  
  
  static void lto_write_tree (struct output_block*, tree, bool);
*************** lto_write_tree_1 (struct output_block *o
*** 406,411 ****
--- 407,432 ----
  			 (ob->decl_state->symtab_node_encoder, expr);
        stream_write_tree (ob, initial, ref_p);
      }
+ 
+   /* Stream references to early generated DIEs.  Keep in sync with the
+      trees handled in dwarf2out_die_ref_for_decl.  */
+   if ((DECL_P (expr)
+        && TREE_CODE (expr) != FIELD_DECL
+        && TREE_CODE (expr) != DEBUG_EXPR_DECL
+        && TREE_CODE (expr) != TYPE_DECL)
+       || TREE_CODE (expr) == BLOCK)
+     {
+       const char *sym;
+       unsigned HOST_WIDE_INT off;
+       if (debug_info_level > DINFO_LEVEL_NONE
+ 	  && debug_hooks->die_ref_for_decl (expr, &sym, &off))
+ 	{
+ 	  streamer_write_string (ob, ob->main_stream, sym, true);
+ 	  streamer_write_uhwi (ob, off);
+ 	}
+       else
+ 	streamer_write_string (ob, ob->main_stream, NULL, true);
+     }
  }
  
  /* Write a physical representation of tree node EXPR to output block
*************** DFS::DFS_write_tree_body (struct output_
*** 745,751 ****
  	;
        else
  	DFS_follow_tree_edge (DECL_NAME (expr));
!       DFS_follow_tree_edge (DECL_CONTEXT (expr));
      }
  
    if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
--- 766,776 ----
  	;
        else
  	DFS_follow_tree_edge (DECL_NAME (expr));
!       if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
! 	  && ! DECL_CONTEXT (expr))
! 	DFS_follow_tree_edge ((*all_translation_units)[0]);
!       else
! 	DFS_follow_tree_edge (DECL_CONTEXT (expr));
      }
  
    if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
*************** DFS::DFS_write_tree_body (struct output_
*** 765,770 ****
--- 790,796 ----
  	 declarations which should be eliminated by decl merging. Be sure none
  	 leaks to this point.  */
        gcc_assert (DECL_ABSTRACT_ORIGIN (expr) != error_mark_node);
+       DFS_follow_tree_edge (DECL_ABSTRACT_ORIGIN (expr));
  
        if ((VAR_P (expr)
  	   || TREE_CODE (expr) == PARM_DECL)
*************** output_function (struct cgraph_node *nod
*** 2061,2066 ****
--- 2087,2103 ----
    stream_write_tree (ob, DECL_RESULT (function), true);
    streamer_write_chain (ob, DECL_ARGUMENTS (function), true);
  
+   /* Output debug args if available. */
+   vec<tree, va_gc> **debugargs = decl_debug_args_lookup (function);
+   if (! debugargs)
+     streamer_write_uhwi (ob, 0);
+   else
+     {
+       streamer_write_uhwi (ob, (*debugargs)->length ());
+       for (unsigned i = 0; i < (*debugargs)->length (); ++i)
+ 	stream_write_tree (ob, (**debugargs)[i], true);
+     }
+ 
    /* Output DECL_INITIAL for the function, which contains the tree of
       lexical scopes.  */
    stream_write_tree (ob, DECL_INITIAL (function), true);
Index: early-lto-debug/gcc/lto-streamer.h
===================================================================
*** early-lto-debug.orig/gcc/lto-streamer.h	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/lto-streamer.h	2017-05-16 13:10:49.858240736 +0200
*************** DEFINE_DECL_STREAM_FUNCS (TYPE_DECL, typ
*** 1212,1215 ****
--- 1212,1225 ----
  DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl)
  DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl)
  
+ /* Entry for the delayed registering of decl -> DIE references.  */
+ struct dref_entry {
+     tree decl;
+     const char *sym;
+     unsigned HOST_WIDE_INT off;
+ };
+ 
+ extern vec<dref_entry> dref_queue;
+ 
+ 
  #endif /* GCC_LTO_STREAMER_H  */
Index: early-lto-debug/gcc/lto-wrapper.c
===================================================================
*** early-lto-debug.orig/gcc/lto-wrapper.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/lto-wrapper.c	2017-05-16 13:10:49.858240736 +0200
*************** static char **output_names;
*** 70,75 ****
--- 70,76 ----
  static char **offload_names;
  static char *offload_objects_file_name;
  static char *makefile;
+ static char *debug_obj;
  
  const char tool_name[] = "lto-wrapper";
  
*************** tool_cleanup (bool)
*** 88,93 ****
--- 89,96 ----
      maybe_unlink (offload_objects_file_name);
    if (makefile)
      maybe_unlink (makefile);
+   if (debug_obj)
+     maybe_unlink (debug_obj);
    for (i = 0; i < nr; ++i)
      {
        maybe_unlink (input_names[i]);
*************** find_and_merge_options (int fd, off_t fi
*** 938,943 ****
--- 941,1007 ----
    return true;
  }
  
+ /* Copy early debug info sections from INFILE to a new file whose name
+    is returned.  Return NULL on error.  */
+ 
+ const char *
+ debug_objcopy (const char *infile)
+ {
+   const char *outfile;
+   const char *errmsg;
+   int err;
+ 
+   const char *p;
+   off_t inoff = 0;
+   long loffset;
+   int consumed;
+   if ((p = strrchr (infile, '@'))
+       && p != infile
+       && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
+       && strlen (p) == (unsigned int) consumed)
+     {
+       char *fname = xstrdup (infile);
+       fname[p - infile] = '\0';
+       infile = fname;
+       inoff = (off_t) loffset;
+     }
+   int infd = open (infile, O_RDONLY);
+   if (infd == -1)
+     return NULL;
+   simple_object_read *inobj = simple_object_start_read (infd, inoff,
+ 							"__GNU_LTO",
+ 							&errmsg, &err);
+   if (!inobj)
+     return NULL;
+ 
+   off_t off, len;
+   if (simple_object_find_section (inobj, ".gnu.debuglto_.debug_info",
+ 				  &off, &len, &errmsg, &err) != 1)
+     {
+       if (errmsg)
+ 	fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
+ 
+       simple_object_release_read (inobj);
+       close (infd);
+       return NULL;
+     }
+ 
+   outfile = make_temp_file ("debugobjtem");
+   errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err);
+   if (errmsg)
+     {
+       unlink_if_ordinary (outfile);
+       fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
+     }
+ 
+   simple_object_release_read (inobj);
+   close (infd);
+ 
+   return outfile;
+ }
+ 
+ 
+ 
  /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
  
  static void
*************** run_gcc (unsigned argc, char *argv[])
*** 962,969 ****
    int new_head_argc;
    bool have_lto = false;
    bool have_offload = false;
!   unsigned lto_argc = 0;
!   char **lto_argv;
  
    /* Get the driver and options.  */
    collect_gcc = getenv ("COLLECT_GCC");
--- 1026,1035 ----
    int new_head_argc;
    bool have_lto = false;
    bool have_offload = false;
!   unsigned lto_argc = 0, ltoobj_argc = 0;
!   char **lto_argv, **ltoobj_argv;
!   bool skip_debug = false;
!   unsigned n_debugobj;
  
    /* Get the driver and options.  */
    collect_gcc = getenv ("COLLECT_GCC");
*************** run_gcc (unsigned argc, char *argv[])
*** 982,987 ****
--- 1048,1054 ----
    /* Allocate array for input object files with LTO IL,
       and for possible preceding arguments.  */
    lto_argv = XNEWVEC (char *, argc);
+   ltoobj_argv = XNEWVEC (char *, argc);
  
    /* Look at saved options in the IL files.  */
    for (i = 1; i < argc; ++i)
*************** run_gcc (unsigned argc, char *argv[])
*** 1024,1030 ****
  				  collect_gcc))
  	{
  	  have_lto = true;
! 	  lto_argv[lto_argc++] = argv[i];
  	}
        close (fd);
      }
--- 1091,1097 ----
  				  collect_gcc))
  	{
  	  have_lto = true;
! 	  ltoobj_argv[ltoobj_argc++] = argv[i];
  	}
        close (fd);
      }
*************** run_gcc (unsigned argc, char *argv[])
*** 1085,1090 ****
--- 1152,1168 ----
  	}
      }
  
+   /* Output lto-wrapper invocation command.  */
+   if (verbose)
+     {
+       for (i = 0; i < argc; ++i)
+ 	{
+ 	  fputs (argv[i], stderr);
+ 	  fputc (' ', stderr);
+ 	}
+       fputc ('\n', stderr);
+     }
+ 
    if (no_partition)
      {
        lto_mode = LTO_MODE_LTO;
*************** cont1:
*** 1274,1291 ****
          obstack_ptr_grow (&argv_obstack, "-fwpa");
      }
  
!   /* Append the input objects and possible preceding arguments.  */
    for (i = 0; i < lto_argc; ++i)
      obstack_ptr_grow (&argv_obstack, lto_argv[i]);
    obstack_ptr_grow (&argv_obstack, NULL);
  
    new_argv = XOBFINISH (&argv_obstack, const char **);
    argv_ptr = &new_argv[new_head_argc];
    fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
  
    if (lto_mode == LTO_MODE_LTO)
      {
        printf ("%s\n", flto_out);
        free (flto_out);
        flto_out = NULL;
      }
--- 1352,1456 ----
          obstack_ptr_grow (&argv_obstack, "-fwpa");
      }
  
!   /* Append input arguments.  */
    for (i = 0; i < lto_argc; ++i)
      obstack_ptr_grow (&argv_obstack, lto_argv[i]);
+   /* Append the input objects.  */
+   for (i = 0; i < ltoobj_argc; ++i)
+     obstack_ptr_grow (&argv_obstack, ltoobj_argv[i]);
    obstack_ptr_grow (&argv_obstack, NULL);
  
    new_argv = XOBFINISH (&argv_obstack, const char **);
    argv_ptr = &new_argv[new_head_argc];
    fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
  
+   /* Handle early generated debug information.  At compile-time
+      we output early DWARF debug info into .gnu.debuglto_ prefixed
+      sections.  LTRANS object DWARF debug info refers to that.
+      So we need to transfer the .gnu.debuglto_ sections to the final
+      link.  Ideally the linker plugin interface would allow us to
+      not claim those sections and instruct the linker to keep
+      them, renaming them in the process.  For now we extract and
+      rename those sections via a simple-object interface to produce
+      regular objects containing only the early debug info.  We
+      then partially link those to a single early debug info object
+      and pass that as additional output back to the linker plugin.  */
+ 
+   /* Prepare the partial link to gather the compile-time generated
+      debug-info into a single input for the final link.  */
+   debug_obj = make_temp_file ("debugobj");
+   obstack_ptr_grow (&argv_obstack, collect_gcc);
+   for (i = 1; i < decoded_options_count; ++i)
+     {
+       /* Retain linker choice and -B.  */
+       if (decoded_options[i].opt_index == OPT_B
+ 	  || decoded_options[i].opt_index == OPT_fuse_ld_bfd
+ 	  || decoded_options[i].opt_index == OPT_fuse_ld_gold)
+ 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
+       /* Retain all target options, this preserves -m32 for example.  */
+       if (cl_options[decoded_options[i].opt_index].flags & CL_TARGET)
+ 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
+       /* Recognize -g0.  */
+       if (decoded_options[i].opt_index == OPT_g
+ 	  && strcmp (decoded_options[i].arg, "0") == 0)
+ 	skip_debug = true;
+     }
+   obstack_ptr_grow (&argv_obstack, "-r");
+   obstack_ptr_grow (&argv_obstack, "-nostdlib");
+   obstack_ptr_grow (&argv_obstack, "-o");
+   obstack_ptr_grow (&argv_obstack, debug_obj);
+ 
+   /* Copy the early generated debug info from the objects to temporary
+      files and append those to the partial link commandline.  */
+   n_debugobj = 0;
+   if (! skip_debug)
+     for (i = 0; i < ltoobj_argc; ++i)
+       {
+ 	const char *tem;
+ 	if ((tem = debug_objcopy (ltoobj_argv[i])))
+ 	  {
+ 	    obstack_ptr_grow (&argv_obstack, tem);
+ 	    n_debugobj++;
+ 	  }
+       }
+ 
+   /* Link them all into a single object.  Ideally this would reduce
+      disk space usage mainly due to .debug_str merging but unfortunately
+      GNU ld doesn't perform this with -r.  */
+   if (n_debugobj)
+     {
+       obstack_ptr_grow (&argv_obstack, NULL);
+       const char **debug_link_argv = XOBFINISH (&argv_obstack, const char **);
+       fork_execute (debug_link_argv[0],
+ 		    CONST_CAST (char **, debug_link_argv), false);
+ 
+       /* And dispose the temporaries.  */
+       for (i = 0; debug_link_argv[i]; ++i)
+ 	;
+       for (--i; i > 0; --i)
+ 	{
+ 	  if (strcmp (debug_link_argv[i], debug_obj) == 0)
+ 	    break;
+ 	  maybe_unlink (debug_link_argv[i]);
+ 	}
+     }
+   else
+     {
+       unlink_if_ordinary (debug_obj);
+       free (debug_obj);
+       debug_obj = NULL;
+       skip_debug = true;
+     }
+ 
    if (lto_mode == LTO_MODE_LTO)
      {
        printf ("%s\n", flto_out);
+       if (!skip_debug)
+ 	{
+ 	  printf ("%s\n", debug_obj);
+ 	  free (debug_obj);
+ 	  debug_obj = NULL;
+ 	}
        free (flto_out);
        flto_out = NULL;
      }
*************** cont:
*** 1434,1439 ****
--- 1599,1610 ----
  	  for (i = 0; i < nr; ++i)
  	    maybe_unlink (input_names[i]);
  	}
+       if (!skip_debug)
+ 	{
+ 	  printf ("%s\n", debug_obj);
+ 	  free (debug_obj);
+ 	  debug_obj = NULL;
+ 	}
        for (i = 0; i < nr; ++i)
  	{
  	  fputs (output_names[i], stdout);
Index: early-lto-debug/gcc/tree-streamer-in.c
===================================================================
*** early-lto-debug.orig/gcc/tree-streamer-in.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/tree-streamer-in.c	2017-05-16 13:10:49.862240801 +0200
*************** lto_input_ts_decl_common_tree_pointers (
*** 688,697 ****
    DECL_SIZE (expr) = stream_read_tree (ib, data_in);
    DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
    DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
! 
!   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
!      for early inlining so drop it on the floor instead of ICEing in
!      dwarf2out.c.  */
  
    if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
        && DECL_HAS_VALUE_EXPR_P (expr))
--- 688,694 ----
    DECL_SIZE (expr) = stream_read_tree (ib, data_in);
    DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
    DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
!   DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
  
    if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
        && DECL_HAS_VALUE_EXPR_P (expr))
Index: early-lto-debug/gcc/tree-streamer-out.c
===================================================================
*** early-lto-debug.orig/gcc/tree-streamer-out.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/tree-streamer-out.c	2017-05-16 13:10:49.862240801 +0200
*************** write_ts_decl_minimal_tree_pointers (str
*** 566,572 ****
      stream_write_tree (ob, NULL_TREE, ref_p);
    else
      stream_write_tree (ob, DECL_NAME (expr), ref_p);
!   stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
  }
  
  
--- 566,576 ----
      stream_write_tree (ob, NULL_TREE, ref_p);
    else
      stream_write_tree (ob, DECL_NAME (expr), ref_p);
!   if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
!       && ! DECL_CONTEXT (expr))
!     stream_write_tree (ob, (*all_translation_units)[0], ref_p);
!   else
!     stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
  }
  
  
*************** write_ts_decl_common_tree_pointers (stru
*** 585,594 ****
       special handling in LTO, it must be handled by streamer hooks.  */
  
    stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
! 
!   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
!      for early inlining so drop it on the floor instead of ICEing in
!      dwarf2out.c.  */
  
    if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
        && DECL_HAS_VALUE_EXPR_P (expr))
--- 589,595 ----
       special handling in LTO, it must be handled by streamer hooks.  */
  
    stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
!   stream_write_tree (ob, DECL_ABSTRACT_ORIGIN (expr), ref_p);
  
    if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
        && DECL_HAS_VALUE_EXPR_P (expr))
Index: early-lto-debug/gcc/config/darwin.c
===================================================================
*** early-lto-debug.orig/gcc/config/darwin.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/config/darwin.c	2017-05-16 13:10:49.862240801 +0200
*************** darwin_asm_lto_end (void)
*** 1959,1965 ****
  }
  
  static void
! darwin_asm_dwarf_section (const char *name, unsigned int flags, tree decl);
  
  /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
  
--- 1959,1966 ----
  }
  
  static void
! darwin_asm_dwarf_section (const char *name, unsigned int flags,
! 			  tree decl, bool is_for_lto);
  
  /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
  
*************** darwin_asm_named_section (const char *na
*** 2001,2007 ****
        vec_safe_push (lto_section_names, e);
     }
    else if (strncmp (name, "__DWARF,", 8) == 0)
!     darwin_asm_dwarf_section (name, flags, decl);
    else
      fprintf (asm_out_file, "\t.section %s\n", name);
  }
--- 2002,2010 ----
        vec_safe_push (lto_section_names, e);
     }
    else if (strncmp (name, "__DWARF,", 8) == 0)
!     darwin_asm_dwarf_section (name, flags, decl, false);
!   else if (strncmp (name, "__GNU_DWARF_LTO,", 16) == 0)
!     darwin_asm_dwarf_section (name, flags, decl, true);
    else
      fprintf (asm_out_file, "\t.section %s\n", name);
  }
*************** static GTY (()) vec<dwarf_sect_used_entr
*** 2783,2801 ****
  
  static void
  darwin_asm_dwarf_section (const char *name, unsigned int flags,
! 			  tree ARG_UNUSED (decl))
  {
    unsigned i;
!   int namelen;
!   const char * sname;
    dwarf_sect_used_entry *ref;
    bool found = false;
!   gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
! 		    == (SECTION_DEBUG | SECTION_NAMED));
!   /* We know that the name starts with __DWARF,  */
!   sname = name + 8;
!   namelen = strchr (sname, ',') - sname;
!   gcc_assert (namelen);
    if (dwarf_sect_names_table == NULL)
      vec_alloc (dwarf_sect_names_table, 16);
    else
--- 2786,2822 ----
  
  static void
  darwin_asm_dwarf_section (const char *name, unsigned int flags,
! 			  tree ARG_UNUSED (decl), bool is_for_lto)
  {
    unsigned i;
!   int namelen, extra = 0;
!   const char *sect, *lto_add = "";
!   char sname[64];
    dwarf_sect_used_entry *ref;
    bool found = false;
! 
!   gcc_checking_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
! 			== (SECTION_DEBUG | SECTION_NAMED));
! 
!   /* We know that the name starts with __DWARF, or __GNU_DAWRF_LTO  */
!   sect = strchr (name, ',') + 1;
!   namelen = strchr (sect, ',') - sect;
!   gcc_checking_assert (namelen);
! 
!   /* The section switch is output as written...  */
!   fprintf (asm_out_file, "\t.section %s\n", name);
! 
!   /* ... but the string we keep to make section start labels needs
!      adjustment for lto cases.  */
!   if (is_for_lto)
!     {
!       lto_add = "_lto";
!       extra = 4;
!     }
! 
!   snprintf (sname, 64, "%.*s%.*s", namelen, sect, extra, lto_add);
!   namelen += extra;
! 
    if (dwarf_sect_names_table == NULL)
      vec_alloc (dwarf_sect_names_table, 16);
    else
*************** darwin_asm_dwarf_section (const char *na
*** 2813,2819 ****
  	  }
        }
  
-   fprintf (asm_out_file, "\t.section %s\n", name);
    if (!found)
      {
        dwarf_sect_used_entry e;
--- 2834,2839 ----
*************** darwin_asm_output_dwarf_offset (FILE *fi
*** 2866,2879 ****
  				HOST_WIDE_INT offset, section *base)
  {
    char sname[64];
!   int namelen;
  
!   gcc_assert (base->common.flags & SECTION_NAMED);
!   gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
!   gcc_assert (strchr (base->named.name + 8, ','));
! 
!   namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
!   sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
    darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
  }
  
--- 2886,2909 ----
  				HOST_WIDE_INT offset, section *base)
  {
    char sname[64];
!   int namelen, extra = 0;
!   bool is_for_lto;
!   const char *lto_add = "";
! 
!   gcc_checking_assert (base->common.flags & SECTION_NAMED);
!   is_for_lto = strncmp (base->named.name, "__GNU_DWARF_LTO,", 16) == 0;
!   gcc_checking_assert (is_for_lto
! 		       || strncmp (base->named.name, "__DWARF,", 8) == 0);
!   const char *name = strchr (base->named.name, ',') + 1;
!   gcc_checking_assert (name);
  
!   namelen = strchr (name, ',') - (name);
!   if (is_for_lto)
!     {
!       lto_add = "_lto";
!       extra = 4;
!     }
!   snprintf (sname, 64, "*Lsection%.*s%.*s", namelen, name, extra, lto_add);
    darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
  }
  
Index: early-lto-debug/gcc/config/darwin.h
===================================================================
*** early-lto-debug.orig/gcc/config/darwin.h	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/config/darwin.h	2017-05-16 13:10:49.866240867 +0200
*************** extern GTY(()) int darwin_ms_struct;
*** 445,451 ****
  #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
  #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
  #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
! #define DEBUG_MACRO_SECTION    "__DWARF,__debug_macro,regular,debug"
  
  #define TARGET_WANT_DEBUG_PUB_SECTIONS true
  
--- 445,458 ----
  #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
  #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
  #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
! #define DEBUG_MACRO_SECTION     "__DWARF,__debug_macro,regular,debug"
! 
! #define DEBUG_LTO_INFO_SECTION	  "__GNU_DWARF_LTO,__debug_info,regular,debug"
! #define DEBUG_LTO_ABBREV_SECTION  "__GNU_DWARF_LTO,__debug_abbrev,regular,debug"
! #define DEBUG_LTO_MACINFO_SECTION "__GNU_DWARF_LTO,__debug_macinfo,regular,debug"
! #define DEBUG_LTO_LINE_SECTION	  "__GNU_DWARF_LTO,__debug_line,regular,debug"
! #define DEBUG_LTO_STR_SECTION	  "__GNU_DWARF_LTO,__debug_str,regular,debug"
! #define DEBUG_LTO_MACRO_SECTION   "__GNU_DWARF_LTO,__debug_macro,regular,debug"
  
  #define TARGET_WANT_DEBUG_PUB_SECTIONS true
  
Index: early-lto-debug/gcc/vmsdbgout.c
===================================================================
*** early-lto-debug.orig/gcc/vmsdbgout.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/vmsdbgout.c	2017-05-16 13:10:49.866240867 +0200
*************** const struct gcc_debug_hooks vmsdbg_debu
*** 198,203 ****
--- 198,205 ----
     vmsdbgout_late_global_decl,
     vmsdbgout_type_decl,		  /* type_decl */
     debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
+    debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
+    debug_nothing_tree_charstar_uhwi, /* register_external_die */
     debug_nothing_tree,		  /* deferred_inline_function */
     vmsdbgout_abstract_function,
     debug_nothing_rtx_code_label,  /* label */
Index: early-lto-debug/gcc/tree.c
===================================================================
*** early-lto-debug.orig/gcc/tree.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/tree.c	2017-05-16 13:10:49.870240933 +0200
*************** free_lang_data (void)
*** 5974,5979 ****
--- 5974,5983 ----
        || (!flag_generate_lto && !flag_generate_offload))
      return 0;
  
+   /* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one.  */
+   if (vec_safe_is_empty (all_translation_units))
+     build_translation_unit_decl (NULL_TREE);
+ 
    /* Allocate and assign alias sets to the standard integer types
       while the slots are still in the way the frontends generated them.  */
    for (i = 0; i < itk_none; ++i)
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-05-16 13:10:49.870240933 +0200
*************** int main() {
*** 23,28 ****
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
  /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
  /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
--- 23,28 ----
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
  /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
  /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-05-16 13:10:49.870240933 +0200
*************** int main(int argc, char **argv) {
*** 24,31 ****
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- 24,31 ----
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-05-16 13:10:49.870240933 +0200
*************** main ()
*** 39,43 ****
  /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
--- 39,43 ----
  /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-05-16 13:10:49.870240933 +0200
*************** main ()
*** 39,43 ****
  /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
--- 39,43 ----
  /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-05-16 13:10:49.870240933 +0200
*************** int main()
*** 18,22 ****
  
  /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- 18,22 ----
  
  /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-05-16 13:10:49.874240999 +0200
*************** int main() {
*** 18,23 ****
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
--- 18,23 ----
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-05-16 13:10:49.874240999 +0200
*************** int main(int argc, char **argv) {
*** 14,21 ****
  
  /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- 14,21 ----
  
  /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-05-16 13:10:49.874240999 +0200
*************** int main() {
*** 12,22 ****
  /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- 12,22 ----
  /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C
===================================================================
*** early-lto-debug.orig/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-05-16 13:10:49.874240999 +0200
*************** int main() {
*** 38,44 ****
  // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
  // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
  // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
--- 38,44 ----
  // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
  // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
  // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
Index: early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp
===================================================================
*** early-lto-debug.orig/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-05-16 13:10:47.554202813 +0200
--- early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-05-16 13:10:49.874240999 +0200
***************
*** 15,20 ****
--- 15,21 ----
  # <http://www.gnu.org/licenses/>.
  
  load_lib gdb-test.exp
+ load_lib target-supports.exp
  
  dg-init
  v3-build_support
*************** global PCH_CXXFLAGS
*** 46,51 ****
--- 47,60 ----
  gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
    "" "$DEFAULT_CXXFLAGS $PCH_CXXFLAGS"
  
+ if { [check_effective_target_lto] } {
+   append cxxflags " -flto"
+   # work around sourceware.org 20882
+   regsub {^(.*)-Wl,--gc-sections(.*)$} $cxxldflags {\1\2} cxxldflags
+   gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
+     "" "$DEFAULT_CXXFLAGS -flto $PCH_CXXFLAGS"
+ }
+ 
  if [info exists guality_gdb_name] {
      unsetenv GUALITY_GDB_NAME
  }
Index: early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90	2017-05-18 09:39:31.394914888 +0200
***************
*** 0 ****
--- 1,54 ----
+ ! { dg-do run }
+ ! { dg-require-effective-target lto }
+ ! { dg-options "-fno-automatic -flto -g" }
+ !
+ ! PR fortran/55733
+ !
+ ! Check that -fno-automatic makes the local variable SAVEd
+ ! Check that -flto -g works
+ !
+ 
+ ! Scalar allocatable
+ subroutine foo(i)
+   integer :: i
+   integer, allocatable :: j
+   if (i == 1) j = 42
+   if (.not. allocated (j)) call abort ()
+   if (j /= 42) call abort ()
+ end
+ 
+ ! Deferred-length string scalar
+ subroutine bar()
+   logical, save :: first = .true.
+   character(len=:), allocatable :: str
+   if (first) then
+     first = .false.
+     if (allocated (str)) call abort ()
+     str = "ABCDEF"
+   end if
+   if (.not. allocated (str)) call abort ()
+   if (len (str) /= 6) call abort ()
+   if (str(1:6) /= "ABCDEF") call abort ()
+ end subroutine bar
+ 
+ ! Deferred-length string array
+ subroutine bar_array()
+   logical, save :: first = .true.
+   character(len=:), allocatable :: str
+   if (first) then
+     first = .false.
+     if (allocated (str)) call abort ()
+     str = "ABCDEF"
+   end if
+   if (.not. allocated (str)) call abort ()
+   if (len (str) /= 6) call abort ()
+   if (str(1:6) /= "ABCDEF") call abort ()
+ end subroutine bar_array
+ 
+ call foo(1)
+ call foo(2)
+ call bar()
+ call bar_array()
+ call bar()
+ call bar_array()
+ end
Index: early-lto-debug/gcc/config/i386/i386.c
===================================================================
*** early-lto-debug.orig/gcc/config/i386/i386.c	2017-05-15 10:57:19.923567540 +0200
--- early-lto-debug/gcc/config/i386/i386.c	2017-05-19 11:27:19.565373271 +0200
*************** make_resolver_func (const tree default_d
*** 33840,33846 ****
    DECL_NAME (decl) = decl_name;
    TREE_USED (decl) = 1;
    DECL_ARTIFICIAL (decl) = 1;
!   DECL_IGNORED_P (decl) = 0;
    /* IFUNC resolvers have to be externally visible.  */
    TREE_PUBLIC (decl) = 1;
    DECL_UNINLINABLE (decl) = 1;
--- 33840,33846 ----
    DECL_NAME (decl) = decl_name;
    TREE_USED (decl) = 1;
    DECL_ARTIFICIAL (decl) = 1;
!   DECL_IGNORED_P (decl) = 1;
    /* IFUNC resolvers have to be externally visible.  */
    TREE_PUBLIC (decl) = 1;
    DECL_UNINLINABLE (decl) = 1;

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-05-19 10:44 [PATCH][2/2] early LTO debug, main part Richard Biener
@ 2017-06-07  8:21 ` Richard Biener
  2017-06-20 11:16   ` Richard Biener
  2017-08-02  4:30 ` Jason Merrill
  1 sibling, 1 reply; 22+ messages in thread
From: Richard Biener @ 2017-06-07  8:21 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason

On Fri, 19 May 2017, Richard Biener wrote:

> 
> This is a repost of the main part of the early LTO debug support.
> The only changes relative to the last post is in the dwarf2out.c
> pieces due to Jasons review and Jakubs introduction of
> DW_OP_GNU_variable_value.
> 
> I've also adjusted testcases for fallout (the asan backtraces do
> give files / line numbers because libbacktrace doesn't understand
> the DWARF) plus added a -flto run over the libstdc++ pretty printer
> testsuite -- after all the goal was to make those work with LTO,
> and they now nicely do.
> 
> [LTO-]bootstrapped and tested on x86_64-unknown-linux-gnu.
> 
> I've also tested with -flto -g and compared to before the patch and
> the outcome doesn't contain any surprises.
> 
> I've also ran the gdb testsuite with no differences (but I guess
> it doesn't exercise LTO).
> 
> I've also built SPEC 2k6 with -flto -g.
> 
> I've also debugged optimized LTO bootstrapped cc1 a bit - not that
> debugging (LTO) optimized cc1 is a pleasant experience, but at least
> gdb doesn't crash.
> 
> Ok for trunk?

Ping.

> Both darwin and mingw maintainers were not concerned about LTO with -g
> being broken for them.
> 
> This patch allows us to go forward with freeing more stuff after
> the frontend finished, in particular remove LTO streaming of a lot
> of type information that is referenced from trees (and, as a first
> step, enable free-lang-data for non-LTO compiles).
> 
> Thanks,
> Richard.
> 
> 2017-05-19  Richard Biener  <rguenther@suse.de>
> 
>         * debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and
>         register_external_die hooks.
>         (debug_false_tree_charstarstar_uhwistar): Declare.
>         (debug_nothing_tree_charstar_uhwi): Likewise.
>         * debug.c (do_nothing_debug_hooks): Adjust.
>         (debug_false_tree_charstarstar_uhwistar): New do nothing.
>         (debug_nothing_tree_charstar_uhwi): Likewise.
>         * dbxout.c (dbx_debug_hooks): Adjust.
>         (xcoff_debug_hooks): Likewise.
>         * sdbout.c (sdb_debug_hooks): Likewise.
>         * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
> 
>         * dwarf2out.c (macinfo_label_base): New global.
> 	(dwarf2out_register_external_die): New function for the
> 	register_external_die hook.
>         (dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl.
>         (dwarf2_debug_hooks): Use them.
>         (dwarf2_lineno_debug_hooks): Adjust.
>         (struct die_struct): Add with_offset flag.
>         (DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION,
>         DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION,
>         DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION,
>         DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION,
>         DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
>         DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros
>         defining section names for the early LTO debug variants.
> 	(reset_indirect_string): New helper.
>         (add_AT_external_die_ref): Helper for dwarf2out_register_external_die.
>         (print_dw_val): Add support for offsetted symbol references.
>         (compute_section_prefix_1): Split out worker to distinguish
>         the comdat from the LTO case.
>         (compute_section_prefix): Wrap old comdat case here.
>         (output_die): Skip DIE symbol output for the LTO added one.
>         Handle DIE symbol references with offset.
>         (output_comp_unit): Guard section name mangling properly.
>         For LTO debug sections emit a symbol at the section beginning
>         which we use to refer to its DIEs.
>         (add_abstract_origin_attribute): For DIEs registered via
>         dwarf2out_register_external_die directly refer to the early
>         DIE rather than indirectly through the shadow one we created.
>         (gen_array_type_die): When generating early LTO debug do
>         not emit DW_AT_string_length.
>         (gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs
>         late when in LTO.
>         (gen_subprogram_die): Adjust the check for whether we face
>         a concrete instance DIE for an inline we can reuse for the
>         late LTO case.  Likewise avoid another specification DIE
>         for early built declarations/definitions for the late LTO case.
>         (gen_variable_die): Add type references for late duplicated VLA dies
>         when in late LTO.
>         (gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function,
>         we have the abstract instance already.
>         (process_scope_var): Adjust decl DIE contexts in LTO which
>         first puts them in limbo.
>         (gen_decl_die): Do not generate type DIEs late apart from
>         types for VLAs or for decls we do not yet have a DIE.
>         (dwarf2out_early_global_decl): Make sure to create DIEs
>         for abstract instances of a decl first.
>         (dwarf2out_late_global_decl): Adjust comment.
>         (output_macinfo_op): With multiple macro sections use
> 	macinfo_label_base to distinguish labels.
>         (output_macinfo): Likewise.  Update macinfo_label_base.
> 	Pass in the line info label.
> 	(note_variable_value_in_expr): When generating LTO resolve
> 	all variable values here by generating DIEs as needed.
>         (init_sections_and_labels): Add early LTO debug flag parameter
>         and generate different sections and names if set.  Add generation
>         counter for the labels so we can have multiple of them.
>         (reset_dies): Helper to allow DIEs to be output multiple times.
>         (dwarf2out_finish): When outputting DIEs to the fat part of an
> 	LTO object first reset DIEs.
>         (dwarf2out_early_finish): Output early DIEs when generating LTO.
> 
> Cleanups we can do (and need) when removing the "old" LTO path and add
> the early LTO path.
> 
>         (set_decl_abstract_flags): Remove.
>         (set_block_abstract_flags): Likewise.
>         (dwarf2out_abstract_function): Treat the early generated DIEs
>         as the abstract copy and only add DW_AT_inline and
>         DW_AT_artificial here.
> 
> 	* tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL
> 	if we have none yet (Go fails to build one, PR78628).
>         * lto-streamer-in.c: Include debug.h.
>         (dref_queue): New global.
>         (lto_read_tree_1): Stream in DIE references.
>         (lto_input_tree): Register DIE references.
> 	(input_function): Stream DECL_DEBUG_ARGS.
>         * lto-streamer-out.c: Include debug.h.
>         (lto_write_tree_1): Output DIE references.
>         (DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN.
> 	Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls.
> 	(output_function): Stream DECL_DEBUG_ARGS.
>         * tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers):
>         Stream DECL_ABSTRACT_ORIGIN.
>         * tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise.
> 	(write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL
> 	DECL_CONTEXT for file-scope decls.
>         * lto-streamer.h (struct dref_entry): Declare.
>         (dref_queue): Likewise.
> 
>         * lto-wrapper.c (debug_obj): New global.
>         (tool_cleanup): Unlink it if required.
>         (debug_objcopy): New function.
>         (run_gcc): Handle early debug sections in the IL files by
>         extracting them to separate files, partially linkin them and
>         feeding the result back as result to the linker.
> 
>         * config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION,
>         DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION,
>         DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug
>         sections into a separate segment.
>         * config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO
>         segments.
>         (darwin_asm_dwarf_section): Likewise.
>         (darwin_asm_output_dwarf_offset): Likewise.
> 
> 	* config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P.
> 
>         lto/
>         * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
>         (lto_read_decls): Process TRANSLATION_UNIT_DECLs.  Remove
>         TYPE_DECL debug processing, register DIE references from
>         prevailing SCCs with the debug machinery.
>         (lto_section_with_id): Handle LTO debug sections.
> 
> 	libstdc++/
> 	* testsuite/libstdc++-prettyprinters/prettyprinters.exp: Run all
> 	tests with -flto as well if supported.
> 
> 	* c-c++-common/asan/global-overflow-1.c: Adjust diagnostic location
> 	regex to handle the LTO case.
> 	* c-c++-common/asan/heap-overflow-1.c: Likewise.
> 	* c-c++-common/asan/misalign-1.c: Likewise.
> 	* c-c++-common/asan/misalign-2.c: Likewise.
> 	* c-c++-common/asan/null-deref-1.c: Likewise.
> 	* c-c++-common/asan/stack-overflow-1.c: Likewise.
> 	* c-c++-common/asan/strncpy-overflow-1.c: Likewise.
> 	* c-c++-common/asan/use-after-free-1.c: Likewise.
> 	* g++.dg/asan/large-func-test-1.C: Likewise.
> 	* gfortran.dg/save_6.f90: Add -flto -g variant of save_5.f90.
> 
> Index: early-lto-debug/gcc/dwarf2out.c
> ===================================================================
> *** early-lto-debug.orig/gcc/dwarf2out.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/dwarf2out.c	2017-05-19 12:29:43.933873285 +0200
> *************** static GTY(()) section *debug_aranges_se
> *** 162,167 ****
> --- 162,168 ----
>   static GTY(()) section *debug_addr_section;
>   static GTY(()) section *debug_macinfo_section;
>   static const char *debug_macinfo_section_name;
> + static unsigned macinfo_label_base = 1;
>   static GTY(()) section *debug_line_section;
>   static GTY(()) section *debug_skeleton_line_section;
>   static GTY(()) section *debug_loc_section;
> *************** static void dwarf2out_begin_function (tr
> *** 2686,2691 ****
> --- 2687,2696 ----
>   static void dwarf2out_end_function (unsigned int);
>   static void dwarf2out_register_main_translation_unit (tree unit);
>   static void dwarf2out_set_name (tree, tree);
> + static void dwarf2out_register_external_die (tree decl, const char *sym,
> + 					     unsigned HOST_WIDE_INT off);
> + static bool dwarf2out_die_ref_for_decl (tree decl, const char **sym,
> + 					unsigned HOST_WIDE_INT *off);
>   
>   /* The debug hooks structure.  */
>   
> *************** const struct gcc_debug_hooks dwarf2_debu
> *** 2720,2725 ****
> --- 2725,2732 ----
>     dwarf2out_late_global_decl,
>     dwarf2out_type_decl,		/* type_decl */
>     dwarf2out_imported_module_or_decl,
> +   dwarf2out_die_ref_for_decl,
> +   dwarf2out_register_external_die,
>     debug_nothing_tree,		/* deferred_inline_function */
>     /* The DWARF 2 backend tries to reduce debugging bloat by not
>        emitting the abstract description of inline functions until
> *************** const struct gcc_debug_hooks dwarf2_line
> *** 2761,2766 ****
> --- 2768,2775 ----
>     debug_nothing_tree,		         /* late_global_decl */
>     debug_nothing_tree_int,		 /* type_decl */
>     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
>     debug_nothing_tree,		         /* deferred_inline_function */
>     debug_nothing_tree,		         /* outlining_inline_function */
>     debug_nothing_rtx_code_label,	         /* label */
> *************** typedef struct GTY((chain_circular ("%h.
> *** 2889,2894 ****
> --- 2898,2906 ----
>     /* Die is used and must not be pruned as unused.  */
>     BOOL_BITFIELD die_perennial_p : 1;
>     BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
> +   /* For an external ref to die_symbol if die_offset contains an extra
> +      offset to that symbol.  */
> +   BOOL_BITFIELD with_offset : 1;
>     /* Whether this DIE was removed from the DIE tree, for example via
>        prune_unused_types.  We don't consider those present from the
>        DIE lookup routines.  */
> *************** new_addr_loc_descr (rtx addr, enum dtpre
> *** 3692,3703 ****
> --- 3704,3727 ----
>   #ifndef DEBUG_DWO_INFO_SECTION
>   #define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
>   #endif
> + #ifndef DEBUG_LTO_DWO_INFO_SECTION
> + #define DEBUG_LTO_DWO_INFO_SECTION ".gnu.debuglto_.debug_info.dwo"
> + #endif
> + #ifndef DEBUG_LTO_INFO_SECTION
> + #define DEBUG_LTO_INFO_SECTION	".gnu.debuglto_.debug_info"
> + #endif
>   #ifndef DEBUG_ABBREV_SECTION
>   #define DEBUG_ABBREV_SECTION	".debug_abbrev"
>   #endif
>   #ifndef DEBUG_DWO_ABBREV_SECTION
>   #define DEBUG_DWO_ABBREV_SECTION ".debug_abbrev.dwo"
>   #endif
> + #ifndef DEBUG_LTO_DWO_ABBREV_SECTION
> + #define DEBUG_LTO_DWO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev.dwo"
> + #endif
> + #ifndef DEBUG_LTO_ABBREV_SECTION
> + #define DEBUG_LTO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev"
> + #endif
>   #ifndef DEBUG_ARANGES_SECTION
>   #define DEBUG_ARANGES_SECTION	".debug_aranges"
>   #endif
> *************** new_addr_loc_descr (rtx addr, enum dtpre
> *** 3710,3727 ****
> --- 3734,3766 ----
>   #ifndef DEBUG_DWO_MACINFO_SECTION
>   #define DEBUG_DWO_MACINFO_SECTION      ".debug_macinfo.dwo"
>   #endif
> + #ifndef DEBUG_LTO_DWO_MACINFO_SECTION
> + #define DEBUG_LTO_DWO_MACINFO_SECTION  ".gnu.debuglto_.debug_macinfo.dwo"
> + #endif
> + #ifndef DEBUG_LTO_MACINFO_SECTION
> + #define DEBUG_LTO_MACINFO_SECTION      ".gnu.debuglto_.debug_macinfo"
> + #endif
>   #ifndef DEBUG_DWO_MACRO_SECTION
>   #define DEBUG_DWO_MACRO_SECTION        ".debug_macro.dwo"
>   #endif
>   #ifndef DEBUG_MACRO_SECTION
>   #define DEBUG_MACRO_SECTION	".debug_macro"
>   #endif
> + #ifndef DEBUG_LTO_DWO_MACRO_SECTION
> + #define DEBUG_LTO_DWO_MACRO_SECTION    ".gnu.debuglto_.debug_macro.dwo"
> + #endif
> + #ifndef DEBUG_LTO_MACRO_SECTION
> + #define DEBUG_LTO_MACRO_SECTION ".gnu.debuglto_.debug_macro"
> + #endif
>   #ifndef DEBUG_LINE_SECTION
>   #define DEBUG_LINE_SECTION	".debug_line"
>   #endif
>   #ifndef DEBUG_DWO_LINE_SECTION
>   #define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
>   #endif
> + #ifndef DEBUG_LTO_LINE_SECTION
> + #define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
> + #endif
>   #ifndef DEBUG_LOC_SECTION
>   #define DEBUG_LOC_SECTION	".debug_loc"
>   #endif
> *************** new_addr_loc_descr (rtx addr, enum dtpre
> *** 3750,3761 ****
> --- 3789,3809 ----
>   #ifndef DEBUG_DWO_STR_OFFSETS_SECTION
>   #define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo"
>   #endif
> + #ifndef DEBUG_LTO_DWO_STR_OFFSETS_SECTION
> + #define DEBUG_LTO_DWO_STR_OFFSETS_SECTION ".gnu.debuglto_.debug_str_offsets.dwo"
> + #endif
>   #ifndef DEBUG_STR_DWO_SECTION
>   #define DEBUG_STR_DWO_SECTION   ".debug_str.dwo"
>   #endif
> + #ifndef DEBUG_LTO_STR_DWO_SECTION
> + #define DEBUG_LTO_STR_DWO_SECTION ".gnu.debuglto_.debug_str.dwo"
> + #endif
>   #ifndef DEBUG_STR_SECTION
>   #define DEBUG_STR_SECTION  ".debug_str"
>   #endif
> + #ifndef DEBUG_LTO_STR_SECTION
> + #define DEBUG_LTO_STR_SECTION ".gnu.debuglto_.debug_str"
> + #endif
>   #ifndef DEBUG_RANGES_SECTION
>   #define DEBUG_RANGES_SECTION	".debug_ranges"
>   #endif
> *************** new_addr_loc_descr (rtx addr, enum dtpre
> *** 3780,3785 ****
> --- 3828,3837 ----
>   /* Section flags for .debug_str.dwo section.  */
>   #define DEBUG_STR_DWO_SECTION_FLAGS (SECTION_DEBUG | SECTION_EXCLUDE)
>   
> + /* Attribute used to refer to the macro section.  */
> + #define DEBUG_MACRO_ATTRIBUTE (dwarf_version >= 5 ? DW_AT_macros \
> + 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros)
> + 
>   /* Labels we insert at beginning sections we can reference instead of
>      the section names themselves.  */
>   
> *************** set_indirect_string (struct indirect_str
> *** 4368,4373 ****
> --- 4420,4443 ----
>       }
>   }
>   
> + /* A helper function for dwarf2out_finish, called to reset indirect
> +    string decisions done for early LTO dwarf output before fat object
> +    dwarf output.  */
> + 
> + int
> + reset_indirect_string (indirect_string_node **h, void *)
> + {
> +   struct indirect_string_node *node = *h;
> +   if (node->form == DW_FORM_strp || node->form == DW_FORM_GNU_str_index)
> +     {
> +       free (node->label);
> +       node->label = NULL;
> +       node->form = (dwarf_form) 0;
> +       node->index = 0;
> +     }
> +   return 1;
> + }
> + 
>   /* Find out whether a string should be output inline in DIE
>      or out-of-line in .debug_str section.  */
>   
> *************** lookup_decl_die (tree decl)
> *** 5413,5418 ****
> --- 5483,5668 ----
>     return *die;
>   }
>   
> + 
> + /* For DECL which might have early dwarf output query a SYMBOL + OFFSET
> +    style reference.  Return true if we found one refering to a DIE for
> +    DECL, otherwise return false.  */
> + 
> + static bool
> + dwarf2out_die_ref_for_decl (tree decl, const char **sym,
> + 			    unsigned HOST_WIDE_INT *off)
> + {
> +   dw_die_ref die;
> + 
> +   if (flag_wpa && !decl_die_table)
> +     return false;
> + 
> +   if (TREE_CODE (decl) == BLOCK)
> +     die = BLOCK_DIE (decl);
> +   else
> +     die = lookup_decl_die (decl);
> +   if (!die)
> +     return false;
> + 
> +   /* During WPA stage we currently use DIEs to store the
> +      decl <-> label + offset map.  That's quite inefficient but it
> +      works for now.  */
> +   if (flag_wpa)
> +     {
> +       dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
> +       if (!ref)
> + 	{
> + 	  gcc_assert (die == comp_unit_die ());
> + 	  return false;
> + 	}
> +       *off = ref->die_offset;
> +       *sym = ref->die_id.die_symbol;
> +       return true;
> +     }
> + 
> +   /* Similar to get_ref_die_offset_label, but using the "correct"
> +      label.  */
> +   *off = die->die_offset;
> +   while (die->die_parent)
> +     die = die->die_parent;
> +   /* For the containing CU DIE we compute a die_symbol in
> +      compute_section_prefix.  */
> +   gcc_assert (die->die_tag == DW_TAG_compile_unit
> + 	      && die->die_id.die_symbol != NULL);
> +   *sym = die->die_id.die_symbol;
> +   return true;
> + }
> + 
> + /* Add a reference of kind ATTR_KIND to a DIE at SYMBOL + OFFSET to DIE.  */
> + 
> + static void
> + add_AT_external_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind,
> + 			 const char *symbol, HOST_WIDE_INT offset)
> + {
> +   /* Create a fake DIE that contains the reference.  Don't use
> +      new_die because we don't want to end up in the limbo list.  */
> +   dw_die_ref ref = ggc_cleared_alloc<die_node> ();
> +   ref->die_tag = die->die_tag;
> +   ref->die_id.die_symbol = IDENTIFIER_POINTER (get_identifier (symbol));
> +   ref->die_offset = offset;
> +   ref->with_offset = 1;
> +   add_AT_die_ref (die, attr_kind, ref);
> + }
> + 
> + /* Create a DIE for DECL if required and add a reference to a DIE
> +    at SYMBOL + OFFSET which contains attributes dumped early.  */
> + 
> + static void
> + dwarf2out_register_external_die (tree decl, const char *sym,
> + 				 unsigned HOST_WIDE_INT off)
> + {
> +   if (debug_info_level == DINFO_LEVEL_NONE)
> +     return;
> + 
> +   if (flag_wpa && !decl_die_table)
> +     decl_die_table = hash_table<decl_die_hasher>::create_ggc (1000);
> + 
> +   dw_die_ref die
> +     = TREE_CODE (decl) == BLOCK ? BLOCK_DIE (decl) : lookup_decl_die (decl);
> +   gcc_assert (!die);
> + 
> +   tree ctx;
> +   dw_die_ref parent = NULL;
> +   /* Need to lookup a DIE for the decls context - the containing
> +      function or translation unit.  */
> +   if (TREE_CODE (decl) == BLOCK)
> +     {
> +       ctx = BLOCK_SUPERCONTEXT (decl);
> +       /* ???  We do not output DIEs for all scopes thus skip as
> + 	 many DIEs as needed.  */
> +       while (TREE_CODE (ctx) == BLOCK
> + 	     && !BLOCK_DIE (ctx))
> + 	ctx = BLOCK_SUPERCONTEXT (ctx);
> +     }
> +   else
> +     ctx = DECL_CONTEXT (decl);
> +   while (ctx && TYPE_P (ctx))
> +     ctx = TYPE_CONTEXT (ctx);
> +   if (ctx)
> +     {
> +       if (TREE_CODE (ctx) == BLOCK)
> + 	parent = BLOCK_DIE (ctx);
> +       else if (TREE_CODE (ctx) == TRANSLATION_UNIT_DECL
> + 	       /* Keep the 1:1 association during WPA.  */
> + 	       && !flag_wpa)
> + 	/* Otherwise all late annotations go to the main CU which
> + 	   imports the original CUs.  */
> + 	parent = comp_unit_die ();
> +       else if (TREE_CODE (ctx) == FUNCTION_DECL
> + 	       && TREE_CODE (decl) != PARM_DECL
> + 	       && TREE_CODE (decl) != BLOCK)
> + 	/* Leave function local entities parent determination to when
> + 	   we process scope vars.  */
> + 	;
> +       else
> + 	parent = lookup_decl_die (ctx);
> +     }
> +   else
> +     /* ???  In some cases the C++ FE (at least) fails to
> +        set DECL_CONTEXT properly.  Simply globalize stuff
> +        in this case.  For example
> +        __dso_handle created via iostream line 74 col 25.  */
> +     parent = comp_unit_die ();
> +   /* Create a DIE "stub".  */
> +   switch (TREE_CODE (decl))
> +     {
> +     case TRANSLATION_UNIT_DECL:
> +       if (! flag_wpa)
> + 	{
> + 	  die = comp_unit_die ();
> + 	  dw_die_ref import = new_die (DW_TAG_imported_unit, die, NULL_TREE);
> + 	  add_AT_external_die_ref (import, DW_AT_import, sym, off);
> + 	  /* We re-target all CU decls to the LTRANS CU DIE, so no need
> + 	     to create a DIE for the original CUs.  */
> + 	  return;
> + 	}
> +       /* Keep the 1:1 association during WPA.  */
> +       die = new_die (DW_TAG_compile_unit, NULL, decl);
> +       break;
> +     case NAMESPACE_DECL:
> +       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
> + 	 at the input language (if we have enough DECL_CONTEXT to follow)
> + 	 or use a bit in tree_decl_with_vis to record the distinction.  */
> +       die = new_die (DW_TAG_namespace, parent, decl);
> +       break;
> +     case FUNCTION_DECL:
> +       die = new_die (DW_TAG_subprogram, parent, decl);
> +       break;
> +     case VAR_DECL:
> +       die = new_die (DW_TAG_variable, parent, decl);
> +       break;
> +     case RESULT_DECL:
> +       die = new_die (DW_TAG_variable, parent, decl);
> +       break;
> +     case PARM_DECL:
> +       die = new_die (DW_TAG_formal_parameter, parent, decl);
> +       break;
> +     case CONST_DECL:
> +       die = new_die (DW_TAG_constant, parent, decl);
> +       break;
> +     case LABEL_DECL:
> +       die = new_die (DW_TAG_label, parent, decl);
> +       break;
> +     case BLOCK:
> +       die = new_die (DW_TAG_lexical_block, parent, decl);
> +       break;
> +     default:
> +       gcc_unreachable ();
> +     }
> +   if (TREE_CODE (decl) == BLOCK)
> +     BLOCK_DIE (decl) = die;
> +   else
> +     equate_decl_number_to_die (decl, die);
> + 
> +   /* Add a reference to the DIE providing early debug at $sym + off.  */
> +   add_AT_external_die_ref (die, DW_AT_abstract_origin, sym, off);
> + }
> + 
>   /* Returns a hash value for X (which really is a var_loc_list).  */
>   
>   inline hashval_t
> *************** print_dw_val (dw_val_node *val, bool rec
> *** 5900,5906 ****
>   			       die->die_id.die_type_node->signature);
>   	    }
>   	  else if (die->die_id.die_symbol)
> ! 	    fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
>   	  else
>   	    fprintf (outfile, "die -> %ld", die->die_offset);
>   	  fprintf (outfile, " (%p)", (void *) die);
> --- 6150,6160 ----
>   			       die->die_id.die_type_node->signature);
>   	    }
>   	  else if (die->die_id.die_symbol)
> ! 	    {
> ! 	      fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
> ! 	      if (die->with_offset)
> ! 		fprintf (outfile, " + %ld", die->die_offset);
> ! 	    }
>   	  else
>   	    fprintf (outfile, "die -> %ld", die->die_offset);
>   	  fprintf (outfile, " (%p)", (void *) die);
> *************** static unsigned int comdat_symbol_number
> *** 7216,7222 ****
>      children, and set comdat_symbol_id accordingly.  */
>   
>   static void
> ! compute_section_prefix (dw_die_ref unit_die)
>   {
>     const char *die_name = get_AT_string (unit_die, DW_AT_name);
>     const char *base = die_name ? lbasename (die_name) : "anonymous";
> --- 7470,7476 ----
>      children, and set comdat_symbol_id accordingly.  */
>   
>   static void
> ! compute_section_prefix_1 (dw_die_ref unit_die, bool comdat_p)
>   {
>     const char *die_name = get_AT_string (unit_die, DW_AT_name);
>     const char *base = die_name ? lbasename (die_name) : "anonymous";
> *************** compute_section_prefix (dw_die_ref unit_
> *** 7235,7241 ****
>     unmark_all_dies (unit_die);
>     md5_finish_ctx (&ctx, checksum);
>   
> !   sprintf (name, "%s.", base);
>     clean_symbol_name (name);
>   
>     p = name + strlen (name);
> --- 7489,7499 ----
>     unmark_all_dies (unit_die);
>     md5_finish_ctx (&ctx, checksum);
>   
> !   /* When we this for comp_unit_die () we have a DW_AT_name that might
> !      not start with a letter but with anything valid for filenames and
> !      clean_symbol_name doesn't fix that up.  Prepend 'g' if the first
> !      character is not a letter.  */
> !   sprintf (name, "%s%s.", ISALPHA (*base) ? "" : "g", base);
>     clean_symbol_name (name);
>   
>     p = name + strlen (name);
> *************** compute_section_prefix (dw_die_ref unit_
> *** 7245,7251 ****
>         p += 2;
>       }
>   
> !   comdat_symbol_id = unit_die->die_id.die_symbol = xstrdup (name);
>     comdat_symbol_number = 0;
>   }
>   
> --- 7503,7517 ----
>         p += 2;
>       }
>   
> !   unit_die->die_id.die_symbol = xstrdup (name);
> !   unit_die->comdat_type_p = comdat_p;
> ! }
> ! 
> ! static void
> ! compute_section_prefix (dw_die_ref unit_die)
> ! {
> !   compute_section_prefix_1 (unit_die, true);
> !   comdat_symbol_id = unit_die->die_id.die_symbol;
>     comdat_symbol_number = 0;
>   }
>   
> *************** output_die (dw_die_ref die)
> *** 9971,9977 ****
>   
>     /* If someone in another CU might refer to us, set up a symbol for
>        them to point to.  */
> !   if (! die->comdat_type_p && die->die_id.die_symbol)
>       output_die_symbol (die);
>   
>     dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
> --- 10237,10247 ----
>   
>     /* If someone in another CU might refer to us, set up a symbol for
>        them to point to.  */
> !   if (! die->comdat_type_p && die->die_id.die_symbol
> !       /* Don't output the symbol twice.  For LTO we want the label
> !          on the section beginning, not on the actual DIE.  */
> !       && (!flag_generate_lto
> ! 	  || die->die_tag != DW_TAG_compile_unit))
>       output_die_symbol (die);
>   
>     dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
> *************** output_die (dw_die_ref die)
> *** 10164,10171 ****
>   		    size = DWARF2_ADDR_SIZE;
>   		  else
>   		    size = DWARF_OFFSET_SIZE;
> ! 		  dw2_asm_output_offset (size, sym, debug_info_section, "%s",
> ! 					 name);
>   		}
>   	    }
>   	  else
> --- 10434,10453 ----
>   		    size = DWARF2_ADDR_SIZE;
>   		  else
>   		    size = DWARF_OFFSET_SIZE;
> ! 		  /* ???  We cannot unconditionally output die_offset if
> ! 		     non-zero - at least -feliminate-dwarf2-dups will
> ! 		     create references to those DIEs via symbols.  And we
> ! 		     do not clear its DIE offset after outputting it
> ! 		     (and the label refers to the actual DIEs, not the
> ! 		     DWARF CU unit header which is when using label + offset
> ! 		     would be the correct thing to do).
> ! 		     ???  This is the reason for the with_offset flag.  */
> ! 		  if (AT_ref (a)->with_offset)
> ! 		    dw2_asm_output_offset (size, sym, AT_ref (a)->die_offset,
> ! 					   debug_info_section, "%s", name);
> ! 		  else
> ! 		    dw2_asm_output_offset (size, sym, debug_info_section, "%s",
> ! 					   name);
>   		}
>   	    }
>   	  else
> *************** output_comp_unit (dw_die_ref die, int ou
> *** 10391,10397 ****
>     calc_die_sizes (die);
>   
>     oldsym = die->die_id.die_symbol;
> !   if (oldsym)
>       {
>         tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
>   
> --- 10673,10679 ----
>     calc_die_sizes (die);
>   
>     oldsym = die->die_id.die_symbol;
> !   if (oldsym && die->comdat_type_p)
>       {
>         tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
>   
> *************** output_comp_unit (dw_die_ref die, int ou
> *** 10407,10412 ****
> --- 10689,10721 ----
>         info_section_emitted = true;
>       }
>   
> +   /* For LTO cross unit DIE refs we want a symbol on the start of the
> +      debuginfo section, not on the CU DIE.
> +      ???  We could simply use the symbol as it would be output by output_die
> +      and account for the extra offset produced by the CU header which has fixed
> +      size.  OTOH it currently only supports linkonce globals which would
> +      be less than ideal?.  */
> +   if (flag_generate_lto && oldsym)
> +     {
> +       /* ???  No way to get visibility assembled without a decl.  */
> +       tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
> + 			      get_identifier (oldsym), char_type_node);
> +       TREE_PUBLIC (decl) = true;
> +       TREE_STATIC (decl) = true;
> +       DECL_ARTIFICIAL (decl) = true;
> +       DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
> +       DECL_VISIBILITY_SPECIFIED (decl) = true;
> +       targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
> + #ifdef ASM_WEAKEN_LABEL
> +       /* We prefer a .weak because that handles duplicates from duplicate
> +          archive members in a graceful way.  */
> +       ASM_WEAKEN_LABEL (asm_out_file, oldsym);
> + #else
> +       targetm.asm_out.globalize_label (asm_out_file, oldsym);
> + #endif
> +       ASM_OUTPUT_LABEL (asm_out_file, oldsym);
> +     }
> + 
>     /* Output debugging information.  */
>     output_compilation_unit_header (dwo_id
>   				  ? DW_UT_split_compile : DW_UT_compile);
> *************** parameter_ref_descriptor (rtx rtl)
> *** 14523,14528 ****
> --- 14832,14840 ----
>     if (dwarf_strict)
>       return NULL;
>     gcc_assert (TREE_CODE (DEBUG_PARAMETER_REF_DECL (rtl)) == PARM_DECL);
> +   /* With LTO during LTRANS we get the late DIE that refers to the early
> +      DIE, thus we add another indirection here.  This seems to confuse
> +      gdb enough to make gcc.dg/guality/pr68860-1.c FAIL with LTO.  */
>     ref = lookup_decl_die (DEBUG_PARAMETER_REF_DECL (rtl));
>     ret = new_loc_descr (DW_OP_GNU_parameter_ref, 0, 0);
>     if (ref)
> *************** add_abstract_origin_attribute (dw_die_re
> *** 20216,20222 ****
>       }
>   
>     if (DECL_P (origin))
> !     origin_die = lookup_decl_die (origin);
>     else if (TYPE_P (origin))
>       origin_die = lookup_type_die (origin);
>     else if (TREE_CODE (origin) == BLOCK)
> --- 20528,20547 ----
>       }
>   
>     if (DECL_P (origin))
> !     {
> !       dw_die_ref c;
> !       origin_die = lookup_decl_die (origin);
> !       /* "Unwrap" the decls DIE which we put in the imported unit context.
> !           ???  If we finish dwarf2out_function_decl refactoring we can
> ! 	  do this in a better way from the start and only lazily emit
> ! 	  the early DIE references.  */
> !       if (in_lto_p
> ! 	  && origin_die
> ! 	  && (c = get_AT_ref (origin_die, DW_AT_abstract_origin))
> ! 	  /* ???  Identify this better.  */
> ! 	  && c->with_offset)
> ! 	origin_die = c;
> !     }
>     else if (TYPE_P (origin))
>       origin_die = lookup_type_die (origin);
>     else if (TREE_CODE (origin) == BLOCK)
> *************** gen_array_type_die (tree type, dw_die_re
> *** 20775,20781 ****
>         size = int_size_in_bytes (type);
>         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)
>   	{
>   	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> --- 21100,21109 ----
>         size = int_size_in_bytes (type);
>         if (size >= 0)
>   	add_AT_unsigned (array_die, DW_AT_byte_size, size);
> !       /* ???  We can't annotate types late, but for LTO we may not
> ! 	 generate a location early either (gfortran.dg/save_6.f90).  */
> !       else if (! (early_dwarf && flag_generate_lto)
> ! 	       && TYPE_DOMAIN (type) != NULL_TREE
>   	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE)
>   	{
>   	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> *************** gen_formal_parameter_die (tree node, tre
> *** 21188,21194 ****
>   	 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
> --- 21516,21524 ----
>   	 thing.  */
>         if (parm_die && parm_die->die_parent != context_die)
>   	{
> ! 	  /* ???  The DIE parent is the "abstract" copy and the context_die
> ! 	     is the specification "copy".  */
> ! 	  if (!DECL_ABSTRACT_P (node) && !in_lto_p)
>   	    {
>   	      /* This can happen when creating an inlined instance, in
>   		 which case we need to create a new DIE that will get
> *************** gen_type_die_for_member (tree type, tree
> *** 21462,21468 ****
>   /* 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, 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
> --- 21792,21797 ----
> *************** set_decl_origin_self (tree decl)
> *** 21535,21685 ****
>       }
>   }
>   \f
> ! /* 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, vec<tree> &abstract_vec)
> ! {
> !   tree local_decl;
> !   tree subblock;
> !   unsigned int i;
> ! 
> !   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, abstract_vec);
> ! 
> !   for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
> !     {
> !       local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i);
> !       if ((VAR_P (local_decl) && !TREE_STATIC (local_decl))
> ! 	  || TREE_CODE (local_decl) == PARM_DECL)
> ! 	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, abstract_vec);
> ! }
> ! 
> ! /* 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, vec<tree> &abstract_vec)
> ! {
> !   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))
> ! 	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), 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.
> ! 
> !    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)
>   {
>     dw_die_ref old_die;
> -   tree save_fn;
> -   tree context;
> -   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;
> -   struct call_arg_loc_node *old_call_arg_locations;
>   
>     /* Make sure we have the actual abstract inline, not a clone.  */
>     decl = DECL_ORIGIN (decl);
>   
>     old_die = lookup_decl_die (decl);
> !   if (old_die && get_AT (old_die, DW_AT_inline))
>       /* We've already generated the abstract instance.  */
>       return;
>   
> !   /* We can be called while recursively when seeing block defining inlined subroutine
> !      DIE.  Be sure to not clobber the outer location table nor use it or we would
> !      get locations in abstract instantces.  */
> !   old_decl_loc_table = decl_loc_table;
> !   decl_loc_table = NULL;
> !   old_cached_dw_loc_list_table = cached_dw_loc_list_table;
> !   cached_dw_loc_list_table = NULL;
> !   old_call_arg_locations = call_arg_locations;
> !   call_arg_locations = NULL;
> !   old_call_site_count = call_site_count;
> !   call_site_count = -1;
> !   old_tail_call_site_count = tail_call_site_count;
> !   tail_call_site_count = -1;
> ! 
> !   /* Be sure we've emitted the in-class declaration DIE (if any) first, so
> !      we don't get confused by DECL_ABSTRACT_P.  */
> !   if (debug_info_level > DINFO_LEVEL_TERSE)
>       {
> !       context = decl_class_context (decl);
> !       if (context)
> ! 	gen_type_die_for_member
> ! 	  (context, decl, decl_function_context (decl) ? NULL : comp_unit_die ());
>       }
>   
> !   /* Pretend we've just finished compiling this function.  */
> !   save_fn = current_function_decl;
> !   current_function_decl = decl;
> ! 
> !   auto_vec<tree, 64> abstract_vec;
> !   set_decl_abstract_flags (decl, abstract_vec);
> !   dwarf2out_decl (decl);
> !   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;
> !   cached_dw_loc_list_table = old_cached_dw_loc_list_table;
> !   call_arg_locations = old_call_arg_locations;
> !   call_site_count = old_call_site_count;
> !   tail_call_site_count = old_tail_call_site_count;
>   }
>   
>   /* Helper function of premark_used_types() which gets called through
> --- 21864,21908 ----
>       }
>   }
>   \f
> ! /* Mark the early DIE for DECL as the abstract instance.  */
>   
>   static void
>   dwarf2out_abstract_function (tree decl)
>   {
>     dw_die_ref old_die;
>   
>     /* Make sure we have the actual abstract inline, not a clone.  */
>     decl = DECL_ORIGIN (decl);
>   
> +   if (DECL_IGNORED_P (decl))
> +     return;
> + 
>     old_die = lookup_decl_die (decl);
> !   /* With early debug we always have an old DIE.  */
> !   gcc_assert (old_die != NULL);
> !   if (get_AT (old_die, DW_AT_inline))
>       /* We've already generated the abstract instance.  */
>       return;
>   
> !   /* Go ahead and put DW_AT_inline on the DIE.  */
> !   if (DECL_DECLARED_INLINE_P (decl))
>       {
> !       if (cgraph_function_possibly_inlined_p (decl))
> ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_inlined);
> !       else
> ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_not_inlined);
> !     }
> !   else
> !     {
> !       if (cgraph_function_possibly_inlined_p (decl))
> ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_inlined);
> !       else
> ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_not_inlined);
>       }
>   
> !   if (DECL_DECLARED_INLINE_P (decl)
> !       && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
> !     add_AT_flag (old_die, DW_AT_artificial, 1);
>   }
>   
>   /* Helper function of premark_used_types() which gets called through
> *************** gen_subprogram_die (tree decl, dw_die_re
> *** 21901,21907 ****
>         if (old_die && old_die->die_parent == NULL)
>   	add_child_die (context_die, old_die);
>   
> !       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.  */
> --- 22124,22135 ----
>         if (old_die && old_die->die_parent == NULL)
>   	add_child_die (context_die, old_die);
>   
> !       dw_die_ref c;
> !       if (old_die
> ! 	  && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
> ! 	  /* ???  In LTO all origin DIEs still refer to the early
> ! 	     debug copy.  Detect that.  */
> ! 	  && get_AT (c, DW_AT_inline))
>   	{
>   	  /* If we have a DW_AT_abstract_origin we have a working
>   	     cached version.  */
> *************** gen_subprogram_die (tree decl, dw_die_re
> *** 21969,21975 ****
>   	   || (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)
> --- 22197,22204 ----
>   	   || (old_die->die_parent
>   	       && old_die->die_parent->die_tag == DW_TAG_module)
>   	   || context_die == NULL)
> ! 	  /* ???  In LTO we do not see any of the location attributes.  */
> ! 	   && ((DECL_ARTIFICIAL (decl) || in_lto_p)
>   	       || (get_AT_file (old_die, DW_AT_decl_file) == file_index
>   		   && (get_AT_unsigned (old_die, DW_AT_decl_line)
>   		       == (unsigned) s.line)
> *************** gen_variable_die (tree decl, tree origin
> *** 22836,22841 ****
> --- 23065,23088 ----
>   	  /* If a DIE was dumped early, it still needs location info.
>   	     Skip to where we fill the location bits.  */
>   	  var_die = old_die;
> + 
> + 	  /* ???  In LTRANS we cannot annotate early created variably
> + 	     modified type DIEs without copying them and adjusting all
> + 	     references to them.  Thus we dumped them again, also add a
> + 	     reference to them.  */
> + 	  tree type = TREE_TYPE (decl_or_origin);
> + 	  if (in_lto_p
> + 	      && variably_modified_type_p
> + 		   (type, decl_function_context (decl_or_origin)))
> + 	    {
> + 	      if (decl_by_reference_p (decl_or_origin))
> + 		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),
> + 				    false, context_die);
> + 	    }
> + 
>   	  goto gen_variable_die_location;
>   	}
>       }
> *************** gen_inlined_subroutine_die (tree stmt, d
> *** 23236,23247 ****
>     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
> -      a die whose origin die hasn't been emitted, and crashing.  */
> -   dwarf2out_abstract_function (decl);
> - 
>     if (! BLOCK_ABSTRACT (stmt))
>       {
>         dw_die_ref subr_die
> --- 23483,23488 ----
> *************** process_scope_var (tree stmt, tree decl,
> *** 24868,24874 ****
>   					     stmt, context_die);
>       }
>     else
> !     gen_decl_die (decl, origin, NULL, context_die);
>   }
>   
>   /* Generate all of the decls declared within a given scope and (recursively)
> --- 25109,25128 ----
>   					     stmt, context_die);
>       }
>     else
> !     {
> !       if (decl && DECL_P (decl))
> ! 	{
> ! 	  die = lookup_decl_die (decl);
> ! 
> ! 	  /* Early created DIEs do not have a parent as the decls refer
> ! 	     to the function as DECL_CONTEXT rather than the BLOCK.  */
> ! 	  if (in_lto_p
> ! 	      && die && die->die_parent == NULL)
> ! 	    add_child_die (context_die, die);
> ! 	}
> ! 
> !       gen_decl_die (decl, origin, NULL, context_die);
> !     }
>   }
>   
>   /* Generate all of the decls declared within a given scope and (recursively)
> *************** gen_decl_die (tree decl, tree origin, st
> *** 25288,25295 ****
>   				     ? DECL_ORIGIN (origin)
>   				     : DECL_ABSTRACT_ORIGIN (decl));
>   
> !       /* If we're emitting an out-of-line copy of an inline function,
> ! 	 emit info for the abstract instance and set up to refer to it.  */
>         else if (cgraph_function_possibly_inlined_p (decl)
>   	       && ! DECL_ABSTRACT_P (decl)
>   	       && ! class_or_namespace_scope_p (context_die)
> --- 25542,25549 ----
>   				     ? DECL_ORIGIN (origin)
>   				     : DECL_ABSTRACT_ORIGIN (decl));
>   
> !       /* If we're emitting a possibly inlined function emit it as
> !          abstract instance.  */
>         else if (cgraph_function_possibly_inlined_p (decl)
>   	       && ! DECL_ABSTRACT_P (decl)
>   	       && ! class_or_namespace_scope_p (context_die)
> *************** gen_decl_die (tree decl, tree origin, st
> *** 25303,25309 ****
>   	}
>   
>         /* Otherwise we're emitting the primary DIE for this decl.  */
> !       else if (debug_info_level > DINFO_LEVEL_TERSE)
>   	{
>   	  /* Before we describe the FUNCTION_DECL itself, make sure that we
>   	     have its containing type.  */
> --- 25557,25565 ----
>   	}
>   
>         /* Otherwise we're emitting the primary DIE for this decl.  */
> !       else if (debug_info_level > DINFO_LEVEL_TERSE
> ! 	       /* Do not generate stray type DIEs in late LTO dumping.  */
> ! 	       && early_dwarf)
>   	{
>   	  /* Before we describe the FUNCTION_DECL itself, make sure that we
>   	     have its containing type.  */
> *************** gen_decl_die (tree decl, tree origin, st
> *** 25370,25389 ****
>         if (debug_info_level <= DINFO_LEVEL_TERSE)
>   	break;
>   
> !       /* Output any DIEs that are needed to specify the type of this data
> ! 	 object.  */
> !       if (decl_by_reference_p (decl_or_origin))
> ! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> !       else
> ! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
>   
> !       /* And its containing type.  */
> !       class_origin = decl_class_context (decl_or_origin);
> !       if (class_origin != NULL_TREE)
> ! 	gen_type_die_for_member (class_origin, decl_or_origin, context_die);
>   
> !       /* And its containing namespace.  */
> !       context_die = declare_in_namespace (decl_or_origin, context_die);
>   
>         /* Now output the DIE to represent the data object itself.  This gets
>   	 complicated because of the possibility that the VAR_DECL really
> --- 25626,25661 ----
>         if (debug_info_level <= DINFO_LEVEL_TERSE)
>   	break;
>   
> !       /* Avoid generating stray type DIEs during late dwarf dumping.
> !          All types have been dumped early.  */
> !       if (! lookup_decl_die (decl_or_origin)
> ! 	  /* ???  But in LTRANS we cannot annotate early created variably
> ! 	     modified type DIEs without copying them and adjusting all
> ! 	     references to them.  Dump them again as happens for inlining
> ! 	     which copies both the decl and the types.  */
> ! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
> ! 	     in VLA bound information for example.  */
> ! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
> ! 						current_function_decl)))
> ! 	{
> ! 	  /* Output any DIEs that are needed to specify the type of this data
> ! 	     object.  */
> ! 	  if (decl_by_reference_p (decl_or_origin))
> ! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> ! 	  else
> ! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> ! 	}
>   
> !       if (early_dwarf)
> ! 	{
> ! 	  /* And its containing type.  */
> ! 	  class_origin = decl_class_context (decl_or_origin);
> ! 	  if (class_origin != NULL_TREE)
> ! 	    gen_type_die_for_member (class_origin, decl_or_origin, context_die);
>   
> ! 	  /* And its containing namespace.  */
> ! 	  context_die = declare_in_namespace (decl_or_origin, context_die);
> ! 	}
>   
>         /* Now output the DIE to represent the data object itself.  This gets
>   	 complicated because of the possibility that the VAR_DECL really
> *************** gen_decl_die (tree decl, tree origin, st
> *** 25413,25422 ****
>         break;
>   
>       case PARM_DECL:
> !       if (DECL_BY_REFERENCE (decl_or_origin))
> ! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> !       else
> ! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
>         return gen_formal_parameter_die (decl, origin,
>   				       true /* Emit name attribute.  */,
>   				       context_die);
> --- 25685,25707 ----
>         break;
>   
>       case PARM_DECL:
> !       /* Avoid generating stray type DIEs during late dwarf dumping.
> !          All types have been dumped early.  */
> !       if (! lookup_decl_die (decl_or_origin)
> ! 	  /* ???  But in LTRANS we cannot annotate early created variably
> ! 	     modified type DIEs without copying them and adjusting all
> ! 	     references to them.  Dump them again as happens for inlining
> ! 	     which copies both the decl and the types.  */
> ! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
> ! 	     in VLA bound information for example.  */
> ! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
> ! 						current_function_decl)))
> ! 	{
> ! 	  if (DECL_BY_REFERENCE (decl_or_origin))
> ! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> ! 	  else
> ! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> ! 	}
>         return gen_formal_parameter_die (decl, origin,
>   				       true /* Emit name attribute.  */,
>   				       context_die);
> *************** dwarf2out_early_global_decl (tree decl)
> *** 25493,25498 ****
> --- 25778,25793 ----
>   	      dwarf2out_decl (context);
>   	    }
>   
> + 	  /* Emit an abstract origin of a function first.  This happens
> + 	     with C++ constructor clones for example and makes
> + 	     dwarf2out_abstract_function happy which requires the early
> + 	     DIE of the abstract instance to be present.  */
> + 	  if (DECL_ABSTRACT_ORIGIN (decl))
> + 	    {
> + 	      current_function_decl = DECL_ABSTRACT_ORIGIN (decl);
> + 	      dwarf2out_decl (DECL_ABSTRACT_ORIGIN (decl));
> + 	    }
> + 
>   	  current_function_decl = decl;
>   	}
>         dwarf2out_decl (decl);
> *************** dwarf2out_late_global_decl (tree decl)
> *** 25515,25521 ****
>       {
>         dw_die_ref die = lookup_decl_die (decl);
>   
> !       /* We have to generate early debug late for LTO.  */
>         if (! die && in_lto_p)
>   	{
>   	  dwarf2out_decl (decl);
> --- 25810,25818 ----
>       {
>         dw_die_ref die = lookup_decl_die (decl);
>   
> !       /* We may have to generate early debug late for LTO in case debug
> !          was not enabled at compile-time or the target doesn't support
> ! 	 the LTO early debug scheme.  */
>         if (! die && in_lto_p)
>   	{
>   	  dwarf2out_decl (decl);
> *************** output_macinfo_op (macinfo_entry *ref)
> *** 26892,26898 ****
>       case DW_MACRO_import:
>         dw2_asm_output_data (1, ref->code, "Import");
>         ASM_GENERATE_INTERNAL_LABEL (label,
> ! 				   DEBUG_MACRO_SECTION_LABEL, ref->lineno);
>         dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
>         break;
>       default:
> --- 27189,27196 ----
>       case DW_MACRO_import:
>         dw2_asm_output_data (1, ref->code, "Import");
>         ASM_GENERATE_INTERNAL_LABEL (label,
> ! 				   DEBUG_MACRO_SECTION_LABEL,
> ! 				   ref->lineno + macinfo_label_base);
>         dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
>         break;
>       default:
> *************** save_macinfo_strings (void)
> *** 27066,27072 ****
>   /* Output macinfo section(s).  */
>   
>   static void
> ! output_macinfo (void)
>   {
>     unsigned i;
>     unsigned long length = vec_safe_length (macinfo_table);
> --- 27364,27370 ----
>   /* Output macinfo section(s).  */
>   
>   static void
> ! output_macinfo (const char *debug_line_label, bool early_lto_debug)
>   {
>     unsigned i;
>     unsigned long length = vec_safe_length (macinfo_table);
> *************** output_macinfo (void)
> *** 27092,27100 ****
>   	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
>         else
>   	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
> !       dw2_asm_output_offset (DWARF_OFFSET_SIZE,
> !                              (!dwarf_split_debug_info ? debug_line_section_label
> !                               : debug_skeleton_line_section_label),
>                                debug_line_section, NULL);
>       }
>   
> --- 27390,27396 ----
>   	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
>         else
>   	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
> !       dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_line_label,
>                                debug_line_section, NULL);
>       }
>   
> *************** output_macinfo (void)
> *** 27148,27153 ****
> --- 27444,27453 ----
>     if (!macinfo_htab)
>       return;
>   
> +   /* Save the number of transparent includes so we can adjust the
> +      label number for the fat LTO object DWARF.  */
> +   unsigned macinfo_label_base_adj = macinfo_htab->elements ();
> + 
>     delete macinfo_htab;
>     macinfo_htab = NULL;
>   
> *************** output_macinfo (void)
> *** 27167,27177 ****
>   	  dw2_asm_output_data (1, 0, "End compilation unit");
>   	  targetm.asm_out.named_section (debug_macinfo_section_name,
>   					 SECTION_DEBUG
> ! 					 | SECTION_LINKONCE,
>   					 comdat_key);
>   	  ASM_GENERATE_INTERNAL_LABEL (label,
>   				       DEBUG_MACRO_SECTION_LABEL,
> ! 				       ref->lineno);
>   	  ASM_OUTPUT_LABEL (asm_out_file, label);
>   	  ref->code = 0;
>   	  ref->info = NULL;
> --- 27467,27479 ----
>   	  dw2_asm_output_data (1, 0, "End compilation unit");
>   	  targetm.asm_out.named_section (debug_macinfo_section_name,
>   					 SECTION_DEBUG
> ! 					 | SECTION_LINKONCE
> ! 					 | (early_lto_debug
> ! 					    ? SECTION_EXCLUDE : 0),
>   					 comdat_key);
>   	  ASM_GENERATE_INTERNAL_LABEL (label,
>   				       DEBUG_MACRO_SECTION_LABEL,
> ! 				       ref->lineno + macinfo_label_base);
>   	  ASM_OUTPUT_LABEL (asm_out_file, label);
>   	  ref->code = 0;
>   	  ref->info = NULL;
> *************** output_macinfo (void)
> *** 27192,27300 ****
>         default:
>   	gcc_unreachable ();
>         }
>   }
>   
> ! /* Initialize the various sections and labels for dwarf output.  */
>   
>   static void
> ! init_sections_and_labels (void)
>   {
> !   if (!dwarf_split_debug_info)
>       {
> !       debug_info_section = get_section (DEBUG_INFO_SECTION,
> !                                         SECTION_DEBUG, NULL);
> !       debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> !                                           SECTION_DEBUG, NULL);
> !       debug_loc_section = get_section (dwarf_version >= 5
> ! 				       ? DEBUG_LOCLISTS_SECTION
> ! 				       : DEBUG_LOC_SECTION,
> !                                        SECTION_DEBUG, NULL);
> !       debug_macinfo_section_name
> ! 	= (dwarf_strict && dwarf_version < 5)
> ! 	  ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
> !       debug_macinfo_section = get_section (debug_macinfo_section_name,
> ! 					   SECTION_DEBUG, NULL);
>       }
>     else
>       {
> !       debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
> !                                         SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> !       debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
> !                                           SECTION_DEBUG | SECTION_EXCLUDE,
> !                                           NULL);
> !       debug_addr_section = get_section (DEBUG_ADDR_SECTION,
> !                                         SECTION_DEBUG, NULL);
> !       debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
> !                                                  SECTION_DEBUG, NULL);
> !       debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> !                                                    SECTION_DEBUG, NULL);
> !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> !                                   DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0);
> ! 
> !       /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
> !          the main .o, but the skeleton_line goes into the split off dwo.  */
> !       debug_skeleton_line_section
> !         = get_section (DEBUG_DWO_LINE_SECTION,
> ! 		       SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> !                                    DEBUG_SKELETON_LINE_SECTION_LABEL, 0);
> !       debug_str_offsets_section = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
> !                                                SECTION_DEBUG | SECTION_EXCLUDE,
> !                                                NULL);
> !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> !                                    DEBUG_SKELETON_INFO_SECTION_LABEL, 0);
> !       debug_loc_section = get_section (dwarf_version >= 5
> ! 				       ? DEBUG_DWO_LOCLISTS_SECTION
> ! 				       : DEBUG_DWO_LOC_SECTION,
> !                                        SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> !       debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
> !                                            DEBUG_STR_DWO_SECTION_FLAGS, NULL);
> !       debug_macinfo_section_name
> ! 	= (dwarf_strict && dwarf_version < 5)
> ! 	  ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
> !       debug_macinfo_section = get_section (debug_macinfo_section_name,
>   					   SECTION_DEBUG | SECTION_EXCLUDE,
>   					   NULL);
> !     }
> !   debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
> ! 				       SECTION_DEBUG, NULL);
> !   debug_line_section = get_section (DEBUG_LINE_SECTION,
> ! 				    SECTION_DEBUG, NULL);
> !   debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
> ! 					SECTION_DEBUG, NULL);
> !   debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
>   					SECTION_DEBUG, NULL);
> !   debug_str_section = get_section (DEBUG_STR_SECTION,
> ! 				   DEBUG_STR_SECTION_FLAGS, NULL);
> !   if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
> !     debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
> ! 					  DEBUG_STR_SECTION_FLAGS, NULL);
> ! 
> !   debug_ranges_section = get_section (dwarf_version >= 5
> ! 				      ? DEBUG_RNGLISTS_SECTION
> ! 				      : DEBUG_RANGES_SECTION,
> ! 				      SECTION_DEBUG, NULL);
> !   debug_frame_section = get_section (DEBUG_FRAME_SECTION,
> ! 				     SECTION_DEBUG, NULL);
>   
>     ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
> ! 			       DEBUG_ABBREV_SECTION_LABEL, 0);
>     ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
> ! 			       DEBUG_INFO_SECTION_LABEL, 0);
>     ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
> ! 			       DEBUG_LINE_SECTION_LABEL, 0);
>     ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
> ! 			       DEBUG_RANGES_SECTION_LABEL, 0);
>     if (dwarf_version >= 5 && dwarf_split_debug_info)
>       ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
> ! 				 DEBUG_RANGES_SECTION_LABEL, 1);
>     ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
> !                                DEBUG_ADDR_SECTION_LABEL, 0);
>     ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
>   			       (dwarf_strict && dwarf_version < 5)
>   			       ? DEBUG_MACINFO_SECTION_LABEL
> ! 			       : DEBUG_MACRO_SECTION_LABEL, 0);
> !   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0);
>   }
>   
>   /* Set up for Dwarf output at the start of compilation.  */
> --- 27494,27685 ----
>         default:
>   	gcc_unreachable ();
>         }
> + 
> +   macinfo_label_base += macinfo_label_base_adj;
>   }
>   
> ! /* Initialize the various sections and labels for dwarf output and prefix
> !    them with PREFIX if non-NULL.  */
>   
>   static void
> ! init_sections_and_labels (bool early_lto_debug)
>   {
> !   /* As we may get called multiple times have a generation count for labels.  */
> !   static unsigned generation = 0;
> ! 
> !   if (early_lto_debug)
>       {
> !       if (!dwarf_split_debug_info)
> ! 	{
> ! 	  debug_info_section = get_section (DEBUG_LTO_INFO_SECTION,
> ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> ! 					    NULL);
> ! 	  debug_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
> ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> ! 					      NULL);
> ! 	  debug_macinfo_section_name = ((dwarf_strict && dwarf_version < 5)
> ! 					? DEBUG_LTO_MACINFO_SECTION
> ! 					: DEBUG_LTO_MACRO_SECTION);
> ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> ! 					       SECTION_DEBUG
> ! 					       | SECTION_EXCLUDE, NULL);
> ! 	  /* For macro info we have to refer to a debug_line section, so similar
> ! 	     to split-dwarf emit a skeleton one for early debug.  */
> ! 	  debug_skeleton_line_section
> ! 	    = get_section (DEBUG_LTO_LINE_SECTION,
> ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> ! 				       generation);
> ! 	}
> !       else
> ! 	{
> ! 	  /* ???  Which of the following do we need early?  */
> ! 	  debug_info_section = get_section (DEBUG_LTO_DWO_INFO_SECTION,
> ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> ! 					    NULL);
> ! 	  debug_abbrev_section = get_section (DEBUG_LTO_DWO_ABBREV_SECTION,
> ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> ! 					      NULL);
> ! 	  debug_skeleton_info_section = get_section (DEBUG_LTO_INFO_SECTION,
> ! 						     SECTION_DEBUG
> ! 						     | SECTION_EXCLUDE, NULL);
> ! 	  debug_skeleton_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
> ! 						       SECTION_DEBUG
> ! 						       | SECTION_EXCLUDE, NULL);
> ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> ! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
> ! 				       generation);
> ! 
> ! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
> ! 	     the main .o, but the skeleton_line goes into the split off dwo.  */
> ! 	  debug_skeleton_line_section
> ! 	    = get_section (DEBUG_LTO_LINE_SECTION,
> ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> ! 				       generation);
> ! 	  debug_str_offsets_section
> ! 	    = get_section (DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
> ! 			   SECTION_DEBUG | SECTION_EXCLUDE,
> ! 			   NULL);
> ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> ! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
> ! 				       generation);
> ! 	  debug_str_dwo_section = get_section (DEBUG_LTO_STR_DWO_SECTION,
> ! 					       DEBUG_STR_DWO_SECTION_FLAGS, NULL);
> ! 	  debug_macinfo_section_name
> ! 	    = (dwarf_strict
> ! 	       ? DEBUG_LTO_DWO_MACINFO_SECTION : DEBUG_LTO_DWO_MACRO_SECTION);
> ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> ! 					       SECTION_DEBUG | SECTION_EXCLUDE,
> ! 					       NULL);
> ! 	}
> !       debug_str_section = get_section (DEBUG_LTO_STR_SECTION,
> ! 				       DEBUG_STR_SECTION_FLAGS
> ! 				       | SECTION_EXCLUDE, NULL);
>       }
>     else
>       {
> !       if (!dwarf_split_debug_info)
> ! 	{
> ! 	  debug_info_section = get_section (DEBUG_INFO_SECTION,
> ! 					    SECTION_DEBUG, NULL);
> ! 	  debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> ! 					      SECTION_DEBUG, NULL);
> ! 	  debug_loc_section = get_section (DEBUG_LOC_SECTION,
> ! 					   SECTION_DEBUG, NULL);
> ! 	  debug_macinfo_section_name
> ! 	      = dwarf_strict ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
> ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> ! 					       SECTION_DEBUG, NULL);
> ! 	}
> !       else
> ! 	{
> ! 	  debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
> ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> ! 					    NULL);
> ! 	  debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
> ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> ! 					      NULL);
> ! 	  debug_addr_section = get_section (DEBUG_ADDR_SECTION,
> ! 					    SECTION_DEBUG, NULL);
> ! 	  debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
> ! 						     SECTION_DEBUG, NULL);
> ! 	  debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> ! 						       SECTION_DEBUG, NULL);
> ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> ! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
> ! 				       generation);
> ! 
> ! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections
> ! 	     stay in the main .o, but the skeleton_line goes into the
> ! 	     split off dwo.  */
> ! 	  debug_skeleton_line_section
> ! 	      = get_section (DEBUG_DWO_LINE_SECTION,
> ! 			     SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> ! 				       generation);
> ! 	  debug_str_offsets_section
> ! 	    = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
> ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> ! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
> ! 				       generation);
> ! 	  debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION,
>   					   SECTION_DEBUG | SECTION_EXCLUDE,
>   					   NULL);
> ! 	  debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
> ! 					       DEBUG_STR_DWO_SECTION_FLAGS,
> ! 					       NULL);
> ! 	  debug_macinfo_section_name
> ! 	    = (dwarf_strict && dwarf_version < 5)
> ! 	      ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
> ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> ! 					       SECTION_DEBUG | SECTION_EXCLUDE,
> ! 					       NULL);
> ! 	}
> !       debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
> ! 					   SECTION_DEBUG, NULL);
> !       debug_line_section = get_section (DEBUG_LINE_SECTION,
>   					SECTION_DEBUG, NULL);
> !       debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
> ! 					    SECTION_DEBUG, NULL);
> !       debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
> ! 					    SECTION_DEBUG, NULL);
> !       debug_str_section = get_section (DEBUG_STR_SECTION,
> ! 				       DEBUG_STR_SECTION_FLAGS, NULL);
> !       debug_ranges_section = get_section (dwarf_version >= 5
> ! 					  ? DEBUG_RNGLISTS_SECTION
> ! 					  : DEBUG_RANGES_SECTION,
> ! 					  SECTION_DEBUG, NULL);
> !       debug_frame_section = get_section (DEBUG_FRAME_SECTION,
> ! 					 SECTION_DEBUG, NULL);
> !     }
>   
>     ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
> ! 			       DEBUG_ABBREV_SECTION_LABEL, generation);
>     ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
> ! 			       DEBUG_INFO_SECTION_LABEL, generation);
> !   info_section_emitted = false;
>     ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
> ! 			       DEBUG_LINE_SECTION_LABEL, generation);
>     ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
> ! 			       DEBUG_RANGES_SECTION_LABEL, generation);
>     if (dwarf_version >= 5 && dwarf_split_debug_info)
>       ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
> ! 				 DEBUG_RANGES_SECTION_LABEL, 2 + generation);
>     ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
> !                                DEBUG_ADDR_SECTION_LABEL, generation);
>     ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
>   			       (dwarf_strict && dwarf_version < 5)
>   			       ? DEBUG_MACINFO_SECTION_LABEL
> ! 			       : DEBUG_MACRO_SECTION_LABEL, generation);
> !   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL,
> ! 			       generation);
> ! 
> !   ++generation;
>   }
>   
>   /* Set up for Dwarf output at the start of compilation.  */
> *************** flush_limbo_die_list (void)
> *** 29641,29646 ****
> --- 30026,30047 ----
>       }
>   }
>   
> + /* Reset DIEs so we can output them again.  */
> + 
> + static void
> + reset_dies (dw_die_ref die)
> + {
> +   dw_die_ref c;
> + 
> +   /* Remove stuff we re-generate.  */
> +   die->die_mark = 0;
> +   die->die_offset = 0;
> +   die->die_abbrev = 0;
> +   remove_AT (die, DW_AT_sibling);
> + 
> +   FOR_EACH_CHILD (die, c, reset_dies (c));
> + }
> + 
>   /* Output stuff that dwarf requires at the end of every file,
>      and generate the DWARF-2 debugging info.  */
>   
> *************** dwarf2out_finish (const char *)
> *** 29667,29672 ****
> --- 30068,30113 ----
>   
>     gen_remaining_tmpl_value_param_die_attribute ();
>   
> +   if (flag_generate_lto)
> +     {
> +       gcc_assert (flag_fat_lto_objects);
> + 
> +       /* Prune stuff so that dwarf2out_finish runs successfully
> + 	 for the fat part of the object.  */
> +       reset_dies (comp_unit_die ());
> +       for (limbo_die_node *node = cu_die_list; node; node = node->next)
> + 	reset_dies (node->die);
> + 
> +       hash_table<comdat_type_hasher> comdat_type_table (100);
> +       for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
> + 	{
> + 	  comdat_type_node **slot
> + 	      = comdat_type_table.find_slot (ctnode, INSERT);
> + 
> + 	  /* Don't reset types twice.  */
> + 	  if (*slot != HTAB_EMPTY_ENTRY)
> + 	    continue;
> + 
> + 	  /* Add a pointer to the line table for the main compilation unit
> + 	     so that the debugger can make sense of DW_AT_decl_file
> + 	     attributes.  */
> + 	  if (debug_info_level >= DINFO_LEVEL_TERSE)
> + 	    reset_dies (ctnode->root_die);
> + 
> + 	  *slot = ctnode;
> + 	}
> + 
> +       /* Reset die CU symbol so we don't output it twice.  */
> +       comp_unit_die ()->die_id.die_symbol = NULL;
> + 
> +       /* Remove DW_AT_macro from the early output.  */
> +       if (have_macinfo)
> + 	remove_AT (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE);
> + 
> +       /* Remove indirect string decisions.  */
> +       debug_str_hash->traverse<void *, reset_indirect_string> (NULL);
> +     }
> + 
>   #if ENABLE_ASSERT_CHECKING
>     {
>       dw_die_ref die = comp_unit_die (), c;
> *************** dwarf2out_finish (const char *)
> *** 29677,29683 ****
>     move_marked_base_types ();
>   
>     /* Initialize sections and labels used for actual assembler output.  */
> !   init_sections_and_labels ();
>   
>     /* Traverse the DIE's and add sibling attributes to those DIE's that
>        have children.  */
> --- 30118,30124 ----
>     move_marked_base_types ();
>   
>     /* Initialize sections and labels used for actual assembler output.  */
> !   init_sections_and_labels (false);
>   
>     /* Traverse the DIE's and add sibling attributes to those DIE's that
>        have children.  */
> *************** dwarf2out_finish (const char *)
> *** 29772,29780 ****
>   		    debug_line_section_label);
>   
>     if (have_macinfo)
> !     add_AT_macptr (comp_unit_die (),
> ! 		   dwarf_version >= 5 ? DW_AT_macros
> ! 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
>   		   macinfo_section_label);
>   
>     if (dwarf_split_debug_info)
> --- 30213,30219 ----
>   		    debug_line_section_label);
>   
>     if (have_macinfo)
> !     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
>   		   macinfo_section_label);
>   
>     if (dwarf_split_debug_info)
> *************** dwarf2out_finish (const char *)
> *** 29979,29985 ****
>       {
>         switch_to_section (debug_macinfo_section);
>         ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> !       output_macinfo ();
>         dw2_asm_output_data (1, 0, "End compilation unit");
>       }
>   
> --- 30418,30425 ----
>       {
>         switch_to_section (debug_macinfo_section);
>         ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> !       output_macinfo (!dwarf_split_debug_info ? debug_line_section_label
> ! 		      : debug_skeleton_line_section_label, false);
>         dw2_asm_output_data (1, 0, "End compilation unit");
>       }
>   
> *************** note_variable_value_in_expr (dw_die_ref
> *** 30200,30205 ****
> --- 30640,30659 ----
>         {
>   	tree decl = loc->dw_loc_oprnd1.v.val_decl_ref;
>   	dw_die_ref ref = lookup_decl_die (decl);
> + 	if (! ref && flag_generate_lto)
> + 	  {
> + 	    /* ???  This is somewhat a hack because we do not create DIEs
> + 	       for variables not in BLOCK trees early but when generating
> + 	       early LTO output we need the dw_val_class_decl_ref to be
> + 	       fully resolved.  For fat LTO objects we'd also like to
> + 	       undo this after LTO dwarf output.  */
> + 	    gcc_assert (DECL_CONTEXT (decl));
> + 	    dw_die_ref ctx = lookup_decl_die (DECL_CONTEXT (decl));
> + 	    gcc_assert (ctx != NULL);
> + 	    gen_decl_die (decl, NULL_TREE, NULL, ctx);
> + 	    ref = lookup_decl_die (decl);
> + 	    gcc_assert (ref != NULL);
> + 	  }
>   	if (ref)
>   	  {
>   	    loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
> *************** dwarf2out_early_finish (const char *file
> *** 30410,30415 ****
> --- 30864,30982 ----
>   
>     /* The early debug phase is now finished.  */
>     early_dwarf_finished = true;
> + 
> +   /* Do not generate DWARF assembler now when not producing LTO bytecode.  */
> +   if (!flag_generate_lto)
> +     return;
> + 
> +   /* Now as we are going to output for LTO initialize sections and labels
> +      to the LTO variants.  We don't need a random-seed postfix as other
> +      LTO sections as linking the LTO debug sections into one in a partial
> +      link is fine.  */
> +   init_sections_and_labels (true);
> + 
> +   /* The output below is modeled after dwarf2out_finish with all
> +      location related output removed and some LTO specific changes.
> +      Some refactoring might make both smaller and easier to match up.  */
> + 
> +   /* Traverse the DIE's and add add sibling attributes to those DIE's
> +      that have children.  */
> +   add_sibling_attributes (comp_unit_die ());
> +   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
> +     add_sibling_attributes (node->die);
> +   for (comdat_type_node *ctnode = comdat_type_list;
> +        ctnode != NULL; ctnode = ctnode->next)
> +     add_sibling_attributes (ctnode->root_die);
> + 
> +   if (have_macinfo)
> +     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
> + 		   macinfo_section_label);
> + 
> +   save_macinfo_strings ();
> + 
> +   /* Output all of the compilation units.  We put the main one last so that
> +      the offsets are available to output_pubnames.  */
> +   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
> +     output_comp_unit (node->die, 0, NULL);
> + 
> +   hash_table<comdat_type_hasher> comdat_type_table (100);
> +   for (comdat_type_node *ctnode = comdat_type_list;
> +        ctnode != NULL; ctnode = ctnode->next)
> +     {
> +       comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT);
> + 
> +       /* Don't output duplicate types.  */
> +       if (*slot != HTAB_EMPTY_ENTRY)
> +         continue;
> + 
> +       /* Add a pointer to the line table for the main compilation unit
> +          so that the debugger can make sense of DW_AT_decl_file
> +          attributes.  */
> +       if (debug_info_level >= DINFO_LEVEL_TERSE)
> +         add_AT_lineptr (ctnode->root_die, DW_AT_stmt_list,
> +                         (!dwarf_split_debug_info
> +                          ? debug_line_section_label
> +                          : debug_skeleton_line_section_label));
> + 
> +       output_comdat_type_unit (ctnode);
> +       *slot = ctnode;
> +     }
> + 
> +   /* The AT_pubnames attribute needs to go in all skeleton dies, including
> +      both the main_cu and all skeleton TUs.  Making this call unconditional
> +      would end up either adding a second copy of the AT_pubnames attribute, or
> +      requiring a special case in add_top_level_skeleton_die_attrs.  */
> +   if (!dwarf_split_debug_info)
> +     add_AT_pubnames (comp_unit_die ());
> + 
> +   /* Stick a unique symbol to the main debuginfo section.  */
> +   compute_section_prefix_1 (comp_unit_die (), false);
> + 
> +   /* Output the main compilation unit.  We always need it if only for
> +      the CU symbol.  */
> +   output_comp_unit (comp_unit_die (), true, NULL);
> + 
> +   /* Output the abbreviation table.  */
> +   if (vec_safe_length (abbrev_die_table) != 1)
> +     {
> +       switch_to_section (debug_abbrev_section);
> +       ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
> +       output_abbrev_section ();
> +     }
> + 
> +   /* Have to end the macro section.  */
> +   if (have_macinfo)
> +     {
> +       /* We have to save macinfo state if we need to output it again
> + 	 for the FAT part of the object.  */
> +       vec<macinfo_entry, va_gc> *saved_macinfo_table = macinfo_table;
> +       if (flag_fat_lto_objects)
> + 	macinfo_table = macinfo_table->copy ();
> + 
> +       switch_to_section (debug_macinfo_section);
> +       ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> +       output_macinfo (debug_skeleton_line_section_label, true);
> +       dw2_asm_output_data (1, 0, "End compilation unit");
> + 
> +       /* Emit a skeleton debug_line section.  */
> +       switch_to_section (debug_skeleton_line_section);
> +       ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_line_section_label);
> +       output_line_info (true);
> + 
> +       if (flag_fat_lto_objects)
> + 	{
> + 	  vec_free (macinfo_table);
> + 	  macinfo_table = saved_macinfo_table;
> + 	}
> +     }
> + 
> + 
> +   /* If we emitted any indirect strings, output the string table too.  */
> +   if (debug_str_hash || skeleton_debug_str_hash)
> +     output_indirect_strings ();
> + 
> +   /* Switch back to the text section.  */
> +   switch_to_section (text_section);
>   }
>   
>   /* Reset all state within dwarf2out.c so that we can rerun the compiler
> Index: early-lto-debug/gcc/debug.h
> ===================================================================
> *** early-lto-debug.orig/gcc/debug.h	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/debug.h	2017-05-16 13:10:49.774239353 +0200
> *************** struct gcc_debug_hooks
> *** 147,152 ****
> --- 147,160 ----
>     void (* imported_module_or_decl) (tree decl, tree name,
>   				    tree context, bool child);
>   
> +   /* Return true if a DIE for the tree is available and return a symbol
> +      and offset that can be used to refer to it externally.  */
> +   bool (* die_ref_for_decl) (tree, const char **, unsigned HOST_WIDE_INT *);
> + 
> +   /* Early debug information for the tree is available at symbol plus
> +      offset externally.  */
> +   void (* register_external_die) (tree, const char *, unsigned HOST_WIDE_INT);
> + 
>     /* DECL is an inline function, whose body is present, but which is
>        not being output at this point.  */
>     void (* deferred_inline_function) (tree decl);
> *************** extern void debug_nothing_tree_tree_tree
> *** 210,215 ****
> --- 218,227 ----
>   extern bool debug_true_const_tree (const_tree);
>   extern void debug_nothing_rtx_insn (rtx_insn *);
>   extern void debug_nothing_rtx_code_label (rtx_code_label *);
> + extern bool debug_false_tree_charstarstar_uhwistar (tree, const char **,
> + 						    unsigned HOST_WIDE_INT *);
> + extern void debug_nothing_tree_charstar_uhwi (tree, const char *,
> + 					      unsigned HOST_WIDE_INT);
>   
>   /* Hooks for various debug formats.  */
>   extern const struct gcc_debug_hooks do_nothing_debug_hooks;
> Index: early-lto-debug/gcc/debug.c
> ===================================================================
> *** early-lto-debug.orig/gcc/debug.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/debug.c	2017-05-16 13:10:49.774239353 +0200
> *************** const struct gcc_debug_hooks do_nothing_
> *** 48,53 ****
> --- 48,55 ----
>     debug_nothing_tree,	         	 /* late_global_decl */
>     debug_nothing_tree_int,		 /* type_decl */
>     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
>     debug_nothing_tree,		         /* deferred_inline_function */
>     debug_nothing_tree,		         /* outlining_inline_function */
>     debug_nothing_rtx_code_label,	         /* label */
> *************** debug_nothing_tree_int (tree decl ATTRIB
> *** 146,148 ****
> --- 148,163 ----
>   			int local ATTRIBUTE_UNUSED)
>   {
>   }
> + 
> + bool
> + debug_false_tree_charstarstar_uhwistar (tree, const char **,
> + 					unsigned HOST_WIDE_INT *)
> + {
> +   return false;
> + }
> + 
> + void
> + debug_nothing_tree_charstar_uhwi (tree, const char *,
> + 				  unsigned HOST_WIDE_INT)
> + {
> + }
> Index: early-lto-debug/gcc/dbxout.c
> ===================================================================
> *** early-lto-debug.orig/gcc/dbxout.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/dbxout.c	2017-05-16 13:10:49.778239419 +0200
> *************** const struct gcc_debug_hooks dbx_debug_h
> *** 372,377 ****
> --- 372,379 ----
>     dbxout_late_global_decl,		 /* late_global_decl */
>     dbxout_type_decl,			 /* type_decl */
>     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
>     debug_nothing_tree,		         /* deferred_inline_function */
>     debug_nothing_tree,		         /* outlining_inline_function */
>     debug_nothing_rtx_code_label,	         /* label */
> *************** const struct gcc_debug_hooks xcoff_debug
> *** 412,417 ****
> --- 414,421 ----
>     dbxout_late_global_decl,		 /* late_global_decl */
>     dbxout_type_decl,			 /* type_decl */
>     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> +   debug_nothing_tree_charstar_uhwi,      /* register_external_die */
>     debug_nothing_tree,		         /* deferred_inline_function */
>     debug_nothing_tree,		         /* outlining_inline_function */
>     debug_nothing_rtx_code_label,	         /* label */
> Index: early-lto-debug/gcc/sdbout.c
> ===================================================================
> *** early-lto-debug.orig/gcc/sdbout.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/sdbout.c	2017-05-16 13:10:49.778239419 +0200
> *************** const struct gcc_debug_hooks sdb_debug_h
> *** 302,307 ****
> --- 302,309 ----
>     sdbout_late_global_decl,		 /* late_global_decl */
>     sdbout_symbol,			 /* type_decl */
>     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
>     debug_nothing_tree,		         /* deferred_inline_function */
>     debug_nothing_tree,		         /* outlining_inline_function */
>     sdbout_label,			         /* label */
> Index: early-lto-debug/gcc/lto/lto.c
> ===================================================================
> *** early-lto-debug.orig/gcc/lto/lto.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/lto/lto.c	2017-05-16 13:10:49.778239419 +0200
> *************** unify_scc (struct data_in *data_in, unsi
> *** 1632,1637 ****
> --- 1632,1640 ----
>   	      free_node (scc->entries[i]);
>   	    }
>   
> + 	  /* Drop DIE references.  */
> + 	  dref_queue.truncate (0);
> + 
>   	  break;
>   	}
>   
> *************** lto_read_decls (struct lto_file_decl_dat
> *** 1707,1714 ****
>   						     from);
>   	  if (len == 1
>   	      && (TREE_CODE (first) == IDENTIFIER_NODE
> ! 		  || TREE_CODE (first) == INTEGER_CST
> ! 		  || TREE_CODE (first) == TRANSLATION_UNIT_DECL))
>   	    continue;
>   
>   	  /* Try to unify the SCC with already existing ones.  */
> --- 1710,1716 ----
>   						     from);
>   	  if (len == 1
>   	      && (TREE_CODE (first) == IDENTIFIER_NODE
> ! 		  || TREE_CODE (first) == INTEGER_CST))
>   	    continue;
>   
>   	  /* Try to unify the SCC with already existing ones.  */
> *************** lto_read_decls (struct lto_file_decl_dat
> *** 1747,1762 ****
>   	      if (TREE_CODE (t) == INTEGER_CST
>   		  && !TREE_OVERFLOW (t))
>   		cache_integer_cst (t);
> - 	      /* Register TYPE_DECLs with the debuginfo machinery.  */
> - 	      if (!flag_wpa
> - 		  && TREE_CODE (t) == TYPE_DECL)
> - 		{
> - 		  /* Dwarf2out needs location information.
> - 		     TODO: Moving this out of the streamer loop may noticealy
> - 		     improve ltrans linemap memory use.  */
> - 		  data_in->location_cache.apply_location_cache ();
> - 		  debug_hooks->type_decl (t, !DECL_FILE_SCOPE_P (t));
> - 		}
>   	      if (!flag_ltrans)
>   		{
>   		  /* Register variables and functions with the
> --- 1749,1754 ----
> *************** lto_read_decls (struct lto_file_decl_dat
> *** 1772,1777 ****
> --- 1764,1777 ----
>   		    vec_safe_push (tree_with_vars, t);
>   		}
>   	    }
> + 
> + 	  /* Register DECLs with the debuginfo machinery.  */
> + 	  while (!dref_queue.is_empty ())
> + 	    {
> + 	      dref_entry e = dref_queue.pop ();
> + 	      debug_hooks->register_external_die (e.decl, e.sym, e.off);
> + 	    }
> + 
>   	  if (seen_type)
>   	    num_type_scc_trees += len;
>   	}
> *************** lto_section_with_id (const char *name, u
> *** 1951,1957 ****
>     if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
>       return 0;
>     s = strrchr (name, '.');
> !   return s && sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
>   }
>   
>   /* Create file_data of each sub file id */
> --- 1951,1962 ----
>     if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
>       return 0;
>     s = strrchr (name, '.');
> !   if (!s)
> !     return 0;
> !   /* If the section is not suffixed with an ID return.  */
> !   if ((size_t)(s - name) == strlen (section_name_prefix))
> !     return 0;
> !   return sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
>   }
>   
>   /* Create file_data of each sub file id */
> Index: early-lto-debug/gcc/lto-streamer-in.c
> ===================================================================
> *** early-lto-debug.orig/gcc/lto-streamer-in.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/lto-streamer-in.c	2017-05-16 13:10:49.858240736 +0200
> *************** along with GCC; see the file COPYING3.
> *** 41,46 ****
> --- 41,47 ----
>   #include "except.h"
>   #include "cgraph.h"
>   #include "cfgloop.h"
> + #include "debug.h"
>   
>   
>   struct freeing_string_slot_hasher : string_slot_hasher
> *************** input_function (tree fn_decl, struct dat
> *** 1038,1043 ****
> --- 1039,1054 ----
>     DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in);
>     DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in);
>   
> +   /* Read debug args if available.  */
> +   unsigned n_debugargs = streamer_read_uhwi (ib);
> +   if (n_debugargs)
> +     {
> +       vec<tree, va_gc> **debugargs = decl_debug_args_insert (fn_decl);
> +       vec_safe_grow (*debugargs, n_debugargs);
> +       for (unsigned i = 0; i < n_debugargs; ++i)
> + 	(**debugargs)[i] = stream_read_tree (ib, data_in);
> +     }
> + 
>     /* Read the tree of lexical scopes for the function.  */
>     DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
>     unsigned block_leaf_count = streamer_read_uhwi (ib);
> *************** lto_input_variable_constructor (struct l
> *** 1318,1323 ****
> --- 1329,1338 ----
>   }
>   
>   
> + /* Queue of acummulated decl -> DIE mappings.  Similar to locations those
> +    are only applied to prevailing tree nodes during tree merging.  */
> + vec<dref_entry> dref_queue;
> + 
>   /* Read the physical representation of a tree node EXPR from
>      input block IB using the per-file context in DATA_IN.  */
>   
> *************** lto_read_tree_1 (struct lto_input_block
> *** 1337,1342 ****
> --- 1352,1374 ----
>         && TREE_CODE (expr) != FUNCTION_DECL
>         && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
>       DECL_INITIAL (expr) = stream_read_tree (ib, data_in);
> + 
> +   /* Stream references to early generated DIEs.  Keep in sync with the
> +      trees handled in dwarf2out_register_external_die.  */
> +   if ((DECL_P (expr)
> +        && TREE_CODE (expr) != FIELD_DECL
> +        && TREE_CODE (expr) != DEBUG_EXPR_DECL
> +        && TREE_CODE (expr) != TYPE_DECL)
> +       || TREE_CODE (expr) == BLOCK)
> +     {
> +       const char *str = streamer_read_string (data_in, ib);
> +       if (str)
> + 	{
> + 	  unsigned HOST_WIDE_INT off = streamer_read_uhwi (ib);
> + 	  dref_entry e = { expr, str, off };
> + 	  dref_queue.safe_push (e);
> + 	}
> +     }
>   }
>   
>   /* Read the physical representation of a tree node with tag TAG from
> *************** lto_input_tree (struct lto_input_block *
> *** 1482,1487 ****
> --- 1514,1526 ----
>       {
>         unsigned len, entry_len;
>         lto_input_scc (ib, data_in, &len, &entry_len);
> + 
> +       /* Register DECLs with the debuginfo machinery.  */
> +       while (!dref_queue.is_empty ())
> + 	{
> + 	  dref_entry e = dref_queue.pop ();
> + 	  debug_hooks->register_external_die (e.decl, e.sym, e.off);
> + 	}
>       }
>     return lto_input_tree_1 (ib, data_in, tag, 0);
>   }
> Index: early-lto-debug/gcc/lto-streamer-out.c
> ===================================================================
> *** early-lto-debug.orig/gcc/lto-streamer-out.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/lto-streamer-out.c	2017-05-16 13:10:49.858240736 +0200
> *************** along with GCC; see the file COPYING3.
> *** 40,45 ****
> --- 40,46 ----
>   #include "cfgloop.h"
>   #include "builtins.h"
>   #include "gomp-constants.h"
> + #include "debug.h"
>   
>   
>   static void lto_write_tree (struct output_block*, tree, bool);
> *************** lto_write_tree_1 (struct output_block *o
> *** 406,411 ****
> --- 407,432 ----
>   			 (ob->decl_state->symtab_node_encoder, expr);
>         stream_write_tree (ob, initial, ref_p);
>       }
> + 
> +   /* Stream references to early generated DIEs.  Keep in sync with the
> +      trees handled in dwarf2out_die_ref_for_decl.  */
> +   if ((DECL_P (expr)
> +        && TREE_CODE (expr) != FIELD_DECL
> +        && TREE_CODE (expr) != DEBUG_EXPR_DECL
> +        && TREE_CODE (expr) != TYPE_DECL)
> +       || TREE_CODE (expr) == BLOCK)
> +     {
> +       const char *sym;
> +       unsigned HOST_WIDE_INT off;
> +       if (debug_info_level > DINFO_LEVEL_NONE
> + 	  && debug_hooks->die_ref_for_decl (expr, &sym, &off))
> + 	{
> + 	  streamer_write_string (ob, ob->main_stream, sym, true);
> + 	  streamer_write_uhwi (ob, off);
> + 	}
> +       else
> + 	streamer_write_string (ob, ob->main_stream, NULL, true);
> +     }
>   }
>   
>   /* Write a physical representation of tree node EXPR to output block
> *************** DFS::DFS_write_tree_body (struct output_
> *** 745,751 ****
>   	;
>         else
>   	DFS_follow_tree_edge (DECL_NAME (expr));
> !       DFS_follow_tree_edge (DECL_CONTEXT (expr));
>       }
>   
>     if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> --- 766,776 ----
>   	;
>         else
>   	DFS_follow_tree_edge (DECL_NAME (expr));
> !       if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
> ! 	  && ! DECL_CONTEXT (expr))
> ! 	DFS_follow_tree_edge ((*all_translation_units)[0]);
> !       else
> ! 	DFS_follow_tree_edge (DECL_CONTEXT (expr));
>       }
>   
>     if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> *************** DFS::DFS_write_tree_body (struct output_
> *** 765,770 ****
> --- 790,796 ----
>   	 declarations which should be eliminated by decl merging. Be sure none
>   	 leaks to this point.  */
>         gcc_assert (DECL_ABSTRACT_ORIGIN (expr) != error_mark_node);
> +       DFS_follow_tree_edge (DECL_ABSTRACT_ORIGIN (expr));
>   
>         if ((VAR_P (expr)
>   	   || TREE_CODE (expr) == PARM_DECL)
> *************** output_function (struct cgraph_node *nod
> *** 2061,2066 ****
> --- 2087,2103 ----
>     stream_write_tree (ob, DECL_RESULT (function), true);
>     streamer_write_chain (ob, DECL_ARGUMENTS (function), true);
>   
> +   /* Output debug args if available. */
> +   vec<tree, va_gc> **debugargs = decl_debug_args_lookup (function);
> +   if (! debugargs)
> +     streamer_write_uhwi (ob, 0);
> +   else
> +     {
> +       streamer_write_uhwi (ob, (*debugargs)->length ());
> +       for (unsigned i = 0; i < (*debugargs)->length (); ++i)
> + 	stream_write_tree (ob, (**debugargs)[i], true);
> +     }
> + 
>     /* Output DECL_INITIAL for the function, which contains the tree of
>        lexical scopes.  */
>     stream_write_tree (ob, DECL_INITIAL (function), true);
> Index: early-lto-debug/gcc/lto-streamer.h
> ===================================================================
> *** early-lto-debug.orig/gcc/lto-streamer.h	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/lto-streamer.h	2017-05-16 13:10:49.858240736 +0200
> *************** DEFINE_DECL_STREAM_FUNCS (TYPE_DECL, typ
> *** 1212,1215 ****
> --- 1212,1225 ----
>   DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl)
>   DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl)
>   
> + /* Entry for the delayed registering of decl -> DIE references.  */
> + struct dref_entry {
> +     tree decl;
> +     const char *sym;
> +     unsigned HOST_WIDE_INT off;
> + };
> + 
> + extern vec<dref_entry> dref_queue;
> + 
> + 
>   #endif /* GCC_LTO_STREAMER_H  */
> Index: early-lto-debug/gcc/lto-wrapper.c
> ===================================================================
> *** early-lto-debug.orig/gcc/lto-wrapper.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/lto-wrapper.c	2017-05-16 13:10:49.858240736 +0200
> *************** static char **output_names;
> *** 70,75 ****
> --- 70,76 ----
>   static char **offload_names;
>   static char *offload_objects_file_name;
>   static char *makefile;
> + static char *debug_obj;
>   
>   const char tool_name[] = "lto-wrapper";
>   
> *************** tool_cleanup (bool)
> *** 88,93 ****
> --- 89,96 ----
>       maybe_unlink (offload_objects_file_name);
>     if (makefile)
>       maybe_unlink (makefile);
> +   if (debug_obj)
> +     maybe_unlink (debug_obj);
>     for (i = 0; i < nr; ++i)
>       {
>         maybe_unlink (input_names[i]);
> *************** find_and_merge_options (int fd, off_t fi
> *** 938,943 ****
> --- 941,1007 ----
>     return true;
>   }
>   
> + /* Copy early debug info sections from INFILE to a new file whose name
> +    is returned.  Return NULL on error.  */
> + 
> + const char *
> + debug_objcopy (const char *infile)
> + {
> +   const char *outfile;
> +   const char *errmsg;
> +   int err;
> + 
> +   const char *p;
> +   off_t inoff = 0;
> +   long loffset;
> +   int consumed;
> +   if ((p = strrchr (infile, '@'))
> +       && p != infile
> +       && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
> +       && strlen (p) == (unsigned int) consumed)
> +     {
> +       char *fname = xstrdup (infile);
> +       fname[p - infile] = '\0';
> +       infile = fname;
> +       inoff = (off_t) loffset;
> +     }
> +   int infd = open (infile, O_RDONLY);
> +   if (infd == -1)
> +     return NULL;
> +   simple_object_read *inobj = simple_object_start_read (infd, inoff,
> + 							"__GNU_LTO",
> + 							&errmsg, &err);
> +   if (!inobj)
> +     return NULL;
> + 
> +   off_t off, len;
> +   if (simple_object_find_section (inobj, ".gnu.debuglto_.debug_info",
> + 				  &off, &len, &errmsg, &err) != 1)
> +     {
> +       if (errmsg)
> + 	fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
> + 
> +       simple_object_release_read (inobj);
> +       close (infd);
> +       return NULL;
> +     }
> + 
> +   outfile = make_temp_file ("debugobjtem");
> +   errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err);
> +   if (errmsg)
> +     {
> +       unlink_if_ordinary (outfile);
> +       fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
> +     }
> + 
> +   simple_object_release_read (inobj);
> +   close (infd);
> + 
> +   return outfile;
> + }
> + 
> + 
> + 
>   /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
>   
>   static void
> *************** run_gcc (unsigned argc, char *argv[])
> *** 962,969 ****
>     int new_head_argc;
>     bool have_lto = false;
>     bool have_offload = false;
> !   unsigned lto_argc = 0;
> !   char **lto_argv;
>   
>     /* Get the driver and options.  */
>     collect_gcc = getenv ("COLLECT_GCC");
> --- 1026,1035 ----
>     int new_head_argc;
>     bool have_lto = false;
>     bool have_offload = false;
> !   unsigned lto_argc = 0, ltoobj_argc = 0;
> !   char **lto_argv, **ltoobj_argv;
> !   bool skip_debug = false;
> !   unsigned n_debugobj;
>   
>     /* Get the driver and options.  */
>     collect_gcc = getenv ("COLLECT_GCC");
> *************** run_gcc (unsigned argc, char *argv[])
> *** 982,987 ****
> --- 1048,1054 ----
>     /* Allocate array for input object files with LTO IL,
>        and for possible preceding arguments.  */
>     lto_argv = XNEWVEC (char *, argc);
> +   ltoobj_argv = XNEWVEC (char *, argc);
>   
>     /* Look at saved options in the IL files.  */
>     for (i = 1; i < argc; ++i)
> *************** run_gcc (unsigned argc, char *argv[])
> *** 1024,1030 ****
>   				  collect_gcc))
>   	{
>   	  have_lto = true;
> ! 	  lto_argv[lto_argc++] = argv[i];
>   	}
>         close (fd);
>       }
> --- 1091,1097 ----
>   				  collect_gcc))
>   	{
>   	  have_lto = true;
> ! 	  ltoobj_argv[ltoobj_argc++] = argv[i];
>   	}
>         close (fd);
>       }
> *************** run_gcc (unsigned argc, char *argv[])
> *** 1085,1090 ****
> --- 1152,1168 ----
>   	}
>       }
>   
> +   /* Output lto-wrapper invocation command.  */
> +   if (verbose)
> +     {
> +       for (i = 0; i < argc; ++i)
> + 	{
> + 	  fputs (argv[i], stderr);
> + 	  fputc (' ', stderr);
> + 	}
> +       fputc ('\n', stderr);
> +     }
> + 
>     if (no_partition)
>       {
>         lto_mode = LTO_MODE_LTO;
> *************** cont1:
> *** 1274,1291 ****
>           obstack_ptr_grow (&argv_obstack, "-fwpa");
>       }
>   
> !   /* Append the input objects and possible preceding arguments.  */
>     for (i = 0; i < lto_argc; ++i)
>       obstack_ptr_grow (&argv_obstack, lto_argv[i]);
>     obstack_ptr_grow (&argv_obstack, NULL);
>   
>     new_argv = XOBFINISH (&argv_obstack, const char **);
>     argv_ptr = &new_argv[new_head_argc];
>     fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
>   
>     if (lto_mode == LTO_MODE_LTO)
>       {
>         printf ("%s\n", flto_out);
>         free (flto_out);
>         flto_out = NULL;
>       }
> --- 1352,1456 ----
>           obstack_ptr_grow (&argv_obstack, "-fwpa");
>       }
>   
> !   /* Append input arguments.  */
>     for (i = 0; i < lto_argc; ++i)
>       obstack_ptr_grow (&argv_obstack, lto_argv[i]);
> +   /* Append the input objects.  */
> +   for (i = 0; i < ltoobj_argc; ++i)
> +     obstack_ptr_grow (&argv_obstack, ltoobj_argv[i]);
>     obstack_ptr_grow (&argv_obstack, NULL);
>   
>     new_argv = XOBFINISH (&argv_obstack, const char **);
>     argv_ptr = &new_argv[new_head_argc];
>     fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
>   
> +   /* Handle early generated debug information.  At compile-time
> +      we output early DWARF debug info into .gnu.debuglto_ prefixed
> +      sections.  LTRANS object DWARF debug info refers to that.
> +      So we need to transfer the .gnu.debuglto_ sections to the final
> +      link.  Ideally the linker plugin interface would allow us to
> +      not claim those sections and instruct the linker to keep
> +      them, renaming them in the process.  For now we extract and
> +      rename those sections via a simple-object interface to produce
> +      regular objects containing only the early debug info.  We
> +      then partially link those to a single early debug info object
> +      and pass that as additional output back to the linker plugin.  */
> + 
> +   /* Prepare the partial link to gather the compile-time generated
> +      debug-info into a single input for the final link.  */
> +   debug_obj = make_temp_file ("debugobj");
> +   obstack_ptr_grow (&argv_obstack, collect_gcc);
> +   for (i = 1; i < decoded_options_count; ++i)
> +     {
> +       /* Retain linker choice and -B.  */
> +       if (decoded_options[i].opt_index == OPT_B
> + 	  || decoded_options[i].opt_index == OPT_fuse_ld_bfd
> + 	  || decoded_options[i].opt_index == OPT_fuse_ld_gold)
> + 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
> +       /* Retain all target options, this preserves -m32 for example.  */
> +       if (cl_options[decoded_options[i].opt_index].flags & CL_TARGET)
> + 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
> +       /* Recognize -g0.  */
> +       if (decoded_options[i].opt_index == OPT_g
> + 	  && strcmp (decoded_options[i].arg, "0") == 0)
> + 	skip_debug = true;
> +     }
> +   obstack_ptr_grow (&argv_obstack, "-r");
> +   obstack_ptr_grow (&argv_obstack, "-nostdlib");
> +   obstack_ptr_grow (&argv_obstack, "-o");
> +   obstack_ptr_grow (&argv_obstack, debug_obj);
> + 
> +   /* Copy the early generated debug info from the objects to temporary
> +      files and append those to the partial link commandline.  */
> +   n_debugobj = 0;
> +   if (! skip_debug)
> +     for (i = 0; i < ltoobj_argc; ++i)
> +       {
> + 	const char *tem;
> + 	if ((tem = debug_objcopy (ltoobj_argv[i])))
> + 	  {
> + 	    obstack_ptr_grow (&argv_obstack, tem);
> + 	    n_debugobj++;
> + 	  }
> +       }
> + 
> +   /* Link them all into a single object.  Ideally this would reduce
> +      disk space usage mainly due to .debug_str merging but unfortunately
> +      GNU ld doesn't perform this with -r.  */
> +   if (n_debugobj)
> +     {
> +       obstack_ptr_grow (&argv_obstack, NULL);
> +       const char **debug_link_argv = XOBFINISH (&argv_obstack, const char **);
> +       fork_execute (debug_link_argv[0],
> + 		    CONST_CAST (char **, debug_link_argv), false);
> + 
> +       /* And dispose the temporaries.  */
> +       for (i = 0; debug_link_argv[i]; ++i)
> + 	;
> +       for (--i; i > 0; --i)
> + 	{
> + 	  if (strcmp (debug_link_argv[i], debug_obj) == 0)
> + 	    break;
> + 	  maybe_unlink (debug_link_argv[i]);
> + 	}
> +     }
> +   else
> +     {
> +       unlink_if_ordinary (debug_obj);
> +       free (debug_obj);
> +       debug_obj = NULL;
> +       skip_debug = true;
> +     }
> + 
>     if (lto_mode == LTO_MODE_LTO)
>       {
>         printf ("%s\n", flto_out);
> +       if (!skip_debug)
> + 	{
> + 	  printf ("%s\n", debug_obj);
> + 	  free (debug_obj);
> + 	  debug_obj = NULL;
> + 	}
>         free (flto_out);
>         flto_out = NULL;
>       }
> *************** cont:
> *** 1434,1439 ****
> --- 1599,1610 ----
>   	  for (i = 0; i < nr; ++i)
>   	    maybe_unlink (input_names[i]);
>   	}
> +       if (!skip_debug)
> + 	{
> + 	  printf ("%s\n", debug_obj);
> + 	  free (debug_obj);
> + 	  debug_obj = NULL;
> + 	}
>         for (i = 0; i < nr; ++i)
>   	{
>   	  fputs (output_names[i], stdout);
> Index: early-lto-debug/gcc/tree-streamer-in.c
> ===================================================================
> *** early-lto-debug.orig/gcc/tree-streamer-in.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/tree-streamer-in.c	2017-05-16 13:10:49.862240801 +0200
> *************** lto_input_ts_decl_common_tree_pointers (
> *** 688,697 ****
>     DECL_SIZE (expr) = stream_read_tree (ib, data_in);
>     DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
>     DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
> ! 
> !   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
> !      for early inlining so drop it on the floor instead of ICEing in
> !      dwarf2out.c.  */
>   
>     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
>         && DECL_HAS_VALUE_EXPR_P (expr))
> --- 688,694 ----
>     DECL_SIZE (expr) = stream_read_tree (ib, data_in);
>     DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
>     DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
> !   DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
>   
>     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
>         && DECL_HAS_VALUE_EXPR_P (expr))
> Index: early-lto-debug/gcc/tree-streamer-out.c
> ===================================================================
> *** early-lto-debug.orig/gcc/tree-streamer-out.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/tree-streamer-out.c	2017-05-16 13:10:49.862240801 +0200
> *************** write_ts_decl_minimal_tree_pointers (str
> *** 566,572 ****
>       stream_write_tree (ob, NULL_TREE, ref_p);
>     else
>       stream_write_tree (ob, DECL_NAME (expr), ref_p);
> !   stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
>   }
>   
>   
> --- 566,576 ----
>       stream_write_tree (ob, NULL_TREE, ref_p);
>     else
>       stream_write_tree (ob, DECL_NAME (expr), ref_p);
> !   if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
> !       && ! DECL_CONTEXT (expr))
> !     stream_write_tree (ob, (*all_translation_units)[0], ref_p);
> !   else
> !     stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
>   }
>   
>   
> *************** write_ts_decl_common_tree_pointers (stru
> *** 585,594 ****
>        special handling in LTO, it must be handled by streamer hooks.  */
>   
>     stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
> ! 
> !   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
> !      for early inlining so drop it on the floor instead of ICEing in
> !      dwarf2out.c.  */
>   
>     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
>         && DECL_HAS_VALUE_EXPR_P (expr))
> --- 589,595 ----
>        special handling in LTO, it must be handled by streamer hooks.  */
>   
>     stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
> !   stream_write_tree (ob, DECL_ABSTRACT_ORIGIN (expr), ref_p);
>   
>     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
>         && DECL_HAS_VALUE_EXPR_P (expr))
> Index: early-lto-debug/gcc/config/darwin.c
> ===================================================================
> *** early-lto-debug.orig/gcc/config/darwin.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/config/darwin.c	2017-05-16 13:10:49.862240801 +0200
> *************** darwin_asm_lto_end (void)
> *** 1959,1965 ****
>   }
>   
>   static void
> ! darwin_asm_dwarf_section (const char *name, unsigned int flags, tree decl);
>   
>   /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
>   
> --- 1959,1966 ----
>   }
>   
>   static void
> ! darwin_asm_dwarf_section (const char *name, unsigned int flags,
> ! 			  tree decl, bool is_for_lto);
>   
>   /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
>   
> *************** darwin_asm_named_section (const char *na
> *** 2001,2007 ****
>         vec_safe_push (lto_section_names, e);
>      }
>     else if (strncmp (name, "__DWARF,", 8) == 0)
> !     darwin_asm_dwarf_section (name, flags, decl);
>     else
>       fprintf (asm_out_file, "\t.section %s\n", name);
>   }
> --- 2002,2010 ----
>         vec_safe_push (lto_section_names, e);
>      }
>     else if (strncmp (name, "__DWARF,", 8) == 0)
> !     darwin_asm_dwarf_section (name, flags, decl, false);
> !   else if (strncmp (name, "__GNU_DWARF_LTO,", 16) == 0)
> !     darwin_asm_dwarf_section (name, flags, decl, true);
>     else
>       fprintf (asm_out_file, "\t.section %s\n", name);
>   }
> *************** static GTY (()) vec<dwarf_sect_used_entr
> *** 2783,2801 ****
>   
>   static void
>   darwin_asm_dwarf_section (const char *name, unsigned int flags,
> ! 			  tree ARG_UNUSED (decl))
>   {
>     unsigned i;
> !   int namelen;
> !   const char * sname;
>     dwarf_sect_used_entry *ref;
>     bool found = false;
> !   gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
> ! 		    == (SECTION_DEBUG | SECTION_NAMED));
> !   /* We know that the name starts with __DWARF,  */
> !   sname = name + 8;
> !   namelen = strchr (sname, ',') - sname;
> !   gcc_assert (namelen);
>     if (dwarf_sect_names_table == NULL)
>       vec_alloc (dwarf_sect_names_table, 16);
>     else
> --- 2786,2822 ----
>   
>   static void
>   darwin_asm_dwarf_section (const char *name, unsigned int flags,
> ! 			  tree ARG_UNUSED (decl), bool is_for_lto)
>   {
>     unsigned i;
> !   int namelen, extra = 0;
> !   const char *sect, *lto_add = "";
> !   char sname[64];
>     dwarf_sect_used_entry *ref;
>     bool found = false;
> ! 
> !   gcc_checking_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
> ! 			== (SECTION_DEBUG | SECTION_NAMED));
> ! 
> !   /* We know that the name starts with __DWARF, or __GNU_DAWRF_LTO  */
> !   sect = strchr (name, ',') + 1;
> !   namelen = strchr (sect, ',') - sect;
> !   gcc_checking_assert (namelen);
> ! 
> !   /* The section switch is output as written...  */
> !   fprintf (asm_out_file, "\t.section %s\n", name);
> ! 
> !   /* ... but the string we keep to make section start labels needs
> !      adjustment for lto cases.  */
> !   if (is_for_lto)
> !     {
> !       lto_add = "_lto";
> !       extra = 4;
> !     }
> ! 
> !   snprintf (sname, 64, "%.*s%.*s", namelen, sect, extra, lto_add);
> !   namelen += extra;
> ! 
>     if (dwarf_sect_names_table == NULL)
>       vec_alloc (dwarf_sect_names_table, 16);
>     else
> *************** darwin_asm_dwarf_section (const char *na
> *** 2813,2819 ****
>   	  }
>         }
>   
> -   fprintf (asm_out_file, "\t.section %s\n", name);
>     if (!found)
>       {
>         dwarf_sect_used_entry e;
> --- 2834,2839 ----
> *************** darwin_asm_output_dwarf_offset (FILE *fi
> *** 2866,2879 ****
>   				HOST_WIDE_INT offset, section *base)
>   {
>     char sname[64];
> !   int namelen;
>   
> !   gcc_assert (base->common.flags & SECTION_NAMED);
> !   gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
> !   gcc_assert (strchr (base->named.name + 8, ','));
> ! 
> !   namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
> !   sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
>     darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
>   }
>   
> --- 2886,2909 ----
>   				HOST_WIDE_INT offset, section *base)
>   {
>     char sname[64];
> !   int namelen, extra = 0;
> !   bool is_for_lto;
> !   const char *lto_add = "";
> ! 
> !   gcc_checking_assert (base->common.flags & SECTION_NAMED);
> !   is_for_lto = strncmp (base->named.name, "__GNU_DWARF_LTO,", 16) == 0;
> !   gcc_checking_assert (is_for_lto
> ! 		       || strncmp (base->named.name, "__DWARF,", 8) == 0);
> !   const char *name = strchr (base->named.name, ',') + 1;
> !   gcc_checking_assert (name);
>   
> !   namelen = strchr (name, ',') - (name);
> !   if (is_for_lto)
> !     {
> !       lto_add = "_lto";
> !       extra = 4;
> !     }
> !   snprintf (sname, 64, "*Lsection%.*s%.*s", namelen, name, extra, lto_add);
>     darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
>   }
>   
> Index: early-lto-debug/gcc/config/darwin.h
> ===================================================================
> *** early-lto-debug.orig/gcc/config/darwin.h	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/config/darwin.h	2017-05-16 13:10:49.866240867 +0200
> *************** extern GTY(()) int darwin_ms_struct;
> *** 445,451 ****
>   #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
>   #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
>   #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
> ! #define DEBUG_MACRO_SECTION    "__DWARF,__debug_macro,regular,debug"
>   
>   #define TARGET_WANT_DEBUG_PUB_SECTIONS true
>   
> --- 445,458 ----
>   #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
>   #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
>   #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
> ! #define DEBUG_MACRO_SECTION     "__DWARF,__debug_macro,regular,debug"
> ! 
> ! #define DEBUG_LTO_INFO_SECTION	  "__GNU_DWARF_LTO,__debug_info,regular,debug"
> ! #define DEBUG_LTO_ABBREV_SECTION  "__GNU_DWARF_LTO,__debug_abbrev,regular,debug"
> ! #define DEBUG_LTO_MACINFO_SECTION "__GNU_DWARF_LTO,__debug_macinfo,regular,debug"
> ! #define DEBUG_LTO_LINE_SECTION	  "__GNU_DWARF_LTO,__debug_line,regular,debug"
> ! #define DEBUG_LTO_STR_SECTION	  "__GNU_DWARF_LTO,__debug_str,regular,debug"
> ! #define DEBUG_LTO_MACRO_SECTION   "__GNU_DWARF_LTO,__debug_macro,regular,debug"
>   
>   #define TARGET_WANT_DEBUG_PUB_SECTIONS true
>   
> Index: early-lto-debug/gcc/vmsdbgout.c
> ===================================================================
> *** early-lto-debug.orig/gcc/vmsdbgout.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/vmsdbgout.c	2017-05-16 13:10:49.866240867 +0200
> *************** const struct gcc_debug_hooks vmsdbg_debu
> *** 198,203 ****
> --- 198,205 ----
>      vmsdbgout_late_global_decl,
>      vmsdbgout_type_decl,		  /* type_decl */
>      debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
> +    debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> +    debug_nothing_tree_charstar_uhwi, /* register_external_die */
>      debug_nothing_tree,		  /* deferred_inline_function */
>      vmsdbgout_abstract_function,
>      debug_nothing_rtx_code_label,  /* label */
> Index: early-lto-debug/gcc/tree.c
> ===================================================================
> *** early-lto-debug.orig/gcc/tree.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/tree.c	2017-05-16 13:10:49.870240933 +0200
> *************** free_lang_data (void)
> *** 5974,5979 ****
> --- 5974,5983 ----
>         || (!flag_generate_lto && !flag_generate_offload))
>       return 0;
>   
> +   /* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one.  */
> +   if (vec_safe_is_empty (all_translation_units))
> +     build_translation_unit_decl (NULL_TREE);
> + 
>     /* Allocate and assign alias sets to the standard integer types
>        while the slots are still in the way the frontends generated them.  */
>     for (i = 0; i < itk_none; ++i)
> Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c
> ===================================================================
> *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-05-16 13:10:49.870240933 +0200
> *************** int main() {
> *** 23,28 ****
>   }
>   
>   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
>   /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
>   /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
> --- 23,28 ----
>   }
>   
>   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
>   /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
>   /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
> Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c
> ===================================================================
> *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-05-16 13:10:49.870240933 +0200
> *************** int main(int argc, char **argv) {
> *** 24,31 ****
>   }
>   
>   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> --- 24,31 ----
>   }
>   
>   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c
> ===================================================================
> *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-05-16 13:10:49.870240933 +0200
> *************** main ()
> *** 39,43 ****
>   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
>   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> --- 39,43 ----
>   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
>   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c
> ===================================================================
> *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-05-16 13:10:49.870240933 +0200
> *************** main ()
> *** 39,43 ****
>   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
>   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> --- 39,43 ----
>   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
>   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c
> ===================================================================
> *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-05-16 13:10:49.870240933 +0200
> *************** int main()
> *** 18,22 ****
>   
>   /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
>   /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> --- 18,22 ----
>   
>   /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
>   /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c
> ===================================================================
> *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-05-16 13:10:49.874240999 +0200
> *************** int main() {
> *** 18,23 ****
>   }
>   
>   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
>   /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
> --- 18,23 ----
>   }
>   
>   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
>   /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
> Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c
> ===================================================================
> *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-05-16 13:10:49.874240999 +0200
> *************** int main(int argc, char **argv) {
> *** 14,21 ****
>   
>   /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> --- 14,21 ----
>   
>   /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c
> ===================================================================
> *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-05-16 13:10:49.874240999 +0200
> *************** int main() {
> *** 12,22 ****
>   /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
>   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> --- 12,22 ----
>   /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
>   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
>   /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
>   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> Index: early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C
> ===================================================================
> *** early-lto-debug.orig/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-05-16 13:10:49.874240999 +0200
> *************** int main() {
> *** 38,44 ****
>   // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
>   // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
>   // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
> ! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" }
>   // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
>   // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
>   // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
> --- 38,44 ----
>   // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
>   // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
>   // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
> ! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" }
>   // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
>   // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
>   // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
> Index: early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp
> ===================================================================
> *** early-lto-debug.orig/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-05-16 13:10:47.554202813 +0200
> --- early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-05-16 13:10:49.874240999 +0200
> ***************
> *** 15,20 ****
> --- 15,21 ----
>   # <http://www.gnu.org/licenses/>.
>   
>   load_lib gdb-test.exp
> + load_lib target-supports.exp
>   
>   dg-init
>   v3-build_support
> *************** global PCH_CXXFLAGS
> *** 46,51 ****
> --- 47,60 ----
>   gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
>     "" "$DEFAULT_CXXFLAGS $PCH_CXXFLAGS"
>   
> + if { [check_effective_target_lto] } {
> +   append cxxflags " -flto"
> +   # work around sourceware.org 20882
> +   regsub {^(.*)-Wl,--gc-sections(.*)$} $cxxldflags {\1\2} cxxldflags
> +   gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
> +     "" "$DEFAULT_CXXFLAGS -flto $PCH_CXXFLAGS"
> + }
> + 
>   if [info exists guality_gdb_name] {
>       unsetenv GUALITY_GDB_NAME
>   }
> Index: early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90
> ===================================================================
> *** /dev/null	1970-01-01 00:00:00.000000000 +0000
> --- early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90	2017-05-18 09:39:31.394914888 +0200
> ***************
> *** 0 ****
> --- 1,54 ----
> + ! { dg-do run }
> + ! { dg-require-effective-target lto }
> + ! { dg-options "-fno-automatic -flto -g" }
> + !
> + ! PR fortran/55733
> + !
> + ! Check that -fno-automatic makes the local variable SAVEd
> + ! Check that -flto -g works
> + !
> + 
> + ! Scalar allocatable
> + subroutine foo(i)
> +   integer :: i
> +   integer, allocatable :: j
> +   if (i == 1) j = 42
> +   if (.not. allocated (j)) call abort ()
> +   if (j /= 42) call abort ()
> + end
> + 
> + ! Deferred-length string scalar
> + subroutine bar()
> +   logical, save :: first = .true.
> +   character(len=:), allocatable :: str
> +   if (first) then
> +     first = .false.
> +     if (allocated (str)) call abort ()
> +     str = "ABCDEF"
> +   end if
> +   if (.not. allocated (str)) call abort ()
> +   if (len (str) /= 6) call abort ()
> +   if (str(1:6) /= "ABCDEF") call abort ()
> + end subroutine bar
> + 
> + ! Deferred-length string array
> + subroutine bar_array()
> +   logical, save :: first = .true.
> +   character(len=:), allocatable :: str
> +   if (first) then
> +     first = .false.
> +     if (allocated (str)) call abort ()
> +     str = "ABCDEF"
> +   end if
> +   if (.not. allocated (str)) call abort ()
> +   if (len (str) /= 6) call abort ()
> +   if (str(1:6) /= "ABCDEF") call abort ()
> + end subroutine bar_array
> + 
> + call foo(1)
> + call foo(2)
> + call bar()
> + call bar_array()
> + call bar()
> + call bar_array()
> + end
> Index: early-lto-debug/gcc/config/i386/i386.c
> ===================================================================
> *** early-lto-debug.orig/gcc/config/i386/i386.c	2017-05-15 10:57:19.923567540 +0200
> --- early-lto-debug/gcc/config/i386/i386.c	2017-05-19 11:27:19.565373271 +0200
> *************** make_resolver_func (const tree default_d
> *** 33840,33846 ****
>     DECL_NAME (decl) = decl_name;
>     TREE_USED (decl) = 1;
>     DECL_ARTIFICIAL (decl) = 1;
> !   DECL_IGNORED_P (decl) = 0;
>     /* IFUNC resolvers have to be externally visible.  */
>     TREE_PUBLIC (decl) = 1;
>     DECL_UNINLINABLE (decl) = 1;
> --- 33840,33846 ----
>     DECL_NAME (decl) = decl_name;
>     TREE_USED (decl) = 1;
>     DECL_ARTIFICIAL (decl) = 1;
> !   DECL_IGNORED_P (decl) = 1;
>     /* IFUNC resolvers have to be externally visible.  */
>     TREE_PUBLIC (decl) = 1;
>     DECL_UNINLINABLE (decl) = 1;
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-06-07  8:21 ` Richard Biener
@ 2017-06-20 11:16   ` Richard Biener
  2017-07-04 11:10     ` Richard Biener
  0 siblings, 1 reply; 22+ messages in thread
From: Richard Biener @ 2017-06-20 11:16 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason

On Wed, 7 Jun 2017, Richard Biener wrote:

> On Fri, 19 May 2017, Richard Biener wrote:
> 
> > 
> > This is a repost of the main part of the early LTO debug support.
> > The only changes relative to the last post is in the dwarf2out.c
> > pieces due to Jasons review and Jakubs introduction of
> > DW_OP_GNU_variable_value.
> > 
> > I've also adjusted testcases for fallout (the asan backtraces do
> > give files / line numbers because libbacktrace doesn't understand
> > the DWARF) plus added a -flto run over the libstdc++ pretty printer
> > testsuite -- after all the goal was to make those work with LTO,
> > and they now nicely do.
> > 
> > [LTO-]bootstrapped and tested on x86_64-unknown-linux-gnu.
> > 
> > I've also tested with -flto -g and compared to before the patch and
> > the outcome doesn't contain any surprises.
> > 
> > I've also ran the gdb testsuite with no differences (but I guess
> > it doesn't exercise LTO).
> > 
> > I've also built SPEC 2k6 with -flto -g.
> > 
> > I've also debugged optimized LTO bootstrapped cc1 a bit - not that
> > debugging (LTO) optimized cc1 is a pleasant experience, but at least
> > gdb doesn't crash.
> > 
> > Ok for trunk?
> 
> Ping.

Ping^2.

> > Both darwin and mingw maintainers were not concerned about LTO with -g
> > being broken for them.
> > 
> > This patch allows us to go forward with freeing more stuff after
> > the frontend finished, in particular remove LTO streaming of a lot
> > of type information that is referenced from trees (and, as a first
> > step, enable free-lang-data for non-LTO compiles).
> > 
> > Thanks,
> > Richard.
> > 
> > 2017-05-19  Richard Biener  <rguenther@suse.de>
> > 
> >         * debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and
> >         register_external_die hooks.
> >         (debug_false_tree_charstarstar_uhwistar): Declare.
> >         (debug_nothing_tree_charstar_uhwi): Likewise.
> >         * debug.c (do_nothing_debug_hooks): Adjust.
> >         (debug_false_tree_charstarstar_uhwistar): New do nothing.
> >         (debug_nothing_tree_charstar_uhwi): Likewise.
> >         * dbxout.c (dbx_debug_hooks): Adjust.
> >         (xcoff_debug_hooks): Likewise.
> >         * sdbout.c (sdb_debug_hooks): Likewise.
> >         * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
> > 
> >         * dwarf2out.c (macinfo_label_base): New global.
> > 	(dwarf2out_register_external_die): New function for the
> > 	register_external_die hook.
> >         (dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl.
> >         (dwarf2_debug_hooks): Use them.
> >         (dwarf2_lineno_debug_hooks): Adjust.
> >         (struct die_struct): Add with_offset flag.
> >         (DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION,
> >         DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION,
> >         DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION,
> >         DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION,
> >         DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
> >         DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros
> >         defining section names for the early LTO debug variants.
> > 	(reset_indirect_string): New helper.
> >         (add_AT_external_die_ref): Helper for dwarf2out_register_external_die.
> >         (print_dw_val): Add support for offsetted symbol references.
> >         (compute_section_prefix_1): Split out worker to distinguish
> >         the comdat from the LTO case.
> >         (compute_section_prefix): Wrap old comdat case here.
> >         (output_die): Skip DIE symbol output for the LTO added one.
> >         Handle DIE symbol references with offset.
> >         (output_comp_unit): Guard section name mangling properly.
> >         For LTO debug sections emit a symbol at the section beginning
> >         which we use to refer to its DIEs.
> >         (add_abstract_origin_attribute): For DIEs registered via
> >         dwarf2out_register_external_die directly refer to the early
> >         DIE rather than indirectly through the shadow one we created.
> >         (gen_array_type_die): When generating early LTO debug do
> >         not emit DW_AT_string_length.
> >         (gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs
> >         late when in LTO.
> >         (gen_subprogram_die): Adjust the check for whether we face
> >         a concrete instance DIE for an inline we can reuse for the
> >         late LTO case.  Likewise avoid another specification DIE
> >         for early built declarations/definitions for the late LTO case.
> >         (gen_variable_die): Add type references for late duplicated VLA dies
> >         when in late LTO.
> >         (gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function,
> >         we have the abstract instance already.
> >         (process_scope_var): Adjust decl DIE contexts in LTO which
> >         first puts them in limbo.
> >         (gen_decl_die): Do not generate type DIEs late apart from
> >         types for VLAs or for decls we do not yet have a DIE.
> >         (dwarf2out_early_global_decl): Make sure to create DIEs
> >         for abstract instances of a decl first.
> >         (dwarf2out_late_global_decl): Adjust comment.
> >         (output_macinfo_op): With multiple macro sections use
> > 	macinfo_label_base to distinguish labels.
> >         (output_macinfo): Likewise.  Update macinfo_label_base.
> > 	Pass in the line info label.
> > 	(note_variable_value_in_expr): When generating LTO resolve
> > 	all variable values here by generating DIEs as needed.
> >         (init_sections_and_labels): Add early LTO debug flag parameter
> >         and generate different sections and names if set.  Add generation
> >         counter for the labels so we can have multiple of them.
> >         (reset_dies): Helper to allow DIEs to be output multiple times.
> >         (dwarf2out_finish): When outputting DIEs to the fat part of an
> > 	LTO object first reset DIEs.
> >         (dwarf2out_early_finish): Output early DIEs when generating LTO.
> > 
> > Cleanups we can do (and need) when removing the "old" LTO path and add
> > the early LTO path.
> > 
> >         (set_decl_abstract_flags): Remove.
> >         (set_block_abstract_flags): Likewise.
> >         (dwarf2out_abstract_function): Treat the early generated DIEs
> >         as the abstract copy and only add DW_AT_inline and
> >         DW_AT_artificial here.
> > 
> > 	* tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL
> > 	if we have none yet (Go fails to build one, PR78628).
> >         * lto-streamer-in.c: Include debug.h.
> >         (dref_queue): New global.
> >         (lto_read_tree_1): Stream in DIE references.
> >         (lto_input_tree): Register DIE references.
> > 	(input_function): Stream DECL_DEBUG_ARGS.
> >         * lto-streamer-out.c: Include debug.h.
> >         (lto_write_tree_1): Output DIE references.
> >         (DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN.
> > 	Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls.
> > 	(output_function): Stream DECL_DEBUG_ARGS.
> >         * tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers):
> >         Stream DECL_ABSTRACT_ORIGIN.
> >         * tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise.
> > 	(write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL
> > 	DECL_CONTEXT for file-scope decls.
> >         * lto-streamer.h (struct dref_entry): Declare.
> >         (dref_queue): Likewise.
> > 
> >         * lto-wrapper.c (debug_obj): New global.
> >         (tool_cleanup): Unlink it if required.
> >         (debug_objcopy): New function.
> >         (run_gcc): Handle early debug sections in the IL files by
> >         extracting them to separate files, partially linkin them and
> >         feeding the result back as result to the linker.
> > 
> >         * config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION,
> >         DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION,
> >         DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug
> >         sections into a separate segment.
> >         * config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO
> >         segments.
> >         (darwin_asm_dwarf_section): Likewise.
> >         (darwin_asm_output_dwarf_offset): Likewise.
> > 
> > 	* config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P.
> > 
> >         lto/
> >         * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
> >         (lto_read_decls): Process TRANSLATION_UNIT_DECLs.  Remove
> >         TYPE_DECL debug processing, register DIE references from
> >         prevailing SCCs with the debug machinery.
> >         (lto_section_with_id): Handle LTO debug sections.
> > 
> > 	libstdc++/
> > 	* testsuite/libstdc++-prettyprinters/prettyprinters.exp: Run all
> > 	tests with -flto as well if supported.
> > 
> > 	* c-c++-common/asan/global-overflow-1.c: Adjust diagnostic location
> > 	regex to handle the LTO case.
> > 	* c-c++-common/asan/heap-overflow-1.c: Likewise.
> > 	* c-c++-common/asan/misalign-1.c: Likewise.
> > 	* c-c++-common/asan/misalign-2.c: Likewise.
> > 	* c-c++-common/asan/null-deref-1.c: Likewise.
> > 	* c-c++-common/asan/stack-overflow-1.c: Likewise.
> > 	* c-c++-common/asan/strncpy-overflow-1.c: Likewise.
> > 	* c-c++-common/asan/use-after-free-1.c: Likewise.
> > 	* g++.dg/asan/large-func-test-1.C: Likewise.
> > 	* gfortran.dg/save_6.f90: Add -flto -g variant of save_5.f90.
> > 
> > Index: early-lto-debug/gcc/dwarf2out.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/dwarf2out.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/dwarf2out.c	2017-05-19 12:29:43.933873285 +0200
> > *************** static GTY(()) section *debug_aranges_se
> > *** 162,167 ****
> > --- 162,168 ----
> >   static GTY(()) section *debug_addr_section;
> >   static GTY(()) section *debug_macinfo_section;
> >   static const char *debug_macinfo_section_name;
> > + static unsigned macinfo_label_base = 1;
> >   static GTY(()) section *debug_line_section;
> >   static GTY(()) section *debug_skeleton_line_section;
> >   static GTY(()) section *debug_loc_section;
> > *************** static void dwarf2out_begin_function (tr
> > *** 2686,2691 ****
> > --- 2687,2696 ----
> >   static void dwarf2out_end_function (unsigned int);
> >   static void dwarf2out_register_main_translation_unit (tree unit);
> >   static void dwarf2out_set_name (tree, tree);
> > + static void dwarf2out_register_external_die (tree decl, const char *sym,
> > + 					     unsigned HOST_WIDE_INT off);
> > + static bool dwarf2out_die_ref_for_decl (tree decl, const char **sym,
> > + 					unsigned HOST_WIDE_INT *off);
> >   
> >   /* The debug hooks structure.  */
> >   
> > *************** const struct gcc_debug_hooks dwarf2_debu
> > *** 2720,2725 ****
> > --- 2725,2732 ----
> >     dwarf2out_late_global_decl,
> >     dwarf2out_type_decl,		/* type_decl */
> >     dwarf2out_imported_module_or_decl,
> > +   dwarf2out_die_ref_for_decl,
> > +   dwarf2out_register_external_die,
> >     debug_nothing_tree,		/* deferred_inline_function */
> >     /* The DWARF 2 backend tries to reduce debugging bloat by not
> >        emitting the abstract description of inline functions until
> > *************** const struct gcc_debug_hooks dwarf2_line
> > *** 2761,2766 ****
> > --- 2768,2775 ----
> >     debug_nothing_tree,		         /* late_global_decl */
> >     debug_nothing_tree_int,		 /* type_decl */
> >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> >     debug_nothing_tree,		         /* deferred_inline_function */
> >     debug_nothing_tree,		         /* outlining_inline_function */
> >     debug_nothing_rtx_code_label,	         /* label */
> > *************** typedef struct GTY((chain_circular ("%h.
> > *** 2889,2894 ****
> > --- 2898,2906 ----
> >     /* Die is used and must not be pruned as unused.  */
> >     BOOL_BITFIELD die_perennial_p : 1;
> >     BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
> > +   /* For an external ref to die_symbol if die_offset contains an extra
> > +      offset to that symbol.  */
> > +   BOOL_BITFIELD with_offset : 1;
> >     /* Whether this DIE was removed from the DIE tree, for example via
> >        prune_unused_types.  We don't consider those present from the
> >        DIE lookup routines.  */
> > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > *** 3692,3703 ****
> > --- 3704,3727 ----
> >   #ifndef DEBUG_DWO_INFO_SECTION
> >   #define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
> >   #endif
> > + #ifndef DEBUG_LTO_DWO_INFO_SECTION
> > + #define DEBUG_LTO_DWO_INFO_SECTION ".gnu.debuglto_.debug_info.dwo"
> > + #endif
> > + #ifndef DEBUG_LTO_INFO_SECTION
> > + #define DEBUG_LTO_INFO_SECTION	".gnu.debuglto_.debug_info"
> > + #endif
> >   #ifndef DEBUG_ABBREV_SECTION
> >   #define DEBUG_ABBREV_SECTION	".debug_abbrev"
> >   #endif
> >   #ifndef DEBUG_DWO_ABBREV_SECTION
> >   #define DEBUG_DWO_ABBREV_SECTION ".debug_abbrev.dwo"
> >   #endif
> > + #ifndef DEBUG_LTO_DWO_ABBREV_SECTION
> > + #define DEBUG_LTO_DWO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev.dwo"
> > + #endif
> > + #ifndef DEBUG_LTO_ABBREV_SECTION
> > + #define DEBUG_LTO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev"
> > + #endif
> >   #ifndef DEBUG_ARANGES_SECTION
> >   #define DEBUG_ARANGES_SECTION	".debug_aranges"
> >   #endif
> > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > *** 3710,3727 ****
> > --- 3734,3766 ----
> >   #ifndef DEBUG_DWO_MACINFO_SECTION
> >   #define DEBUG_DWO_MACINFO_SECTION      ".debug_macinfo.dwo"
> >   #endif
> > + #ifndef DEBUG_LTO_DWO_MACINFO_SECTION
> > + #define DEBUG_LTO_DWO_MACINFO_SECTION  ".gnu.debuglto_.debug_macinfo.dwo"
> > + #endif
> > + #ifndef DEBUG_LTO_MACINFO_SECTION
> > + #define DEBUG_LTO_MACINFO_SECTION      ".gnu.debuglto_.debug_macinfo"
> > + #endif
> >   #ifndef DEBUG_DWO_MACRO_SECTION
> >   #define DEBUG_DWO_MACRO_SECTION        ".debug_macro.dwo"
> >   #endif
> >   #ifndef DEBUG_MACRO_SECTION
> >   #define DEBUG_MACRO_SECTION	".debug_macro"
> >   #endif
> > + #ifndef DEBUG_LTO_DWO_MACRO_SECTION
> > + #define DEBUG_LTO_DWO_MACRO_SECTION    ".gnu.debuglto_.debug_macro.dwo"
> > + #endif
> > + #ifndef DEBUG_LTO_MACRO_SECTION
> > + #define DEBUG_LTO_MACRO_SECTION ".gnu.debuglto_.debug_macro"
> > + #endif
> >   #ifndef DEBUG_LINE_SECTION
> >   #define DEBUG_LINE_SECTION	".debug_line"
> >   #endif
> >   #ifndef DEBUG_DWO_LINE_SECTION
> >   #define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
> >   #endif
> > + #ifndef DEBUG_LTO_LINE_SECTION
> > + #define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
> > + #endif
> >   #ifndef DEBUG_LOC_SECTION
> >   #define DEBUG_LOC_SECTION	".debug_loc"
> >   #endif
> > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > *** 3750,3761 ****
> > --- 3789,3809 ----
> >   #ifndef DEBUG_DWO_STR_OFFSETS_SECTION
> >   #define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo"
> >   #endif
> > + #ifndef DEBUG_LTO_DWO_STR_OFFSETS_SECTION
> > + #define DEBUG_LTO_DWO_STR_OFFSETS_SECTION ".gnu.debuglto_.debug_str_offsets.dwo"
> > + #endif
> >   #ifndef DEBUG_STR_DWO_SECTION
> >   #define DEBUG_STR_DWO_SECTION   ".debug_str.dwo"
> >   #endif
> > + #ifndef DEBUG_LTO_STR_DWO_SECTION
> > + #define DEBUG_LTO_STR_DWO_SECTION ".gnu.debuglto_.debug_str.dwo"
> > + #endif
> >   #ifndef DEBUG_STR_SECTION
> >   #define DEBUG_STR_SECTION  ".debug_str"
> >   #endif
> > + #ifndef DEBUG_LTO_STR_SECTION
> > + #define DEBUG_LTO_STR_SECTION ".gnu.debuglto_.debug_str"
> > + #endif
> >   #ifndef DEBUG_RANGES_SECTION
> >   #define DEBUG_RANGES_SECTION	".debug_ranges"
> >   #endif
> > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > *** 3780,3785 ****
> > --- 3828,3837 ----
> >   /* Section flags for .debug_str.dwo section.  */
> >   #define DEBUG_STR_DWO_SECTION_FLAGS (SECTION_DEBUG | SECTION_EXCLUDE)
> >   
> > + /* Attribute used to refer to the macro section.  */
> > + #define DEBUG_MACRO_ATTRIBUTE (dwarf_version >= 5 ? DW_AT_macros \
> > + 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros)
> > + 
> >   /* Labels we insert at beginning sections we can reference instead of
> >      the section names themselves.  */
> >   
> > *************** set_indirect_string (struct indirect_str
> > *** 4368,4373 ****
> > --- 4420,4443 ----
> >       }
> >   }
> >   
> > + /* A helper function for dwarf2out_finish, called to reset indirect
> > +    string decisions done for early LTO dwarf output before fat object
> > +    dwarf output.  */
> > + 
> > + int
> > + reset_indirect_string (indirect_string_node **h, void *)
> > + {
> > +   struct indirect_string_node *node = *h;
> > +   if (node->form == DW_FORM_strp || node->form == DW_FORM_GNU_str_index)
> > +     {
> > +       free (node->label);
> > +       node->label = NULL;
> > +       node->form = (dwarf_form) 0;
> > +       node->index = 0;
> > +     }
> > +   return 1;
> > + }
> > + 
> >   /* Find out whether a string should be output inline in DIE
> >      or out-of-line in .debug_str section.  */
> >   
> > *************** lookup_decl_die (tree decl)
> > *** 5413,5418 ****
> > --- 5483,5668 ----
> >     return *die;
> >   }
> >   
> > + 
> > + /* For DECL which might have early dwarf output query a SYMBOL + OFFSET
> > +    style reference.  Return true if we found one refering to a DIE for
> > +    DECL, otherwise return false.  */
> > + 
> > + static bool
> > + dwarf2out_die_ref_for_decl (tree decl, const char **sym,
> > + 			    unsigned HOST_WIDE_INT *off)
> > + {
> > +   dw_die_ref die;
> > + 
> > +   if (flag_wpa && !decl_die_table)
> > +     return false;
> > + 
> > +   if (TREE_CODE (decl) == BLOCK)
> > +     die = BLOCK_DIE (decl);
> > +   else
> > +     die = lookup_decl_die (decl);
> > +   if (!die)
> > +     return false;
> > + 
> > +   /* During WPA stage we currently use DIEs to store the
> > +      decl <-> label + offset map.  That's quite inefficient but it
> > +      works for now.  */
> > +   if (flag_wpa)
> > +     {
> > +       dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
> > +       if (!ref)
> > + 	{
> > + 	  gcc_assert (die == comp_unit_die ());
> > + 	  return false;
> > + 	}
> > +       *off = ref->die_offset;
> > +       *sym = ref->die_id.die_symbol;
> > +       return true;
> > +     }
> > + 
> > +   /* Similar to get_ref_die_offset_label, but using the "correct"
> > +      label.  */
> > +   *off = die->die_offset;
> > +   while (die->die_parent)
> > +     die = die->die_parent;
> > +   /* For the containing CU DIE we compute a die_symbol in
> > +      compute_section_prefix.  */
> > +   gcc_assert (die->die_tag == DW_TAG_compile_unit
> > + 	      && die->die_id.die_symbol != NULL);
> > +   *sym = die->die_id.die_symbol;
> > +   return true;
> > + }
> > + 
> > + /* Add a reference of kind ATTR_KIND to a DIE at SYMBOL + OFFSET to DIE.  */
> > + 
> > + static void
> > + add_AT_external_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind,
> > + 			 const char *symbol, HOST_WIDE_INT offset)
> > + {
> > +   /* Create a fake DIE that contains the reference.  Don't use
> > +      new_die because we don't want to end up in the limbo list.  */
> > +   dw_die_ref ref = ggc_cleared_alloc<die_node> ();
> > +   ref->die_tag = die->die_tag;
> > +   ref->die_id.die_symbol = IDENTIFIER_POINTER (get_identifier (symbol));
> > +   ref->die_offset = offset;
> > +   ref->with_offset = 1;
> > +   add_AT_die_ref (die, attr_kind, ref);
> > + }
> > + 
> > + /* Create a DIE for DECL if required and add a reference to a DIE
> > +    at SYMBOL + OFFSET which contains attributes dumped early.  */
> > + 
> > + static void
> > + dwarf2out_register_external_die (tree decl, const char *sym,
> > + 				 unsigned HOST_WIDE_INT off)
> > + {
> > +   if (debug_info_level == DINFO_LEVEL_NONE)
> > +     return;
> > + 
> > +   if (flag_wpa && !decl_die_table)
> > +     decl_die_table = hash_table<decl_die_hasher>::create_ggc (1000);
> > + 
> > +   dw_die_ref die
> > +     = TREE_CODE (decl) == BLOCK ? BLOCK_DIE (decl) : lookup_decl_die (decl);
> > +   gcc_assert (!die);
> > + 
> > +   tree ctx;
> > +   dw_die_ref parent = NULL;
> > +   /* Need to lookup a DIE for the decls context - the containing
> > +      function or translation unit.  */
> > +   if (TREE_CODE (decl) == BLOCK)
> > +     {
> > +       ctx = BLOCK_SUPERCONTEXT (decl);
> > +       /* ???  We do not output DIEs for all scopes thus skip as
> > + 	 many DIEs as needed.  */
> > +       while (TREE_CODE (ctx) == BLOCK
> > + 	     && !BLOCK_DIE (ctx))
> > + 	ctx = BLOCK_SUPERCONTEXT (ctx);
> > +     }
> > +   else
> > +     ctx = DECL_CONTEXT (decl);
> > +   while (ctx && TYPE_P (ctx))
> > +     ctx = TYPE_CONTEXT (ctx);
> > +   if (ctx)
> > +     {
> > +       if (TREE_CODE (ctx) == BLOCK)
> > + 	parent = BLOCK_DIE (ctx);
> > +       else if (TREE_CODE (ctx) == TRANSLATION_UNIT_DECL
> > + 	       /* Keep the 1:1 association during WPA.  */
> > + 	       && !flag_wpa)
> > + 	/* Otherwise all late annotations go to the main CU which
> > + 	   imports the original CUs.  */
> > + 	parent = comp_unit_die ();
> > +       else if (TREE_CODE (ctx) == FUNCTION_DECL
> > + 	       && TREE_CODE (decl) != PARM_DECL
> > + 	       && TREE_CODE (decl) != BLOCK)
> > + 	/* Leave function local entities parent determination to when
> > + 	   we process scope vars.  */
> > + 	;
> > +       else
> > + 	parent = lookup_decl_die (ctx);
> > +     }
> > +   else
> > +     /* ???  In some cases the C++ FE (at least) fails to
> > +        set DECL_CONTEXT properly.  Simply globalize stuff
> > +        in this case.  For example
> > +        __dso_handle created via iostream line 74 col 25.  */
> > +     parent = comp_unit_die ();
> > +   /* Create a DIE "stub".  */
> > +   switch (TREE_CODE (decl))
> > +     {
> > +     case TRANSLATION_UNIT_DECL:
> > +       if (! flag_wpa)
> > + 	{
> > + 	  die = comp_unit_die ();
> > + 	  dw_die_ref import = new_die (DW_TAG_imported_unit, die, NULL_TREE);
> > + 	  add_AT_external_die_ref (import, DW_AT_import, sym, off);
> > + 	  /* We re-target all CU decls to the LTRANS CU DIE, so no need
> > + 	     to create a DIE for the original CUs.  */
> > + 	  return;
> > + 	}
> > +       /* Keep the 1:1 association during WPA.  */
> > +       die = new_die (DW_TAG_compile_unit, NULL, decl);
> > +       break;
> > +     case NAMESPACE_DECL:
> > +       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
> > + 	 at the input language (if we have enough DECL_CONTEXT to follow)
> > + 	 or use a bit in tree_decl_with_vis to record the distinction.  */
> > +       die = new_die (DW_TAG_namespace, parent, decl);
> > +       break;
> > +     case FUNCTION_DECL:
> > +       die = new_die (DW_TAG_subprogram, parent, decl);
> > +       break;
> > +     case VAR_DECL:
> > +       die = new_die (DW_TAG_variable, parent, decl);
> > +       break;
> > +     case RESULT_DECL:
> > +       die = new_die (DW_TAG_variable, parent, decl);
> > +       break;
> > +     case PARM_DECL:
> > +       die = new_die (DW_TAG_formal_parameter, parent, decl);
> > +       break;
> > +     case CONST_DECL:
> > +       die = new_die (DW_TAG_constant, parent, decl);
> > +       break;
> > +     case LABEL_DECL:
> > +       die = new_die (DW_TAG_label, parent, decl);
> > +       break;
> > +     case BLOCK:
> > +       die = new_die (DW_TAG_lexical_block, parent, decl);
> > +       break;
> > +     default:
> > +       gcc_unreachable ();
> > +     }
> > +   if (TREE_CODE (decl) == BLOCK)
> > +     BLOCK_DIE (decl) = die;
> > +   else
> > +     equate_decl_number_to_die (decl, die);
> > + 
> > +   /* Add a reference to the DIE providing early debug at $sym + off.  */
> > +   add_AT_external_die_ref (die, DW_AT_abstract_origin, sym, off);
> > + }
> > + 
> >   /* Returns a hash value for X (which really is a var_loc_list).  */
> >   
> >   inline hashval_t
> > *************** print_dw_val (dw_val_node *val, bool rec
> > *** 5900,5906 ****
> >   			       die->die_id.die_type_node->signature);
> >   	    }
> >   	  else if (die->die_id.die_symbol)
> > ! 	    fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
> >   	  else
> >   	    fprintf (outfile, "die -> %ld", die->die_offset);
> >   	  fprintf (outfile, " (%p)", (void *) die);
> > --- 6150,6160 ----
> >   			       die->die_id.die_type_node->signature);
> >   	    }
> >   	  else if (die->die_id.die_symbol)
> > ! 	    {
> > ! 	      fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
> > ! 	      if (die->with_offset)
> > ! 		fprintf (outfile, " + %ld", die->die_offset);
> > ! 	    }
> >   	  else
> >   	    fprintf (outfile, "die -> %ld", die->die_offset);
> >   	  fprintf (outfile, " (%p)", (void *) die);
> > *************** static unsigned int comdat_symbol_number
> > *** 7216,7222 ****
> >      children, and set comdat_symbol_id accordingly.  */
> >   
> >   static void
> > ! compute_section_prefix (dw_die_ref unit_die)
> >   {
> >     const char *die_name = get_AT_string (unit_die, DW_AT_name);
> >     const char *base = die_name ? lbasename (die_name) : "anonymous";
> > --- 7470,7476 ----
> >      children, and set comdat_symbol_id accordingly.  */
> >   
> >   static void
> > ! compute_section_prefix_1 (dw_die_ref unit_die, bool comdat_p)
> >   {
> >     const char *die_name = get_AT_string (unit_die, DW_AT_name);
> >     const char *base = die_name ? lbasename (die_name) : "anonymous";
> > *************** compute_section_prefix (dw_die_ref unit_
> > *** 7235,7241 ****
> >     unmark_all_dies (unit_die);
> >     md5_finish_ctx (&ctx, checksum);
> >   
> > !   sprintf (name, "%s.", base);
> >     clean_symbol_name (name);
> >   
> >     p = name + strlen (name);
> > --- 7489,7499 ----
> >     unmark_all_dies (unit_die);
> >     md5_finish_ctx (&ctx, checksum);
> >   
> > !   /* When we this for comp_unit_die () we have a DW_AT_name that might
> > !      not start with a letter but with anything valid for filenames and
> > !      clean_symbol_name doesn't fix that up.  Prepend 'g' if the first
> > !      character is not a letter.  */
> > !   sprintf (name, "%s%s.", ISALPHA (*base) ? "" : "g", base);
> >     clean_symbol_name (name);
> >   
> >     p = name + strlen (name);
> > *************** compute_section_prefix (dw_die_ref unit_
> > *** 7245,7251 ****
> >         p += 2;
> >       }
> >   
> > !   comdat_symbol_id = unit_die->die_id.die_symbol = xstrdup (name);
> >     comdat_symbol_number = 0;
> >   }
> >   
> > --- 7503,7517 ----
> >         p += 2;
> >       }
> >   
> > !   unit_die->die_id.die_symbol = xstrdup (name);
> > !   unit_die->comdat_type_p = comdat_p;
> > ! }
> > ! 
> > ! static void
> > ! compute_section_prefix (dw_die_ref unit_die)
> > ! {
> > !   compute_section_prefix_1 (unit_die, true);
> > !   comdat_symbol_id = unit_die->die_id.die_symbol;
> >     comdat_symbol_number = 0;
> >   }
> >   
> > *************** output_die (dw_die_ref die)
> > *** 9971,9977 ****
> >   
> >     /* If someone in another CU might refer to us, set up a symbol for
> >        them to point to.  */
> > !   if (! die->comdat_type_p && die->die_id.die_symbol)
> >       output_die_symbol (die);
> >   
> >     dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
> > --- 10237,10247 ----
> >   
> >     /* If someone in another CU might refer to us, set up a symbol for
> >        them to point to.  */
> > !   if (! die->comdat_type_p && die->die_id.die_symbol
> > !       /* Don't output the symbol twice.  For LTO we want the label
> > !          on the section beginning, not on the actual DIE.  */
> > !       && (!flag_generate_lto
> > ! 	  || die->die_tag != DW_TAG_compile_unit))
> >       output_die_symbol (die);
> >   
> >     dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
> > *************** output_die (dw_die_ref die)
> > *** 10164,10171 ****
> >   		    size = DWARF2_ADDR_SIZE;
> >   		  else
> >   		    size = DWARF_OFFSET_SIZE;
> > ! 		  dw2_asm_output_offset (size, sym, debug_info_section, "%s",
> > ! 					 name);
> >   		}
> >   	    }
> >   	  else
> > --- 10434,10453 ----
> >   		    size = DWARF2_ADDR_SIZE;
> >   		  else
> >   		    size = DWARF_OFFSET_SIZE;
> > ! 		  /* ???  We cannot unconditionally output die_offset if
> > ! 		     non-zero - at least -feliminate-dwarf2-dups will
> > ! 		     create references to those DIEs via symbols.  And we
> > ! 		     do not clear its DIE offset after outputting it
> > ! 		     (and the label refers to the actual DIEs, not the
> > ! 		     DWARF CU unit header which is when using label + offset
> > ! 		     would be the correct thing to do).
> > ! 		     ???  This is the reason for the with_offset flag.  */
> > ! 		  if (AT_ref (a)->with_offset)
> > ! 		    dw2_asm_output_offset (size, sym, AT_ref (a)->die_offset,
> > ! 					   debug_info_section, "%s", name);
> > ! 		  else
> > ! 		    dw2_asm_output_offset (size, sym, debug_info_section, "%s",
> > ! 					   name);
> >   		}
> >   	    }
> >   	  else
> > *************** output_comp_unit (dw_die_ref die, int ou
> > *** 10391,10397 ****
> >     calc_die_sizes (die);
> >   
> >     oldsym = die->die_id.die_symbol;
> > !   if (oldsym)
> >       {
> >         tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
> >   
> > --- 10673,10679 ----
> >     calc_die_sizes (die);
> >   
> >     oldsym = die->die_id.die_symbol;
> > !   if (oldsym && die->comdat_type_p)
> >       {
> >         tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
> >   
> > *************** output_comp_unit (dw_die_ref die, int ou
> > *** 10407,10412 ****
> > --- 10689,10721 ----
> >         info_section_emitted = true;
> >       }
> >   
> > +   /* For LTO cross unit DIE refs we want a symbol on the start of the
> > +      debuginfo section, not on the CU DIE.
> > +      ???  We could simply use the symbol as it would be output by output_die
> > +      and account for the extra offset produced by the CU header which has fixed
> > +      size.  OTOH it currently only supports linkonce globals which would
> > +      be less than ideal?.  */
> > +   if (flag_generate_lto && oldsym)
> > +     {
> > +       /* ???  No way to get visibility assembled without a decl.  */
> > +       tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
> > + 			      get_identifier (oldsym), char_type_node);
> > +       TREE_PUBLIC (decl) = true;
> > +       TREE_STATIC (decl) = true;
> > +       DECL_ARTIFICIAL (decl) = true;
> > +       DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
> > +       DECL_VISIBILITY_SPECIFIED (decl) = true;
> > +       targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
> > + #ifdef ASM_WEAKEN_LABEL
> > +       /* We prefer a .weak because that handles duplicates from duplicate
> > +          archive members in a graceful way.  */
> > +       ASM_WEAKEN_LABEL (asm_out_file, oldsym);
> > + #else
> > +       targetm.asm_out.globalize_label (asm_out_file, oldsym);
> > + #endif
> > +       ASM_OUTPUT_LABEL (asm_out_file, oldsym);
> > +     }
> > + 
> >     /* Output debugging information.  */
> >     output_compilation_unit_header (dwo_id
> >   				  ? DW_UT_split_compile : DW_UT_compile);
> > *************** parameter_ref_descriptor (rtx rtl)
> > *** 14523,14528 ****
> > --- 14832,14840 ----
> >     if (dwarf_strict)
> >       return NULL;
> >     gcc_assert (TREE_CODE (DEBUG_PARAMETER_REF_DECL (rtl)) == PARM_DECL);
> > +   /* With LTO during LTRANS we get the late DIE that refers to the early
> > +      DIE, thus we add another indirection here.  This seems to confuse
> > +      gdb enough to make gcc.dg/guality/pr68860-1.c FAIL with LTO.  */
> >     ref = lookup_decl_die (DEBUG_PARAMETER_REF_DECL (rtl));
> >     ret = new_loc_descr (DW_OP_GNU_parameter_ref, 0, 0);
> >     if (ref)
> > *************** add_abstract_origin_attribute (dw_die_re
> > *** 20216,20222 ****
> >       }
> >   
> >     if (DECL_P (origin))
> > !     origin_die = lookup_decl_die (origin);
> >     else if (TYPE_P (origin))
> >       origin_die = lookup_type_die (origin);
> >     else if (TREE_CODE (origin) == BLOCK)
> > --- 20528,20547 ----
> >       }
> >   
> >     if (DECL_P (origin))
> > !     {
> > !       dw_die_ref c;
> > !       origin_die = lookup_decl_die (origin);
> > !       /* "Unwrap" the decls DIE which we put in the imported unit context.
> > !           ???  If we finish dwarf2out_function_decl refactoring we can
> > ! 	  do this in a better way from the start and only lazily emit
> > ! 	  the early DIE references.  */
> > !       if (in_lto_p
> > ! 	  && origin_die
> > ! 	  && (c = get_AT_ref (origin_die, DW_AT_abstract_origin))
> > ! 	  /* ???  Identify this better.  */
> > ! 	  && c->with_offset)
> > ! 	origin_die = c;
> > !     }
> >     else if (TYPE_P (origin))
> >       origin_die = lookup_type_die (origin);
> >     else if (TREE_CODE (origin) == BLOCK)
> > *************** gen_array_type_die (tree type, dw_die_re
> > *** 20775,20781 ****
> >         size = int_size_in_bytes (type);
> >         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)
> >   	{
> >   	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> > --- 21100,21109 ----
> >         size = int_size_in_bytes (type);
> >         if (size >= 0)
> >   	add_AT_unsigned (array_die, DW_AT_byte_size, size);
> > !       /* ???  We can't annotate types late, but for LTO we may not
> > ! 	 generate a location early either (gfortran.dg/save_6.f90).  */
> > !       else if (! (early_dwarf && flag_generate_lto)
> > ! 	       && TYPE_DOMAIN (type) != NULL_TREE
> >   	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE)
> >   	{
> >   	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> > *************** gen_formal_parameter_die (tree node, tre
> > *** 21188,21194 ****
> >   	 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
> > --- 21516,21524 ----
> >   	 thing.  */
> >         if (parm_die && parm_die->die_parent != context_die)
> >   	{
> > ! 	  /* ???  The DIE parent is the "abstract" copy and the context_die
> > ! 	     is the specification "copy".  */
> > ! 	  if (!DECL_ABSTRACT_P (node) && !in_lto_p)
> >   	    {
> >   	      /* This can happen when creating an inlined instance, in
> >   		 which case we need to create a new DIE that will get
> > *************** gen_type_die_for_member (tree type, tree
> > *** 21462,21468 ****
> >   /* 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, 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
> > --- 21792,21797 ----
> > *************** set_decl_origin_self (tree decl)
> > *** 21535,21685 ****
> >       }
> >   }
> >   \f
> > ! /* 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, vec<tree> &abstract_vec)
> > ! {
> > !   tree local_decl;
> > !   tree subblock;
> > !   unsigned int i;
> > ! 
> > !   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, abstract_vec);
> > ! 
> > !   for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
> > !     {
> > !       local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i);
> > !       if ((VAR_P (local_decl) && !TREE_STATIC (local_decl))
> > ! 	  || TREE_CODE (local_decl) == PARM_DECL)
> > ! 	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, abstract_vec);
> > ! }
> > ! 
> > ! /* 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, vec<tree> &abstract_vec)
> > ! {
> > !   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))
> > ! 	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), 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.
> > ! 
> > !    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)
> >   {
> >     dw_die_ref old_die;
> > -   tree save_fn;
> > -   tree context;
> > -   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;
> > -   struct call_arg_loc_node *old_call_arg_locations;
> >   
> >     /* Make sure we have the actual abstract inline, not a clone.  */
> >     decl = DECL_ORIGIN (decl);
> >   
> >     old_die = lookup_decl_die (decl);
> > !   if (old_die && get_AT (old_die, DW_AT_inline))
> >       /* We've already generated the abstract instance.  */
> >       return;
> >   
> > !   /* We can be called while recursively when seeing block defining inlined subroutine
> > !      DIE.  Be sure to not clobber the outer location table nor use it or we would
> > !      get locations in abstract instantces.  */
> > !   old_decl_loc_table = decl_loc_table;
> > !   decl_loc_table = NULL;
> > !   old_cached_dw_loc_list_table = cached_dw_loc_list_table;
> > !   cached_dw_loc_list_table = NULL;
> > !   old_call_arg_locations = call_arg_locations;
> > !   call_arg_locations = NULL;
> > !   old_call_site_count = call_site_count;
> > !   call_site_count = -1;
> > !   old_tail_call_site_count = tail_call_site_count;
> > !   tail_call_site_count = -1;
> > ! 
> > !   /* Be sure we've emitted the in-class declaration DIE (if any) first, so
> > !      we don't get confused by DECL_ABSTRACT_P.  */
> > !   if (debug_info_level > DINFO_LEVEL_TERSE)
> >       {
> > !       context = decl_class_context (decl);
> > !       if (context)
> > ! 	gen_type_die_for_member
> > ! 	  (context, decl, decl_function_context (decl) ? NULL : comp_unit_die ());
> >       }
> >   
> > !   /* Pretend we've just finished compiling this function.  */
> > !   save_fn = current_function_decl;
> > !   current_function_decl = decl;
> > ! 
> > !   auto_vec<tree, 64> abstract_vec;
> > !   set_decl_abstract_flags (decl, abstract_vec);
> > !   dwarf2out_decl (decl);
> > !   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;
> > !   cached_dw_loc_list_table = old_cached_dw_loc_list_table;
> > !   call_arg_locations = old_call_arg_locations;
> > !   call_site_count = old_call_site_count;
> > !   tail_call_site_count = old_tail_call_site_count;
> >   }
> >   
> >   /* Helper function of premark_used_types() which gets called through
> > --- 21864,21908 ----
> >       }
> >   }
> >   \f
> > ! /* Mark the early DIE for DECL as the abstract instance.  */
> >   
> >   static void
> >   dwarf2out_abstract_function (tree decl)
> >   {
> >     dw_die_ref old_die;
> >   
> >     /* Make sure we have the actual abstract inline, not a clone.  */
> >     decl = DECL_ORIGIN (decl);
> >   
> > +   if (DECL_IGNORED_P (decl))
> > +     return;
> > + 
> >     old_die = lookup_decl_die (decl);
> > !   /* With early debug we always have an old DIE.  */
> > !   gcc_assert (old_die != NULL);
> > !   if (get_AT (old_die, DW_AT_inline))
> >       /* We've already generated the abstract instance.  */
> >       return;
> >   
> > !   /* Go ahead and put DW_AT_inline on the DIE.  */
> > !   if (DECL_DECLARED_INLINE_P (decl))
> >       {
> > !       if (cgraph_function_possibly_inlined_p (decl))
> > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_inlined);
> > !       else
> > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_not_inlined);
> > !     }
> > !   else
> > !     {
> > !       if (cgraph_function_possibly_inlined_p (decl))
> > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_inlined);
> > !       else
> > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_not_inlined);
> >       }
> >   
> > !   if (DECL_DECLARED_INLINE_P (decl)
> > !       && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
> > !     add_AT_flag (old_die, DW_AT_artificial, 1);
> >   }
> >   
> >   /* Helper function of premark_used_types() which gets called through
> > *************** gen_subprogram_die (tree decl, dw_die_re
> > *** 21901,21907 ****
> >         if (old_die && old_die->die_parent == NULL)
> >   	add_child_die (context_die, old_die);
> >   
> > !       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.  */
> > --- 22124,22135 ----
> >         if (old_die && old_die->die_parent == NULL)
> >   	add_child_die (context_die, old_die);
> >   
> > !       dw_die_ref c;
> > !       if (old_die
> > ! 	  && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
> > ! 	  /* ???  In LTO all origin DIEs still refer to the early
> > ! 	     debug copy.  Detect that.  */
> > ! 	  && get_AT (c, DW_AT_inline))
> >   	{
> >   	  /* If we have a DW_AT_abstract_origin we have a working
> >   	     cached version.  */
> > *************** gen_subprogram_die (tree decl, dw_die_re
> > *** 21969,21975 ****
> >   	   || (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)
> > --- 22197,22204 ----
> >   	   || (old_die->die_parent
> >   	       && old_die->die_parent->die_tag == DW_TAG_module)
> >   	   || context_die == NULL)
> > ! 	  /* ???  In LTO we do not see any of the location attributes.  */
> > ! 	   && ((DECL_ARTIFICIAL (decl) || in_lto_p)
> >   	       || (get_AT_file (old_die, DW_AT_decl_file) == file_index
> >   		   && (get_AT_unsigned (old_die, DW_AT_decl_line)
> >   		       == (unsigned) s.line)
> > *************** gen_variable_die (tree decl, tree origin
> > *** 22836,22841 ****
> > --- 23065,23088 ----
> >   	  /* If a DIE was dumped early, it still needs location info.
> >   	     Skip to where we fill the location bits.  */
> >   	  var_die = old_die;
> > + 
> > + 	  /* ???  In LTRANS we cannot annotate early created variably
> > + 	     modified type DIEs without copying them and adjusting all
> > + 	     references to them.  Thus we dumped them again, also add a
> > + 	     reference to them.  */
> > + 	  tree type = TREE_TYPE (decl_or_origin);
> > + 	  if (in_lto_p
> > + 	      && variably_modified_type_p
> > + 		   (type, decl_function_context (decl_or_origin)))
> > + 	    {
> > + 	      if (decl_by_reference_p (decl_or_origin))
> > + 		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),
> > + 				    false, context_die);
> > + 	    }
> > + 
> >   	  goto gen_variable_die_location;
> >   	}
> >       }
> > *************** gen_inlined_subroutine_die (tree stmt, d
> > *** 23236,23247 ****
> >     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
> > -      a die whose origin die hasn't been emitted, and crashing.  */
> > -   dwarf2out_abstract_function (decl);
> > - 
> >     if (! BLOCK_ABSTRACT (stmt))
> >       {
> >         dw_die_ref subr_die
> > --- 23483,23488 ----
> > *************** process_scope_var (tree stmt, tree decl,
> > *** 24868,24874 ****
> >   					     stmt, context_die);
> >       }
> >     else
> > !     gen_decl_die (decl, origin, NULL, context_die);
> >   }
> >   
> >   /* Generate all of the decls declared within a given scope and (recursively)
> > --- 25109,25128 ----
> >   					     stmt, context_die);
> >       }
> >     else
> > !     {
> > !       if (decl && DECL_P (decl))
> > ! 	{
> > ! 	  die = lookup_decl_die (decl);
> > ! 
> > ! 	  /* Early created DIEs do not have a parent as the decls refer
> > ! 	     to the function as DECL_CONTEXT rather than the BLOCK.  */
> > ! 	  if (in_lto_p
> > ! 	      && die && die->die_parent == NULL)
> > ! 	    add_child_die (context_die, die);
> > ! 	}
> > ! 
> > !       gen_decl_die (decl, origin, NULL, context_die);
> > !     }
> >   }
> >   
> >   /* Generate all of the decls declared within a given scope and (recursively)
> > *************** gen_decl_die (tree decl, tree origin, st
> > *** 25288,25295 ****
> >   				     ? DECL_ORIGIN (origin)
> >   				     : DECL_ABSTRACT_ORIGIN (decl));
> >   
> > !       /* If we're emitting an out-of-line copy of an inline function,
> > ! 	 emit info for the abstract instance and set up to refer to it.  */
> >         else if (cgraph_function_possibly_inlined_p (decl)
> >   	       && ! DECL_ABSTRACT_P (decl)
> >   	       && ! class_or_namespace_scope_p (context_die)
> > --- 25542,25549 ----
> >   				     ? DECL_ORIGIN (origin)
> >   				     : DECL_ABSTRACT_ORIGIN (decl));
> >   
> > !       /* If we're emitting a possibly inlined function emit it as
> > !          abstract instance.  */
> >         else if (cgraph_function_possibly_inlined_p (decl)
> >   	       && ! DECL_ABSTRACT_P (decl)
> >   	       && ! class_or_namespace_scope_p (context_die)
> > *************** gen_decl_die (tree decl, tree origin, st
> > *** 25303,25309 ****
> >   	}
> >   
> >         /* Otherwise we're emitting the primary DIE for this decl.  */
> > !       else if (debug_info_level > DINFO_LEVEL_TERSE)
> >   	{
> >   	  /* Before we describe the FUNCTION_DECL itself, make sure that we
> >   	     have its containing type.  */
> > --- 25557,25565 ----
> >   	}
> >   
> >         /* Otherwise we're emitting the primary DIE for this decl.  */
> > !       else if (debug_info_level > DINFO_LEVEL_TERSE
> > ! 	       /* Do not generate stray type DIEs in late LTO dumping.  */
> > ! 	       && early_dwarf)
> >   	{
> >   	  /* Before we describe the FUNCTION_DECL itself, make sure that we
> >   	     have its containing type.  */
> > *************** gen_decl_die (tree decl, tree origin, st
> > *** 25370,25389 ****
> >         if (debug_info_level <= DINFO_LEVEL_TERSE)
> >   	break;
> >   
> > !       /* Output any DIEs that are needed to specify the type of this data
> > ! 	 object.  */
> > !       if (decl_by_reference_p (decl_or_origin))
> > ! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > !       else
> > ! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> >   
> > !       /* And its containing type.  */
> > !       class_origin = decl_class_context (decl_or_origin);
> > !       if (class_origin != NULL_TREE)
> > ! 	gen_type_die_for_member (class_origin, decl_or_origin, context_die);
> >   
> > !       /* And its containing namespace.  */
> > !       context_die = declare_in_namespace (decl_or_origin, context_die);
> >   
> >         /* Now output the DIE to represent the data object itself.  This gets
> >   	 complicated because of the possibility that the VAR_DECL really
> > --- 25626,25661 ----
> >         if (debug_info_level <= DINFO_LEVEL_TERSE)
> >   	break;
> >   
> > !       /* Avoid generating stray type DIEs during late dwarf dumping.
> > !          All types have been dumped early.  */
> > !       if (! lookup_decl_die (decl_or_origin)
> > ! 	  /* ???  But in LTRANS we cannot annotate early created variably
> > ! 	     modified type DIEs without copying them and adjusting all
> > ! 	     references to them.  Dump them again as happens for inlining
> > ! 	     which copies both the decl and the types.  */
> > ! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
> > ! 	     in VLA bound information for example.  */
> > ! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
> > ! 						current_function_decl)))
> > ! 	{
> > ! 	  /* Output any DIEs that are needed to specify the type of this data
> > ! 	     object.  */
> > ! 	  if (decl_by_reference_p (decl_or_origin))
> > ! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > ! 	  else
> > ! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> > ! 	}
> >   
> > !       if (early_dwarf)
> > ! 	{
> > ! 	  /* And its containing type.  */
> > ! 	  class_origin = decl_class_context (decl_or_origin);
> > ! 	  if (class_origin != NULL_TREE)
> > ! 	    gen_type_die_for_member (class_origin, decl_or_origin, context_die);
> >   
> > ! 	  /* And its containing namespace.  */
> > ! 	  context_die = declare_in_namespace (decl_or_origin, context_die);
> > ! 	}
> >   
> >         /* Now output the DIE to represent the data object itself.  This gets
> >   	 complicated because of the possibility that the VAR_DECL really
> > *************** gen_decl_die (tree decl, tree origin, st
> > *** 25413,25422 ****
> >         break;
> >   
> >       case PARM_DECL:
> > !       if (DECL_BY_REFERENCE (decl_or_origin))
> > ! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > !       else
> > ! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> >         return gen_formal_parameter_die (decl, origin,
> >   				       true /* Emit name attribute.  */,
> >   				       context_die);
> > --- 25685,25707 ----
> >         break;
> >   
> >       case PARM_DECL:
> > !       /* Avoid generating stray type DIEs during late dwarf dumping.
> > !          All types have been dumped early.  */
> > !       if (! lookup_decl_die (decl_or_origin)
> > ! 	  /* ???  But in LTRANS we cannot annotate early created variably
> > ! 	     modified type DIEs without copying them and adjusting all
> > ! 	     references to them.  Dump them again as happens for inlining
> > ! 	     which copies both the decl and the types.  */
> > ! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
> > ! 	     in VLA bound information for example.  */
> > ! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
> > ! 						current_function_decl)))
> > ! 	{
> > ! 	  if (DECL_BY_REFERENCE (decl_or_origin))
> > ! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > ! 	  else
> > ! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> > ! 	}
> >         return gen_formal_parameter_die (decl, origin,
> >   				       true /* Emit name attribute.  */,
> >   				       context_die);
> > *************** dwarf2out_early_global_decl (tree decl)
> > *** 25493,25498 ****
> > --- 25778,25793 ----
> >   	      dwarf2out_decl (context);
> >   	    }
> >   
> > + 	  /* Emit an abstract origin of a function first.  This happens
> > + 	     with C++ constructor clones for example and makes
> > + 	     dwarf2out_abstract_function happy which requires the early
> > + 	     DIE of the abstract instance to be present.  */
> > + 	  if (DECL_ABSTRACT_ORIGIN (decl))
> > + 	    {
> > + 	      current_function_decl = DECL_ABSTRACT_ORIGIN (decl);
> > + 	      dwarf2out_decl (DECL_ABSTRACT_ORIGIN (decl));
> > + 	    }
> > + 
> >   	  current_function_decl = decl;
> >   	}
> >         dwarf2out_decl (decl);
> > *************** dwarf2out_late_global_decl (tree decl)
> > *** 25515,25521 ****
> >       {
> >         dw_die_ref die = lookup_decl_die (decl);
> >   
> > !       /* We have to generate early debug late for LTO.  */
> >         if (! die && in_lto_p)
> >   	{
> >   	  dwarf2out_decl (decl);
> > --- 25810,25818 ----
> >       {
> >         dw_die_ref die = lookup_decl_die (decl);
> >   
> > !       /* We may have to generate early debug late for LTO in case debug
> > !          was not enabled at compile-time or the target doesn't support
> > ! 	 the LTO early debug scheme.  */
> >         if (! die && in_lto_p)
> >   	{
> >   	  dwarf2out_decl (decl);
> > *************** output_macinfo_op (macinfo_entry *ref)
> > *** 26892,26898 ****
> >       case DW_MACRO_import:
> >         dw2_asm_output_data (1, ref->code, "Import");
> >         ASM_GENERATE_INTERNAL_LABEL (label,
> > ! 				   DEBUG_MACRO_SECTION_LABEL, ref->lineno);
> >         dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
> >         break;
> >       default:
> > --- 27189,27196 ----
> >       case DW_MACRO_import:
> >         dw2_asm_output_data (1, ref->code, "Import");
> >         ASM_GENERATE_INTERNAL_LABEL (label,
> > ! 				   DEBUG_MACRO_SECTION_LABEL,
> > ! 				   ref->lineno + macinfo_label_base);
> >         dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
> >         break;
> >       default:
> > *************** save_macinfo_strings (void)
> > *** 27066,27072 ****
> >   /* Output macinfo section(s).  */
> >   
> >   static void
> > ! output_macinfo (void)
> >   {
> >     unsigned i;
> >     unsigned long length = vec_safe_length (macinfo_table);
> > --- 27364,27370 ----
> >   /* Output macinfo section(s).  */
> >   
> >   static void
> > ! output_macinfo (const char *debug_line_label, bool early_lto_debug)
> >   {
> >     unsigned i;
> >     unsigned long length = vec_safe_length (macinfo_table);
> > *************** output_macinfo (void)
> > *** 27092,27100 ****
> >   	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
> >         else
> >   	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
> > !       dw2_asm_output_offset (DWARF_OFFSET_SIZE,
> > !                              (!dwarf_split_debug_info ? debug_line_section_label
> > !                               : debug_skeleton_line_section_label),
> >                                debug_line_section, NULL);
> >       }
> >   
> > --- 27390,27396 ----
> >   	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
> >         else
> >   	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
> > !       dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_line_label,
> >                                debug_line_section, NULL);
> >       }
> >   
> > *************** output_macinfo (void)
> > *** 27148,27153 ****
> > --- 27444,27453 ----
> >     if (!macinfo_htab)
> >       return;
> >   
> > +   /* Save the number of transparent includes so we can adjust the
> > +      label number for the fat LTO object DWARF.  */
> > +   unsigned macinfo_label_base_adj = macinfo_htab->elements ();
> > + 
> >     delete macinfo_htab;
> >     macinfo_htab = NULL;
> >   
> > *************** output_macinfo (void)
> > *** 27167,27177 ****
> >   	  dw2_asm_output_data (1, 0, "End compilation unit");
> >   	  targetm.asm_out.named_section (debug_macinfo_section_name,
> >   					 SECTION_DEBUG
> > ! 					 | SECTION_LINKONCE,
> >   					 comdat_key);
> >   	  ASM_GENERATE_INTERNAL_LABEL (label,
> >   				       DEBUG_MACRO_SECTION_LABEL,
> > ! 				       ref->lineno);
> >   	  ASM_OUTPUT_LABEL (asm_out_file, label);
> >   	  ref->code = 0;
> >   	  ref->info = NULL;
> > --- 27467,27479 ----
> >   	  dw2_asm_output_data (1, 0, "End compilation unit");
> >   	  targetm.asm_out.named_section (debug_macinfo_section_name,
> >   					 SECTION_DEBUG
> > ! 					 | SECTION_LINKONCE
> > ! 					 | (early_lto_debug
> > ! 					    ? SECTION_EXCLUDE : 0),
> >   					 comdat_key);
> >   	  ASM_GENERATE_INTERNAL_LABEL (label,
> >   				       DEBUG_MACRO_SECTION_LABEL,
> > ! 				       ref->lineno + macinfo_label_base);
> >   	  ASM_OUTPUT_LABEL (asm_out_file, label);
> >   	  ref->code = 0;
> >   	  ref->info = NULL;
> > *************** output_macinfo (void)
> > *** 27192,27300 ****
> >         default:
> >   	gcc_unreachable ();
> >         }
> >   }
> >   
> > ! /* Initialize the various sections and labels for dwarf output.  */
> >   
> >   static void
> > ! init_sections_and_labels (void)
> >   {
> > !   if (!dwarf_split_debug_info)
> >       {
> > !       debug_info_section = get_section (DEBUG_INFO_SECTION,
> > !                                         SECTION_DEBUG, NULL);
> > !       debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > !                                           SECTION_DEBUG, NULL);
> > !       debug_loc_section = get_section (dwarf_version >= 5
> > ! 				       ? DEBUG_LOCLISTS_SECTION
> > ! 				       : DEBUG_LOC_SECTION,
> > !                                        SECTION_DEBUG, NULL);
> > !       debug_macinfo_section_name
> > ! 	= (dwarf_strict && dwarf_version < 5)
> > ! 	  ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
> > !       debug_macinfo_section = get_section (debug_macinfo_section_name,
> > ! 					   SECTION_DEBUG, NULL);
> >       }
> >     else
> >       {
> > !       debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
> > !                                         SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > !       debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
> > !                                           SECTION_DEBUG | SECTION_EXCLUDE,
> > !                                           NULL);
> > !       debug_addr_section = get_section (DEBUG_ADDR_SECTION,
> > !                                         SECTION_DEBUG, NULL);
> > !       debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
> > !                                                  SECTION_DEBUG, NULL);
> > !       debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > !                                                    SECTION_DEBUG, NULL);
> > !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> > !                                   DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0);
> > ! 
> > !       /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
> > !          the main .o, but the skeleton_line goes into the split off dwo.  */
> > !       debug_skeleton_line_section
> > !         = get_section (DEBUG_DWO_LINE_SECTION,
> > ! 		       SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > !                                    DEBUG_SKELETON_LINE_SECTION_LABEL, 0);
> > !       debug_str_offsets_section = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
> > !                                                SECTION_DEBUG | SECTION_EXCLUDE,
> > !                                                NULL);
> > !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> > !                                    DEBUG_SKELETON_INFO_SECTION_LABEL, 0);
> > !       debug_loc_section = get_section (dwarf_version >= 5
> > ! 				       ? DEBUG_DWO_LOCLISTS_SECTION
> > ! 				       : DEBUG_DWO_LOC_SECTION,
> > !                                        SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > !       debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
> > !                                            DEBUG_STR_DWO_SECTION_FLAGS, NULL);
> > !       debug_macinfo_section_name
> > ! 	= (dwarf_strict && dwarf_version < 5)
> > ! 	  ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
> > !       debug_macinfo_section = get_section (debug_macinfo_section_name,
> >   					   SECTION_DEBUG | SECTION_EXCLUDE,
> >   					   NULL);
> > !     }
> > !   debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
> > ! 				       SECTION_DEBUG, NULL);
> > !   debug_line_section = get_section (DEBUG_LINE_SECTION,
> > ! 				    SECTION_DEBUG, NULL);
> > !   debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
> > ! 					SECTION_DEBUG, NULL);
> > !   debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
> >   					SECTION_DEBUG, NULL);
> > !   debug_str_section = get_section (DEBUG_STR_SECTION,
> > ! 				   DEBUG_STR_SECTION_FLAGS, NULL);
> > !   if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
> > !     debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
> > ! 					  DEBUG_STR_SECTION_FLAGS, NULL);
> > ! 
> > !   debug_ranges_section = get_section (dwarf_version >= 5
> > ! 				      ? DEBUG_RNGLISTS_SECTION
> > ! 				      : DEBUG_RANGES_SECTION,
> > ! 				      SECTION_DEBUG, NULL);
> > !   debug_frame_section = get_section (DEBUG_FRAME_SECTION,
> > ! 				     SECTION_DEBUG, NULL);
> >   
> >     ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
> > ! 			       DEBUG_ABBREV_SECTION_LABEL, 0);
> >     ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
> > ! 			       DEBUG_INFO_SECTION_LABEL, 0);
> >     ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
> > ! 			       DEBUG_LINE_SECTION_LABEL, 0);
> >     ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
> > ! 			       DEBUG_RANGES_SECTION_LABEL, 0);
> >     if (dwarf_version >= 5 && dwarf_split_debug_info)
> >       ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
> > ! 				 DEBUG_RANGES_SECTION_LABEL, 1);
> >     ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
> > !                                DEBUG_ADDR_SECTION_LABEL, 0);
> >     ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
> >   			       (dwarf_strict && dwarf_version < 5)
> >   			       ? DEBUG_MACINFO_SECTION_LABEL
> > ! 			       : DEBUG_MACRO_SECTION_LABEL, 0);
> > !   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0);
> >   }
> >   
> >   /* Set up for Dwarf output at the start of compilation.  */
> > --- 27494,27685 ----
> >         default:
> >   	gcc_unreachable ();
> >         }
> > + 
> > +   macinfo_label_base += macinfo_label_base_adj;
> >   }
> >   
> > ! /* Initialize the various sections and labels for dwarf output and prefix
> > !    them with PREFIX if non-NULL.  */
> >   
> >   static void
> > ! init_sections_and_labels (bool early_lto_debug)
> >   {
> > !   /* As we may get called multiple times have a generation count for labels.  */
> > !   static unsigned generation = 0;
> > ! 
> > !   if (early_lto_debug)
> >       {
> > !       if (!dwarf_split_debug_info)
> > ! 	{
> > ! 	  debug_info_section = get_section (DEBUG_LTO_INFO_SECTION,
> > ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> > ! 					    NULL);
> > ! 	  debug_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
> > ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> > ! 					      NULL);
> > ! 	  debug_macinfo_section_name = ((dwarf_strict && dwarf_version < 5)
> > ! 					? DEBUG_LTO_MACINFO_SECTION
> > ! 					: DEBUG_LTO_MACRO_SECTION);
> > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > ! 					       SECTION_DEBUG
> > ! 					       | SECTION_EXCLUDE, NULL);
> > ! 	  /* For macro info we have to refer to a debug_line section, so similar
> > ! 	     to split-dwarf emit a skeleton one for early debug.  */
> > ! 	  debug_skeleton_line_section
> > ! 	    = get_section (DEBUG_LTO_LINE_SECTION,
> > ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> > ! 				       generation);
> > ! 	}
> > !       else
> > ! 	{
> > ! 	  /* ???  Which of the following do we need early?  */
> > ! 	  debug_info_section = get_section (DEBUG_LTO_DWO_INFO_SECTION,
> > ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> > ! 					    NULL);
> > ! 	  debug_abbrev_section = get_section (DEBUG_LTO_DWO_ABBREV_SECTION,
> > ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> > ! 					      NULL);
> > ! 	  debug_skeleton_info_section = get_section (DEBUG_LTO_INFO_SECTION,
> > ! 						     SECTION_DEBUG
> > ! 						     | SECTION_EXCLUDE, NULL);
> > ! 	  debug_skeleton_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
> > ! 						       SECTION_DEBUG
> > ! 						       | SECTION_EXCLUDE, NULL);
> > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> > ! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
> > ! 				       generation);
> > ! 
> > ! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
> > ! 	     the main .o, but the skeleton_line goes into the split off dwo.  */
> > ! 	  debug_skeleton_line_section
> > ! 	    = get_section (DEBUG_LTO_LINE_SECTION,
> > ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> > ! 				       generation);
> > ! 	  debug_str_offsets_section
> > ! 	    = get_section (DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
> > ! 			   SECTION_DEBUG | SECTION_EXCLUDE,
> > ! 			   NULL);
> > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> > ! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
> > ! 				       generation);
> > ! 	  debug_str_dwo_section = get_section (DEBUG_LTO_STR_DWO_SECTION,
> > ! 					       DEBUG_STR_DWO_SECTION_FLAGS, NULL);
> > ! 	  debug_macinfo_section_name
> > ! 	    = (dwarf_strict
> > ! 	       ? DEBUG_LTO_DWO_MACINFO_SECTION : DEBUG_LTO_DWO_MACRO_SECTION);
> > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > ! 					       SECTION_DEBUG | SECTION_EXCLUDE,
> > ! 					       NULL);
> > ! 	}
> > !       debug_str_section = get_section (DEBUG_LTO_STR_SECTION,
> > ! 				       DEBUG_STR_SECTION_FLAGS
> > ! 				       | SECTION_EXCLUDE, NULL);
> >       }
> >     else
> >       {
> > !       if (!dwarf_split_debug_info)
> > ! 	{
> > ! 	  debug_info_section = get_section (DEBUG_INFO_SECTION,
> > ! 					    SECTION_DEBUG, NULL);
> > ! 	  debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > ! 					      SECTION_DEBUG, NULL);
> > ! 	  debug_loc_section = get_section (DEBUG_LOC_SECTION,
> > ! 					   SECTION_DEBUG, NULL);
> > ! 	  debug_macinfo_section_name
> > ! 	      = dwarf_strict ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
> > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > ! 					       SECTION_DEBUG, NULL);
> > ! 	}
> > !       else
> > ! 	{
> > ! 	  debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
> > ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> > ! 					    NULL);
> > ! 	  debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
> > ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> > ! 					      NULL);
> > ! 	  debug_addr_section = get_section (DEBUG_ADDR_SECTION,
> > ! 					    SECTION_DEBUG, NULL);
> > ! 	  debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
> > ! 						     SECTION_DEBUG, NULL);
> > ! 	  debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > ! 						       SECTION_DEBUG, NULL);
> > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> > ! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
> > ! 				       generation);
> > ! 
> > ! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections
> > ! 	     stay in the main .o, but the skeleton_line goes into the
> > ! 	     split off dwo.  */
> > ! 	  debug_skeleton_line_section
> > ! 	      = get_section (DEBUG_DWO_LINE_SECTION,
> > ! 			     SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> > ! 				       generation);
> > ! 	  debug_str_offsets_section
> > ! 	    = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
> > ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> > ! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
> > ! 				       generation);
> > ! 	  debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION,
> >   					   SECTION_DEBUG | SECTION_EXCLUDE,
> >   					   NULL);
> > ! 	  debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
> > ! 					       DEBUG_STR_DWO_SECTION_FLAGS,
> > ! 					       NULL);
> > ! 	  debug_macinfo_section_name
> > ! 	    = (dwarf_strict && dwarf_version < 5)
> > ! 	      ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
> > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > ! 					       SECTION_DEBUG | SECTION_EXCLUDE,
> > ! 					       NULL);
> > ! 	}
> > !       debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
> > ! 					   SECTION_DEBUG, NULL);
> > !       debug_line_section = get_section (DEBUG_LINE_SECTION,
> >   					SECTION_DEBUG, NULL);
> > !       debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
> > ! 					    SECTION_DEBUG, NULL);
> > !       debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
> > ! 					    SECTION_DEBUG, NULL);
> > !       debug_str_section = get_section (DEBUG_STR_SECTION,
> > ! 				       DEBUG_STR_SECTION_FLAGS, NULL);
> > !       debug_ranges_section = get_section (dwarf_version >= 5
> > ! 					  ? DEBUG_RNGLISTS_SECTION
> > ! 					  : DEBUG_RANGES_SECTION,
> > ! 					  SECTION_DEBUG, NULL);
> > !       debug_frame_section = get_section (DEBUG_FRAME_SECTION,
> > ! 					 SECTION_DEBUG, NULL);
> > !     }
> >   
> >     ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
> > ! 			       DEBUG_ABBREV_SECTION_LABEL, generation);
> >     ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
> > ! 			       DEBUG_INFO_SECTION_LABEL, generation);
> > !   info_section_emitted = false;
> >     ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
> > ! 			       DEBUG_LINE_SECTION_LABEL, generation);
> >     ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
> > ! 			       DEBUG_RANGES_SECTION_LABEL, generation);
> >     if (dwarf_version >= 5 && dwarf_split_debug_info)
> >       ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
> > ! 				 DEBUG_RANGES_SECTION_LABEL, 2 + generation);
> >     ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
> > !                                DEBUG_ADDR_SECTION_LABEL, generation);
> >     ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
> >   			       (dwarf_strict && dwarf_version < 5)
> >   			       ? DEBUG_MACINFO_SECTION_LABEL
> > ! 			       : DEBUG_MACRO_SECTION_LABEL, generation);
> > !   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL,
> > ! 			       generation);
> > ! 
> > !   ++generation;
> >   }
> >   
> >   /* Set up for Dwarf output at the start of compilation.  */
> > *************** flush_limbo_die_list (void)
> > *** 29641,29646 ****
> > --- 30026,30047 ----
> >       }
> >   }
> >   
> > + /* Reset DIEs so we can output them again.  */
> > + 
> > + static void
> > + reset_dies (dw_die_ref die)
> > + {
> > +   dw_die_ref c;
> > + 
> > +   /* Remove stuff we re-generate.  */
> > +   die->die_mark = 0;
> > +   die->die_offset = 0;
> > +   die->die_abbrev = 0;
> > +   remove_AT (die, DW_AT_sibling);
> > + 
> > +   FOR_EACH_CHILD (die, c, reset_dies (c));
> > + }
> > + 
> >   /* Output stuff that dwarf requires at the end of every file,
> >      and generate the DWARF-2 debugging info.  */
> >   
> > *************** dwarf2out_finish (const char *)
> > *** 29667,29672 ****
> > --- 30068,30113 ----
> >   
> >     gen_remaining_tmpl_value_param_die_attribute ();
> >   
> > +   if (flag_generate_lto)
> > +     {
> > +       gcc_assert (flag_fat_lto_objects);
> > + 
> > +       /* Prune stuff so that dwarf2out_finish runs successfully
> > + 	 for the fat part of the object.  */
> > +       reset_dies (comp_unit_die ());
> > +       for (limbo_die_node *node = cu_die_list; node; node = node->next)
> > + 	reset_dies (node->die);
> > + 
> > +       hash_table<comdat_type_hasher> comdat_type_table (100);
> > +       for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
> > + 	{
> > + 	  comdat_type_node **slot
> > + 	      = comdat_type_table.find_slot (ctnode, INSERT);
> > + 
> > + 	  /* Don't reset types twice.  */
> > + 	  if (*slot != HTAB_EMPTY_ENTRY)
> > + 	    continue;
> > + 
> > + 	  /* Add a pointer to the line table for the main compilation unit
> > + 	     so that the debugger can make sense of DW_AT_decl_file
> > + 	     attributes.  */
> > + 	  if (debug_info_level >= DINFO_LEVEL_TERSE)
> > + 	    reset_dies (ctnode->root_die);
> > + 
> > + 	  *slot = ctnode;
> > + 	}
> > + 
> > +       /* Reset die CU symbol so we don't output it twice.  */
> > +       comp_unit_die ()->die_id.die_symbol = NULL;
> > + 
> > +       /* Remove DW_AT_macro from the early output.  */
> > +       if (have_macinfo)
> > + 	remove_AT (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE);
> > + 
> > +       /* Remove indirect string decisions.  */
> > +       debug_str_hash->traverse<void *, reset_indirect_string> (NULL);
> > +     }
> > + 
> >   #if ENABLE_ASSERT_CHECKING
> >     {
> >       dw_die_ref die = comp_unit_die (), c;
> > *************** dwarf2out_finish (const char *)
> > *** 29677,29683 ****
> >     move_marked_base_types ();
> >   
> >     /* Initialize sections and labels used for actual assembler output.  */
> > !   init_sections_and_labels ();
> >   
> >     /* Traverse the DIE's and add sibling attributes to those DIE's that
> >        have children.  */
> > --- 30118,30124 ----
> >     move_marked_base_types ();
> >   
> >     /* Initialize sections and labels used for actual assembler output.  */
> > !   init_sections_and_labels (false);
> >   
> >     /* Traverse the DIE's and add sibling attributes to those DIE's that
> >        have children.  */
> > *************** dwarf2out_finish (const char *)
> > *** 29772,29780 ****
> >   		    debug_line_section_label);
> >   
> >     if (have_macinfo)
> > !     add_AT_macptr (comp_unit_die (),
> > ! 		   dwarf_version >= 5 ? DW_AT_macros
> > ! 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
> >   		   macinfo_section_label);
> >   
> >     if (dwarf_split_debug_info)
> > --- 30213,30219 ----
> >   		    debug_line_section_label);
> >   
> >     if (have_macinfo)
> > !     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
> >   		   macinfo_section_label);
> >   
> >     if (dwarf_split_debug_info)
> > *************** dwarf2out_finish (const char *)
> > *** 29979,29985 ****
> >       {
> >         switch_to_section (debug_macinfo_section);
> >         ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> > !       output_macinfo ();
> >         dw2_asm_output_data (1, 0, "End compilation unit");
> >       }
> >   
> > --- 30418,30425 ----
> >       {
> >         switch_to_section (debug_macinfo_section);
> >         ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> > !       output_macinfo (!dwarf_split_debug_info ? debug_line_section_label
> > ! 		      : debug_skeleton_line_section_label, false);
> >         dw2_asm_output_data (1, 0, "End compilation unit");
> >       }
> >   
> > *************** note_variable_value_in_expr (dw_die_ref
> > *** 30200,30205 ****
> > --- 30640,30659 ----
> >         {
> >   	tree decl = loc->dw_loc_oprnd1.v.val_decl_ref;
> >   	dw_die_ref ref = lookup_decl_die (decl);
> > + 	if (! ref && flag_generate_lto)
> > + 	  {
> > + 	    /* ???  This is somewhat a hack because we do not create DIEs
> > + 	       for variables not in BLOCK trees early but when generating
> > + 	       early LTO output we need the dw_val_class_decl_ref to be
> > + 	       fully resolved.  For fat LTO objects we'd also like to
> > + 	       undo this after LTO dwarf output.  */
> > + 	    gcc_assert (DECL_CONTEXT (decl));
> > + 	    dw_die_ref ctx = lookup_decl_die (DECL_CONTEXT (decl));
> > + 	    gcc_assert (ctx != NULL);
> > + 	    gen_decl_die (decl, NULL_TREE, NULL, ctx);
> > + 	    ref = lookup_decl_die (decl);
> > + 	    gcc_assert (ref != NULL);
> > + 	  }
> >   	if (ref)
> >   	  {
> >   	    loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
> > *************** dwarf2out_early_finish (const char *file
> > *** 30410,30415 ****
> > --- 30864,30982 ----
> >   
> >     /* The early debug phase is now finished.  */
> >     early_dwarf_finished = true;
> > + 
> > +   /* Do not generate DWARF assembler now when not producing LTO bytecode.  */
> > +   if (!flag_generate_lto)
> > +     return;
> > + 
> > +   /* Now as we are going to output for LTO initialize sections and labels
> > +      to the LTO variants.  We don't need a random-seed postfix as other
> > +      LTO sections as linking the LTO debug sections into one in a partial
> > +      link is fine.  */
> > +   init_sections_and_labels (true);
> > + 
> > +   /* The output below is modeled after dwarf2out_finish with all
> > +      location related output removed and some LTO specific changes.
> > +      Some refactoring might make both smaller and easier to match up.  */
> > + 
> > +   /* Traverse the DIE's and add add sibling attributes to those DIE's
> > +      that have children.  */
> > +   add_sibling_attributes (comp_unit_die ());
> > +   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
> > +     add_sibling_attributes (node->die);
> > +   for (comdat_type_node *ctnode = comdat_type_list;
> > +        ctnode != NULL; ctnode = ctnode->next)
> > +     add_sibling_attributes (ctnode->root_die);
> > + 
> > +   if (have_macinfo)
> > +     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
> > + 		   macinfo_section_label);
> > + 
> > +   save_macinfo_strings ();
> > + 
> > +   /* Output all of the compilation units.  We put the main one last so that
> > +      the offsets are available to output_pubnames.  */
> > +   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
> > +     output_comp_unit (node->die, 0, NULL);
> > + 
> > +   hash_table<comdat_type_hasher> comdat_type_table (100);
> > +   for (comdat_type_node *ctnode = comdat_type_list;
> > +        ctnode != NULL; ctnode = ctnode->next)
> > +     {
> > +       comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT);
> > + 
> > +       /* Don't output duplicate types.  */
> > +       if (*slot != HTAB_EMPTY_ENTRY)
> > +         continue;
> > + 
> > +       /* Add a pointer to the line table for the main compilation unit
> > +          so that the debugger can make sense of DW_AT_decl_file
> > +          attributes.  */
> > +       if (debug_info_level >= DINFO_LEVEL_TERSE)
> > +         add_AT_lineptr (ctnode->root_die, DW_AT_stmt_list,
> > +                         (!dwarf_split_debug_info
> > +                          ? debug_line_section_label
> > +                          : debug_skeleton_line_section_label));
> > + 
> > +       output_comdat_type_unit (ctnode);
> > +       *slot = ctnode;
> > +     }
> > + 
> > +   /* The AT_pubnames attribute needs to go in all skeleton dies, including
> > +      both the main_cu and all skeleton TUs.  Making this call unconditional
> > +      would end up either adding a second copy of the AT_pubnames attribute, or
> > +      requiring a special case in add_top_level_skeleton_die_attrs.  */
> > +   if (!dwarf_split_debug_info)
> > +     add_AT_pubnames (comp_unit_die ());
> > + 
> > +   /* Stick a unique symbol to the main debuginfo section.  */
> > +   compute_section_prefix_1 (comp_unit_die (), false);
> > + 
> > +   /* Output the main compilation unit.  We always need it if only for
> > +      the CU symbol.  */
> > +   output_comp_unit (comp_unit_die (), true, NULL);
> > + 
> > +   /* Output the abbreviation table.  */
> > +   if (vec_safe_length (abbrev_die_table) != 1)
> > +     {
> > +       switch_to_section (debug_abbrev_section);
> > +       ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
> > +       output_abbrev_section ();
> > +     }
> > + 
> > +   /* Have to end the macro section.  */
> > +   if (have_macinfo)
> > +     {
> > +       /* We have to save macinfo state if we need to output it again
> > + 	 for the FAT part of the object.  */
> > +       vec<macinfo_entry, va_gc> *saved_macinfo_table = macinfo_table;
> > +       if (flag_fat_lto_objects)
> > + 	macinfo_table = macinfo_table->copy ();
> > + 
> > +       switch_to_section (debug_macinfo_section);
> > +       ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> > +       output_macinfo (debug_skeleton_line_section_label, true);
> > +       dw2_asm_output_data (1, 0, "End compilation unit");
> > + 
> > +       /* Emit a skeleton debug_line section.  */
> > +       switch_to_section (debug_skeleton_line_section);
> > +       ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_line_section_label);
> > +       output_line_info (true);
> > + 
> > +       if (flag_fat_lto_objects)
> > + 	{
> > + 	  vec_free (macinfo_table);
> > + 	  macinfo_table = saved_macinfo_table;
> > + 	}
> > +     }
> > + 
> > + 
> > +   /* If we emitted any indirect strings, output the string table too.  */
> > +   if (debug_str_hash || skeleton_debug_str_hash)
> > +     output_indirect_strings ();
> > + 
> > +   /* Switch back to the text section.  */
> > +   switch_to_section (text_section);
> >   }
> >   
> >   /* Reset all state within dwarf2out.c so that we can rerun the compiler
> > Index: early-lto-debug/gcc/debug.h
> > ===================================================================
> > *** early-lto-debug.orig/gcc/debug.h	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/debug.h	2017-05-16 13:10:49.774239353 +0200
> > *************** struct gcc_debug_hooks
> > *** 147,152 ****
> > --- 147,160 ----
> >     void (* imported_module_or_decl) (tree decl, tree name,
> >   				    tree context, bool child);
> >   
> > +   /* Return true if a DIE for the tree is available and return a symbol
> > +      and offset that can be used to refer to it externally.  */
> > +   bool (* die_ref_for_decl) (tree, const char **, unsigned HOST_WIDE_INT *);
> > + 
> > +   /* Early debug information for the tree is available at symbol plus
> > +      offset externally.  */
> > +   void (* register_external_die) (tree, const char *, unsigned HOST_WIDE_INT);
> > + 
> >     /* DECL is an inline function, whose body is present, but which is
> >        not being output at this point.  */
> >     void (* deferred_inline_function) (tree decl);
> > *************** extern void debug_nothing_tree_tree_tree
> > *** 210,215 ****
> > --- 218,227 ----
> >   extern bool debug_true_const_tree (const_tree);
> >   extern void debug_nothing_rtx_insn (rtx_insn *);
> >   extern void debug_nothing_rtx_code_label (rtx_code_label *);
> > + extern bool debug_false_tree_charstarstar_uhwistar (tree, const char **,
> > + 						    unsigned HOST_WIDE_INT *);
> > + extern void debug_nothing_tree_charstar_uhwi (tree, const char *,
> > + 					      unsigned HOST_WIDE_INT);
> >   
> >   /* Hooks for various debug formats.  */
> >   extern const struct gcc_debug_hooks do_nothing_debug_hooks;
> > Index: early-lto-debug/gcc/debug.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/debug.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/debug.c	2017-05-16 13:10:49.774239353 +0200
> > *************** const struct gcc_debug_hooks do_nothing_
> > *** 48,53 ****
> > --- 48,55 ----
> >     debug_nothing_tree,	         	 /* late_global_decl */
> >     debug_nothing_tree_int,		 /* type_decl */
> >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> >     debug_nothing_tree,		         /* deferred_inline_function */
> >     debug_nothing_tree,		         /* outlining_inline_function */
> >     debug_nothing_rtx_code_label,	         /* label */
> > *************** debug_nothing_tree_int (tree decl ATTRIB
> > *** 146,148 ****
> > --- 148,163 ----
> >   			int local ATTRIBUTE_UNUSED)
> >   {
> >   }
> > + 
> > + bool
> > + debug_false_tree_charstarstar_uhwistar (tree, const char **,
> > + 					unsigned HOST_WIDE_INT *)
> > + {
> > +   return false;
> > + }
> > + 
> > + void
> > + debug_nothing_tree_charstar_uhwi (tree, const char *,
> > + 				  unsigned HOST_WIDE_INT)
> > + {
> > + }
> > Index: early-lto-debug/gcc/dbxout.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/dbxout.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/dbxout.c	2017-05-16 13:10:49.778239419 +0200
> > *************** const struct gcc_debug_hooks dbx_debug_h
> > *** 372,377 ****
> > --- 372,379 ----
> >     dbxout_late_global_decl,		 /* late_global_decl */
> >     dbxout_type_decl,			 /* type_decl */
> >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> >     debug_nothing_tree,		         /* deferred_inline_function */
> >     debug_nothing_tree,		         /* outlining_inline_function */
> >     debug_nothing_rtx_code_label,	         /* label */
> > *************** const struct gcc_debug_hooks xcoff_debug
> > *** 412,417 ****
> > --- 414,421 ----
> >     dbxout_late_global_decl,		 /* late_global_decl */
> >     dbxout_type_decl,			 /* type_decl */
> >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > +   debug_nothing_tree_charstar_uhwi,      /* register_external_die */
> >     debug_nothing_tree,		         /* deferred_inline_function */
> >     debug_nothing_tree,		         /* outlining_inline_function */
> >     debug_nothing_rtx_code_label,	         /* label */
> > Index: early-lto-debug/gcc/sdbout.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/sdbout.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/sdbout.c	2017-05-16 13:10:49.778239419 +0200
> > *************** const struct gcc_debug_hooks sdb_debug_h
> > *** 302,307 ****
> > --- 302,309 ----
> >     sdbout_late_global_decl,		 /* late_global_decl */
> >     sdbout_symbol,			 /* type_decl */
> >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> >     debug_nothing_tree,		         /* deferred_inline_function */
> >     debug_nothing_tree,		         /* outlining_inline_function */
> >     sdbout_label,			         /* label */
> > Index: early-lto-debug/gcc/lto/lto.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/lto/lto.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/lto/lto.c	2017-05-16 13:10:49.778239419 +0200
> > *************** unify_scc (struct data_in *data_in, unsi
> > *** 1632,1637 ****
> > --- 1632,1640 ----
> >   	      free_node (scc->entries[i]);
> >   	    }
> >   
> > + 	  /* Drop DIE references.  */
> > + 	  dref_queue.truncate (0);
> > + 
> >   	  break;
> >   	}
> >   
> > *************** lto_read_decls (struct lto_file_decl_dat
> > *** 1707,1714 ****
> >   						     from);
> >   	  if (len == 1
> >   	      && (TREE_CODE (first) == IDENTIFIER_NODE
> > ! 		  || TREE_CODE (first) == INTEGER_CST
> > ! 		  || TREE_CODE (first) == TRANSLATION_UNIT_DECL))
> >   	    continue;
> >   
> >   	  /* Try to unify the SCC with already existing ones.  */
> > --- 1710,1716 ----
> >   						     from);
> >   	  if (len == 1
> >   	      && (TREE_CODE (first) == IDENTIFIER_NODE
> > ! 		  || TREE_CODE (first) == INTEGER_CST))
> >   	    continue;
> >   
> >   	  /* Try to unify the SCC with already existing ones.  */
> > *************** lto_read_decls (struct lto_file_decl_dat
> > *** 1747,1762 ****
> >   	      if (TREE_CODE (t) == INTEGER_CST
> >   		  && !TREE_OVERFLOW (t))
> >   		cache_integer_cst (t);
> > - 	      /* Register TYPE_DECLs with the debuginfo machinery.  */
> > - 	      if (!flag_wpa
> > - 		  && TREE_CODE (t) == TYPE_DECL)
> > - 		{
> > - 		  /* Dwarf2out needs location information.
> > - 		     TODO: Moving this out of the streamer loop may noticealy
> > - 		     improve ltrans linemap memory use.  */
> > - 		  data_in->location_cache.apply_location_cache ();
> > - 		  debug_hooks->type_decl (t, !DECL_FILE_SCOPE_P (t));
> > - 		}
> >   	      if (!flag_ltrans)
> >   		{
> >   		  /* Register variables and functions with the
> > --- 1749,1754 ----
> > *************** lto_read_decls (struct lto_file_decl_dat
> > *** 1772,1777 ****
> > --- 1764,1777 ----
> >   		    vec_safe_push (tree_with_vars, t);
> >   		}
> >   	    }
> > + 
> > + 	  /* Register DECLs with the debuginfo machinery.  */
> > + 	  while (!dref_queue.is_empty ())
> > + 	    {
> > + 	      dref_entry e = dref_queue.pop ();
> > + 	      debug_hooks->register_external_die (e.decl, e.sym, e.off);
> > + 	    }
> > + 
> >   	  if (seen_type)
> >   	    num_type_scc_trees += len;
> >   	}
> > *************** lto_section_with_id (const char *name, u
> > *** 1951,1957 ****
> >     if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
> >       return 0;
> >     s = strrchr (name, '.');
> > !   return s && sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
> >   }
> >   
> >   /* Create file_data of each sub file id */
> > --- 1951,1962 ----
> >     if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
> >       return 0;
> >     s = strrchr (name, '.');
> > !   if (!s)
> > !     return 0;
> > !   /* If the section is not suffixed with an ID return.  */
> > !   if ((size_t)(s - name) == strlen (section_name_prefix))
> > !     return 0;
> > !   return sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
> >   }
> >   
> >   /* Create file_data of each sub file id */
> > Index: early-lto-debug/gcc/lto-streamer-in.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/lto-streamer-in.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/lto-streamer-in.c	2017-05-16 13:10:49.858240736 +0200
> > *************** along with GCC; see the file COPYING3.
> > *** 41,46 ****
> > --- 41,47 ----
> >   #include "except.h"
> >   #include "cgraph.h"
> >   #include "cfgloop.h"
> > + #include "debug.h"
> >   
> >   
> >   struct freeing_string_slot_hasher : string_slot_hasher
> > *************** input_function (tree fn_decl, struct dat
> > *** 1038,1043 ****
> > --- 1039,1054 ----
> >     DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in);
> >     DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in);
> >   
> > +   /* Read debug args if available.  */
> > +   unsigned n_debugargs = streamer_read_uhwi (ib);
> > +   if (n_debugargs)
> > +     {
> > +       vec<tree, va_gc> **debugargs = decl_debug_args_insert (fn_decl);
> > +       vec_safe_grow (*debugargs, n_debugargs);
> > +       for (unsigned i = 0; i < n_debugargs; ++i)
> > + 	(**debugargs)[i] = stream_read_tree (ib, data_in);
> > +     }
> > + 
> >     /* Read the tree of lexical scopes for the function.  */
> >     DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
> >     unsigned block_leaf_count = streamer_read_uhwi (ib);
> > *************** lto_input_variable_constructor (struct l
> > *** 1318,1323 ****
> > --- 1329,1338 ----
> >   }
> >   
> >   
> > + /* Queue of acummulated decl -> DIE mappings.  Similar to locations those
> > +    are only applied to prevailing tree nodes during tree merging.  */
> > + vec<dref_entry> dref_queue;
> > + 
> >   /* Read the physical representation of a tree node EXPR from
> >      input block IB using the per-file context in DATA_IN.  */
> >   
> > *************** lto_read_tree_1 (struct lto_input_block
> > *** 1337,1342 ****
> > --- 1352,1374 ----
> >         && TREE_CODE (expr) != FUNCTION_DECL
> >         && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
> >       DECL_INITIAL (expr) = stream_read_tree (ib, data_in);
> > + 
> > +   /* Stream references to early generated DIEs.  Keep in sync with the
> > +      trees handled in dwarf2out_register_external_die.  */
> > +   if ((DECL_P (expr)
> > +        && TREE_CODE (expr) != FIELD_DECL
> > +        && TREE_CODE (expr) != DEBUG_EXPR_DECL
> > +        && TREE_CODE (expr) != TYPE_DECL)
> > +       || TREE_CODE (expr) == BLOCK)
> > +     {
> > +       const char *str = streamer_read_string (data_in, ib);
> > +       if (str)
> > + 	{
> > + 	  unsigned HOST_WIDE_INT off = streamer_read_uhwi (ib);
> > + 	  dref_entry e = { expr, str, off };
> > + 	  dref_queue.safe_push (e);
> > + 	}
> > +     }
> >   }
> >   
> >   /* Read the physical representation of a tree node with tag TAG from
> > *************** lto_input_tree (struct lto_input_block *
> > *** 1482,1487 ****
> > --- 1514,1526 ----
> >       {
> >         unsigned len, entry_len;
> >         lto_input_scc (ib, data_in, &len, &entry_len);
> > + 
> > +       /* Register DECLs with the debuginfo machinery.  */
> > +       while (!dref_queue.is_empty ())
> > + 	{
> > + 	  dref_entry e = dref_queue.pop ();
> > + 	  debug_hooks->register_external_die (e.decl, e.sym, e.off);
> > + 	}
> >       }
> >     return lto_input_tree_1 (ib, data_in, tag, 0);
> >   }
> > Index: early-lto-debug/gcc/lto-streamer-out.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/lto-streamer-out.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/lto-streamer-out.c	2017-05-16 13:10:49.858240736 +0200
> > *************** along with GCC; see the file COPYING3.
> > *** 40,45 ****
> > --- 40,46 ----
> >   #include "cfgloop.h"
> >   #include "builtins.h"
> >   #include "gomp-constants.h"
> > + #include "debug.h"
> >   
> >   
> >   static void lto_write_tree (struct output_block*, tree, bool);
> > *************** lto_write_tree_1 (struct output_block *o
> > *** 406,411 ****
> > --- 407,432 ----
> >   			 (ob->decl_state->symtab_node_encoder, expr);
> >         stream_write_tree (ob, initial, ref_p);
> >       }
> > + 
> > +   /* Stream references to early generated DIEs.  Keep in sync with the
> > +      trees handled in dwarf2out_die_ref_for_decl.  */
> > +   if ((DECL_P (expr)
> > +        && TREE_CODE (expr) != FIELD_DECL
> > +        && TREE_CODE (expr) != DEBUG_EXPR_DECL
> > +        && TREE_CODE (expr) != TYPE_DECL)
> > +       || TREE_CODE (expr) == BLOCK)
> > +     {
> > +       const char *sym;
> > +       unsigned HOST_WIDE_INT off;
> > +       if (debug_info_level > DINFO_LEVEL_NONE
> > + 	  && debug_hooks->die_ref_for_decl (expr, &sym, &off))
> > + 	{
> > + 	  streamer_write_string (ob, ob->main_stream, sym, true);
> > + 	  streamer_write_uhwi (ob, off);
> > + 	}
> > +       else
> > + 	streamer_write_string (ob, ob->main_stream, NULL, true);
> > +     }
> >   }
> >   
> >   /* Write a physical representation of tree node EXPR to output block
> > *************** DFS::DFS_write_tree_body (struct output_
> > *** 745,751 ****
> >   	;
> >         else
> >   	DFS_follow_tree_edge (DECL_NAME (expr));
> > !       DFS_follow_tree_edge (DECL_CONTEXT (expr));
> >       }
> >   
> >     if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> > --- 766,776 ----
> >   	;
> >         else
> >   	DFS_follow_tree_edge (DECL_NAME (expr));
> > !       if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
> > ! 	  && ! DECL_CONTEXT (expr))
> > ! 	DFS_follow_tree_edge ((*all_translation_units)[0]);
> > !       else
> > ! 	DFS_follow_tree_edge (DECL_CONTEXT (expr));
> >       }
> >   
> >     if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> > *************** DFS::DFS_write_tree_body (struct output_
> > *** 765,770 ****
> > --- 790,796 ----
> >   	 declarations which should be eliminated by decl merging. Be sure none
> >   	 leaks to this point.  */
> >         gcc_assert (DECL_ABSTRACT_ORIGIN (expr) != error_mark_node);
> > +       DFS_follow_tree_edge (DECL_ABSTRACT_ORIGIN (expr));
> >   
> >         if ((VAR_P (expr)
> >   	   || TREE_CODE (expr) == PARM_DECL)
> > *************** output_function (struct cgraph_node *nod
> > *** 2061,2066 ****
> > --- 2087,2103 ----
> >     stream_write_tree (ob, DECL_RESULT (function), true);
> >     streamer_write_chain (ob, DECL_ARGUMENTS (function), true);
> >   
> > +   /* Output debug args if available. */
> > +   vec<tree, va_gc> **debugargs = decl_debug_args_lookup (function);
> > +   if (! debugargs)
> > +     streamer_write_uhwi (ob, 0);
> > +   else
> > +     {
> > +       streamer_write_uhwi (ob, (*debugargs)->length ());
> > +       for (unsigned i = 0; i < (*debugargs)->length (); ++i)
> > + 	stream_write_tree (ob, (**debugargs)[i], true);
> > +     }
> > + 
> >     /* Output DECL_INITIAL for the function, which contains the tree of
> >        lexical scopes.  */
> >     stream_write_tree (ob, DECL_INITIAL (function), true);
> > Index: early-lto-debug/gcc/lto-streamer.h
> > ===================================================================
> > *** early-lto-debug.orig/gcc/lto-streamer.h	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/lto-streamer.h	2017-05-16 13:10:49.858240736 +0200
> > *************** DEFINE_DECL_STREAM_FUNCS (TYPE_DECL, typ
> > *** 1212,1215 ****
> > --- 1212,1225 ----
> >   DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl)
> >   DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl)
> >   
> > + /* Entry for the delayed registering of decl -> DIE references.  */
> > + struct dref_entry {
> > +     tree decl;
> > +     const char *sym;
> > +     unsigned HOST_WIDE_INT off;
> > + };
> > + 
> > + extern vec<dref_entry> dref_queue;
> > + 
> > + 
> >   #endif /* GCC_LTO_STREAMER_H  */
> > Index: early-lto-debug/gcc/lto-wrapper.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/lto-wrapper.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/lto-wrapper.c	2017-05-16 13:10:49.858240736 +0200
> > *************** static char **output_names;
> > *** 70,75 ****
> > --- 70,76 ----
> >   static char **offload_names;
> >   static char *offload_objects_file_name;
> >   static char *makefile;
> > + static char *debug_obj;
> >   
> >   const char tool_name[] = "lto-wrapper";
> >   
> > *************** tool_cleanup (bool)
> > *** 88,93 ****
> > --- 89,96 ----
> >       maybe_unlink (offload_objects_file_name);
> >     if (makefile)
> >       maybe_unlink (makefile);
> > +   if (debug_obj)
> > +     maybe_unlink (debug_obj);
> >     for (i = 0; i < nr; ++i)
> >       {
> >         maybe_unlink (input_names[i]);
> > *************** find_and_merge_options (int fd, off_t fi
> > *** 938,943 ****
> > --- 941,1007 ----
> >     return true;
> >   }
> >   
> > + /* Copy early debug info sections from INFILE to a new file whose name
> > +    is returned.  Return NULL on error.  */
> > + 
> > + const char *
> > + debug_objcopy (const char *infile)
> > + {
> > +   const char *outfile;
> > +   const char *errmsg;
> > +   int err;
> > + 
> > +   const char *p;
> > +   off_t inoff = 0;
> > +   long loffset;
> > +   int consumed;
> > +   if ((p = strrchr (infile, '@'))
> > +       && p != infile
> > +       && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
> > +       && strlen (p) == (unsigned int) consumed)
> > +     {
> > +       char *fname = xstrdup (infile);
> > +       fname[p - infile] = '\0';
> > +       infile = fname;
> > +       inoff = (off_t) loffset;
> > +     }
> > +   int infd = open (infile, O_RDONLY);
> > +   if (infd == -1)
> > +     return NULL;
> > +   simple_object_read *inobj = simple_object_start_read (infd, inoff,
> > + 							"__GNU_LTO",
> > + 							&errmsg, &err);
> > +   if (!inobj)
> > +     return NULL;
> > + 
> > +   off_t off, len;
> > +   if (simple_object_find_section (inobj, ".gnu.debuglto_.debug_info",
> > + 				  &off, &len, &errmsg, &err) != 1)
> > +     {
> > +       if (errmsg)
> > + 	fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
> > + 
> > +       simple_object_release_read (inobj);
> > +       close (infd);
> > +       return NULL;
> > +     }
> > + 
> > +   outfile = make_temp_file ("debugobjtem");
> > +   errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err);
> > +   if (errmsg)
> > +     {
> > +       unlink_if_ordinary (outfile);
> > +       fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
> > +     }
> > + 
> > +   simple_object_release_read (inobj);
> > +   close (infd);
> > + 
> > +   return outfile;
> > + }
> > + 
> > + 
> > + 
> >   /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
> >   
> >   static void
> > *************** run_gcc (unsigned argc, char *argv[])
> > *** 962,969 ****
> >     int new_head_argc;
> >     bool have_lto = false;
> >     bool have_offload = false;
> > !   unsigned lto_argc = 0;
> > !   char **lto_argv;
> >   
> >     /* Get the driver and options.  */
> >     collect_gcc = getenv ("COLLECT_GCC");
> > --- 1026,1035 ----
> >     int new_head_argc;
> >     bool have_lto = false;
> >     bool have_offload = false;
> > !   unsigned lto_argc = 0, ltoobj_argc = 0;
> > !   char **lto_argv, **ltoobj_argv;
> > !   bool skip_debug = false;
> > !   unsigned n_debugobj;
> >   
> >     /* Get the driver and options.  */
> >     collect_gcc = getenv ("COLLECT_GCC");
> > *************** run_gcc (unsigned argc, char *argv[])
> > *** 982,987 ****
> > --- 1048,1054 ----
> >     /* Allocate array for input object files with LTO IL,
> >        and for possible preceding arguments.  */
> >     lto_argv = XNEWVEC (char *, argc);
> > +   ltoobj_argv = XNEWVEC (char *, argc);
> >   
> >     /* Look at saved options in the IL files.  */
> >     for (i = 1; i < argc; ++i)
> > *************** run_gcc (unsigned argc, char *argv[])
> > *** 1024,1030 ****
> >   				  collect_gcc))
> >   	{
> >   	  have_lto = true;
> > ! 	  lto_argv[lto_argc++] = argv[i];
> >   	}
> >         close (fd);
> >       }
> > --- 1091,1097 ----
> >   				  collect_gcc))
> >   	{
> >   	  have_lto = true;
> > ! 	  ltoobj_argv[ltoobj_argc++] = argv[i];
> >   	}
> >         close (fd);
> >       }
> > *************** run_gcc (unsigned argc, char *argv[])
> > *** 1085,1090 ****
> > --- 1152,1168 ----
> >   	}
> >       }
> >   
> > +   /* Output lto-wrapper invocation command.  */
> > +   if (verbose)
> > +     {
> > +       for (i = 0; i < argc; ++i)
> > + 	{
> > + 	  fputs (argv[i], stderr);
> > + 	  fputc (' ', stderr);
> > + 	}
> > +       fputc ('\n', stderr);
> > +     }
> > + 
> >     if (no_partition)
> >       {
> >         lto_mode = LTO_MODE_LTO;
> > *************** cont1:
> > *** 1274,1291 ****
> >           obstack_ptr_grow (&argv_obstack, "-fwpa");
> >       }
> >   
> > !   /* Append the input objects and possible preceding arguments.  */
> >     for (i = 0; i < lto_argc; ++i)
> >       obstack_ptr_grow (&argv_obstack, lto_argv[i]);
> >     obstack_ptr_grow (&argv_obstack, NULL);
> >   
> >     new_argv = XOBFINISH (&argv_obstack, const char **);
> >     argv_ptr = &new_argv[new_head_argc];
> >     fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
> >   
> >     if (lto_mode == LTO_MODE_LTO)
> >       {
> >         printf ("%s\n", flto_out);
> >         free (flto_out);
> >         flto_out = NULL;
> >       }
> > --- 1352,1456 ----
> >           obstack_ptr_grow (&argv_obstack, "-fwpa");
> >       }
> >   
> > !   /* Append input arguments.  */
> >     for (i = 0; i < lto_argc; ++i)
> >       obstack_ptr_grow (&argv_obstack, lto_argv[i]);
> > +   /* Append the input objects.  */
> > +   for (i = 0; i < ltoobj_argc; ++i)
> > +     obstack_ptr_grow (&argv_obstack, ltoobj_argv[i]);
> >     obstack_ptr_grow (&argv_obstack, NULL);
> >   
> >     new_argv = XOBFINISH (&argv_obstack, const char **);
> >     argv_ptr = &new_argv[new_head_argc];
> >     fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
> >   
> > +   /* Handle early generated debug information.  At compile-time
> > +      we output early DWARF debug info into .gnu.debuglto_ prefixed
> > +      sections.  LTRANS object DWARF debug info refers to that.
> > +      So we need to transfer the .gnu.debuglto_ sections to the final
> > +      link.  Ideally the linker plugin interface would allow us to
> > +      not claim those sections and instruct the linker to keep
> > +      them, renaming them in the process.  For now we extract and
> > +      rename those sections via a simple-object interface to produce
> > +      regular objects containing only the early debug info.  We
> > +      then partially link those to a single early debug info object
> > +      and pass that as additional output back to the linker plugin.  */
> > + 
> > +   /* Prepare the partial link to gather the compile-time generated
> > +      debug-info into a single input for the final link.  */
> > +   debug_obj = make_temp_file ("debugobj");
> > +   obstack_ptr_grow (&argv_obstack, collect_gcc);
> > +   for (i = 1; i < decoded_options_count; ++i)
> > +     {
> > +       /* Retain linker choice and -B.  */
> > +       if (decoded_options[i].opt_index == OPT_B
> > + 	  || decoded_options[i].opt_index == OPT_fuse_ld_bfd
> > + 	  || decoded_options[i].opt_index == OPT_fuse_ld_gold)
> > + 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
> > +       /* Retain all target options, this preserves -m32 for example.  */
> > +       if (cl_options[decoded_options[i].opt_index].flags & CL_TARGET)
> > + 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
> > +       /* Recognize -g0.  */
> > +       if (decoded_options[i].opt_index == OPT_g
> > + 	  && strcmp (decoded_options[i].arg, "0") == 0)
> > + 	skip_debug = true;
> > +     }
> > +   obstack_ptr_grow (&argv_obstack, "-r");
> > +   obstack_ptr_grow (&argv_obstack, "-nostdlib");
> > +   obstack_ptr_grow (&argv_obstack, "-o");
> > +   obstack_ptr_grow (&argv_obstack, debug_obj);
> > + 
> > +   /* Copy the early generated debug info from the objects to temporary
> > +      files and append those to the partial link commandline.  */
> > +   n_debugobj = 0;
> > +   if (! skip_debug)
> > +     for (i = 0; i < ltoobj_argc; ++i)
> > +       {
> > + 	const char *tem;
> > + 	if ((tem = debug_objcopy (ltoobj_argv[i])))
> > + 	  {
> > + 	    obstack_ptr_grow (&argv_obstack, tem);
> > + 	    n_debugobj++;
> > + 	  }
> > +       }
> > + 
> > +   /* Link them all into a single object.  Ideally this would reduce
> > +      disk space usage mainly due to .debug_str merging but unfortunately
> > +      GNU ld doesn't perform this with -r.  */
> > +   if (n_debugobj)
> > +     {
> > +       obstack_ptr_grow (&argv_obstack, NULL);
> > +       const char **debug_link_argv = XOBFINISH (&argv_obstack, const char **);
> > +       fork_execute (debug_link_argv[0],
> > + 		    CONST_CAST (char **, debug_link_argv), false);
> > + 
> > +       /* And dispose the temporaries.  */
> > +       for (i = 0; debug_link_argv[i]; ++i)
> > + 	;
> > +       for (--i; i > 0; --i)
> > + 	{
> > + 	  if (strcmp (debug_link_argv[i], debug_obj) == 0)
> > + 	    break;
> > + 	  maybe_unlink (debug_link_argv[i]);
> > + 	}
> > +     }
> > +   else
> > +     {
> > +       unlink_if_ordinary (debug_obj);
> > +       free (debug_obj);
> > +       debug_obj = NULL;
> > +       skip_debug = true;
> > +     }
> > + 
> >     if (lto_mode == LTO_MODE_LTO)
> >       {
> >         printf ("%s\n", flto_out);
> > +       if (!skip_debug)
> > + 	{
> > + 	  printf ("%s\n", debug_obj);
> > + 	  free (debug_obj);
> > + 	  debug_obj = NULL;
> > + 	}
> >         free (flto_out);
> >         flto_out = NULL;
> >       }
> > *************** cont:
> > *** 1434,1439 ****
> > --- 1599,1610 ----
> >   	  for (i = 0; i < nr; ++i)
> >   	    maybe_unlink (input_names[i]);
> >   	}
> > +       if (!skip_debug)
> > + 	{
> > + 	  printf ("%s\n", debug_obj);
> > + 	  free (debug_obj);
> > + 	  debug_obj = NULL;
> > + 	}
> >         for (i = 0; i < nr; ++i)
> >   	{
> >   	  fputs (output_names[i], stdout);
> > Index: early-lto-debug/gcc/tree-streamer-in.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/tree-streamer-in.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/tree-streamer-in.c	2017-05-16 13:10:49.862240801 +0200
> > *************** lto_input_ts_decl_common_tree_pointers (
> > *** 688,697 ****
> >     DECL_SIZE (expr) = stream_read_tree (ib, data_in);
> >     DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
> >     DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
> > ! 
> > !   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
> > !      for early inlining so drop it on the floor instead of ICEing in
> > !      dwarf2out.c.  */
> >   
> >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> >         && DECL_HAS_VALUE_EXPR_P (expr))
> > --- 688,694 ----
> >     DECL_SIZE (expr) = stream_read_tree (ib, data_in);
> >     DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
> >     DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
> > !   DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
> >   
> >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> >         && DECL_HAS_VALUE_EXPR_P (expr))
> > Index: early-lto-debug/gcc/tree-streamer-out.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/tree-streamer-out.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/tree-streamer-out.c	2017-05-16 13:10:49.862240801 +0200
> > *************** write_ts_decl_minimal_tree_pointers (str
> > *** 566,572 ****
> >       stream_write_tree (ob, NULL_TREE, ref_p);
> >     else
> >       stream_write_tree (ob, DECL_NAME (expr), ref_p);
> > !   stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
> >   }
> >   
> >   
> > --- 566,576 ----
> >       stream_write_tree (ob, NULL_TREE, ref_p);
> >     else
> >       stream_write_tree (ob, DECL_NAME (expr), ref_p);
> > !   if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
> > !       && ! DECL_CONTEXT (expr))
> > !     stream_write_tree (ob, (*all_translation_units)[0], ref_p);
> > !   else
> > !     stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
> >   }
> >   
> >   
> > *************** write_ts_decl_common_tree_pointers (stru
> > *** 585,594 ****
> >        special handling in LTO, it must be handled by streamer hooks.  */
> >   
> >     stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
> > ! 
> > !   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
> > !      for early inlining so drop it on the floor instead of ICEing in
> > !      dwarf2out.c.  */
> >   
> >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> >         && DECL_HAS_VALUE_EXPR_P (expr))
> > --- 589,595 ----
> >        special handling in LTO, it must be handled by streamer hooks.  */
> >   
> >     stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
> > !   stream_write_tree (ob, DECL_ABSTRACT_ORIGIN (expr), ref_p);
> >   
> >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> >         && DECL_HAS_VALUE_EXPR_P (expr))
> > Index: early-lto-debug/gcc/config/darwin.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/config/darwin.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/config/darwin.c	2017-05-16 13:10:49.862240801 +0200
> > *************** darwin_asm_lto_end (void)
> > *** 1959,1965 ****
> >   }
> >   
> >   static void
> > ! darwin_asm_dwarf_section (const char *name, unsigned int flags, tree decl);
> >   
> >   /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
> >   
> > --- 1959,1966 ----
> >   }
> >   
> >   static void
> > ! darwin_asm_dwarf_section (const char *name, unsigned int flags,
> > ! 			  tree decl, bool is_for_lto);
> >   
> >   /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
> >   
> > *************** darwin_asm_named_section (const char *na
> > *** 2001,2007 ****
> >         vec_safe_push (lto_section_names, e);
> >      }
> >     else if (strncmp (name, "__DWARF,", 8) == 0)
> > !     darwin_asm_dwarf_section (name, flags, decl);
> >     else
> >       fprintf (asm_out_file, "\t.section %s\n", name);
> >   }
> > --- 2002,2010 ----
> >         vec_safe_push (lto_section_names, e);
> >      }
> >     else if (strncmp (name, "__DWARF,", 8) == 0)
> > !     darwin_asm_dwarf_section (name, flags, decl, false);
> > !   else if (strncmp (name, "__GNU_DWARF_LTO,", 16) == 0)
> > !     darwin_asm_dwarf_section (name, flags, decl, true);
> >     else
> >       fprintf (asm_out_file, "\t.section %s\n", name);
> >   }
> > *************** static GTY (()) vec<dwarf_sect_used_entr
> > *** 2783,2801 ****
> >   
> >   static void
> >   darwin_asm_dwarf_section (const char *name, unsigned int flags,
> > ! 			  tree ARG_UNUSED (decl))
> >   {
> >     unsigned i;
> > !   int namelen;
> > !   const char * sname;
> >     dwarf_sect_used_entry *ref;
> >     bool found = false;
> > !   gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
> > ! 		    == (SECTION_DEBUG | SECTION_NAMED));
> > !   /* We know that the name starts with __DWARF,  */
> > !   sname = name + 8;
> > !   namelen = strchr (sname, ',') - sname;
> > !   gcc_assert (namelen);
> >     if (dwarf_sect_names_table == NULL)
> >       vec_alloc (dwarf_sect_names_table, 16);
> >     else
> > --- 2786,2822 ----
> >   
> >   static void
> >   darwin_asm_dwarf_section (const char *name, unsigned int flags,
> > ! 			  tree ARG_UNUSED (decl), bool is_for_lto)
> >   {
> >     unsigned i;
> > !   int namelen, extra = 0;
> > !   const char *sect, *lto_add = "";
> > !   char sname[64];
> >     dwarf_sect_used_entry *ref;
> >     bool found = false;
> > ! 
> > !   gcc_checking_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
> > ! 			== (SECTION_DEBUG | SECTION_NAMED));
> > ! 
> > !   /* We know that the name starts with __DWARF, or __GNU_DAWRF_LTO  */
> > !   sect = strchr (name, ',') + 1;
> > !   namelen = strchr (sect, ',') - sect;
> > !   gcc_checking_assert (namelen);
> > ! 
> > !   /* The section switch is output as written...  */
> > !   fprintf (asm_out_file, "\t.section %s\n", name);
> > ! 
> > !   /* ... but the string we keep to make section start labels needs
> > !      adjustment for lto cases.  */
> > !   if (is_for_lto)
> > !     {
> > !       lto_add = "_lto";
> > !       extra = 4;
> > !     }
> > ! 
> > !   snprintf (sname, 64, "%.*s%.*s", namelen, sect, extra, lto_add);
> > !   namelen += extra;
> > ! 
> >     if (dwarf_sect_names_table == NULL)
> >       vec_alloc (dwarf_sect_names_table, 16);
> >     else
> > *************** darwin_asm_dwarf_section (const char *na
> > *** 2813,2819 ****
> >   	  }
> >         }
> >   
> > -   fprintf (asm_out_file, "\t.section %s\n", name);
> >     if (!found)
> >       {
> >         dwarf_sect_used_entry e;
> > --- 2834,2839 ----
> > *************** darwin_asm_output_dwarf_offset (FILE *fi
> > *** 2866,2879 ****
> >   				HOST_WIDE_INT offset, section *base)
> >   {
> >     char sname[64];
> > !   int namelen;
> >   
> > !   gcc_assert (base->common.flags & SECTION_NAMED);
> > !   gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
> > !   gcc_assert (strchr (base->named.name + 8, ','));
> > ! 
> > !   namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
> > !   sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
> >     darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
> >   }
> >   
> > --- 2886,2909 ----
> >   				HOST_WIDE_INT offset, section *base)
> >   {
> >     char sname[64];
> > !   int namelen, extra = 0;
> > !   bool is_for_lto;
> > !   const char *lto_add = "";
> > ! 
> > !   gcc_checking_assert (base->common.flags & SECTION_NAMED);
> > !   is_for_lto = strncmp (base->named.name, "__GNU_DWARF_LTO,", 16) == 0;
> > !   gcc_checking_assert (is_for_lto
> > ! 		       || strncmp (base->named.name, "__DWARF,", 8) == 0);
> > !   const char *name = strchr (base->named.name, ',') + 1;
> > !   gcc_checking_assert (name);
> >   
> > !   namelen = strchr (name, ',') - (name);
> > !   if (is_for_lto)
> > !     {
> > !       lto_add = "_lto";
> > !       extra = 4;
> > !     }
> > !   snprintf (sname, 64, "*Lsection%.*s%.*s", namelen, name, extra, lto_add);
> >     darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
> >   }
> >   
> > Index: early-lto-debug/gcc/config/darwin.h
> > ===================================================================
> > *** early-lto-debug.orig/gcc/config/darwin.h	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/config/darwin.h	2017-05-16 13:10:49.866240867 +0200
> > *************** extern GTY(()) int darwin_ms_struct;
> > *** 445,451 ****
> >   #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
> >   #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
> >   #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
> > ! #define DEBUG_MACRO_SECTION    "__DWARF,__debug_macro,regular,debug"
> >   
> >   #define TARGET_WANT_DEBUG_PUB_SECTIONS true
> >   
> > --- 445,458 ----
> >   #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
> >   #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
> >   #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
> > ! #define DEBUG_MACRO_SECTION     "__DWARF,__debug_macro,regular,debug"
> > ! 
> > ! #define DEBUG_LTO_INFO_SECTION	  "__GNU_DWARF_LTO,__debug_info,regular,debug"
> > ! #define DEBUG_LTO_ABBREV_SECTION  "__GNU_DWARF_LTO,__debug_abbrev,regular,debug"
> > ! #define DEBUG_LTO_MACINFO_SECTION "__GNU_DWARF_LTO,__debug_macinfo,regular,debug"
> > ! #define DEBUG_LTO_LINE_SECTION	  "__GNU_DWARF_LTO,__debug_line,regular,debug"
> > ! #define DEBUG_LTO_STR_SECTION	  "__GNU_DWARF_LTO,__debug_str,regular,debug"
> > ! #define DEBUG_LTO_MACRO_SECTION   "__GNU_DWARF_LTO,__debug_macro,regular,debug"
> >   
> >   #define TARGET_WANT_DEBUG_PUB_SECTIONS true
> >   
> > Index: early-lto-debug/gcc/vmsdbgout.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/vmsdbgout.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/vmsdbgout.c	2017-05-16 13:10:49.866240867 +0200
> > *************** const struct gcc_debug_hooks vmsdbg_debu
> > *** 198,203 ****
> > --- 198,205 ----
> >      vmsdbgout_late_global_decl,
> >      vmsdbgout_type_decl,		  /* type_decl */
> >      debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
> > +    debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > +    debug_nothing_tree_charstar_uhwi, /* register_external_die */
> >      debug_nothing_tree,		  /* deferred_inline_function */
> >      vmsdbgout_abstract_function,
> >      debug_nothing_rtx_code_label,  /* label */
> > Index: early-lto-debug/gcc/tree.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/tree.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/tree.c	2017-05-16 13:10:49.870240933 +0200
> > *************** free_lang_data (void)
> > *** 5974,5979 ****
> > --- 5974,5983 ----
> >         || (!flag_generate_lto && !flag_generate_offload))
> >       return 0;
> >   
> > +   /* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one.  */
> > +   if (vec_safe_is_empty (all_translation_units))
> > +     build_translation_unit_decl (NULL_TREE);
> > + 
> >     /* Allocate and assign alias sets to the standard integer types
> >        while the slots are still in the way the frontends generated them.  */
> >     for (i = 0; i < itk_none; ++i)
> > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-05-16 13:10:49.870240933 +0200
> > *************** int main() {
> > *** 23,28 ****
> >   }
> >   
> >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
> >   /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
> >   /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
> > --- 23,28 ----
> >   }
> >   
> >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
> >   /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
> >   /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
> > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-05-16 13:10:49.870240933 +0200
> > *************** int main(int argc, char **argv) {
> > *** 24,31 ****
> >   }
> >   
> >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > --- 24,31 ----
> >   }
> >   
> >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-05-16 13:10:49.870240933 +0200
> > *************** main ()
> > *** 39,43 ****
> >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > --- 39,43 ----
> >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-05-16 13:10:49.870240933 +0200
> > *************** main ()
> > *** 39,43 ****
> >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > --- 39,43 ----
> >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-05-16 13:10:49.870240933 +0200
> > *************** int main()
> > *** 18,22 ****
> >   
> >   /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
> >   /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > --- 18,22 ----
> >   
> >   /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
> >   /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-05-16 13:10:49.874240999 +0200
> > *************** int main() {
> > *** 18,23 ****
> >   }
> >   
> >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
> >   /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
> > --- 18,23 ----
> >   }
> >   
> >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
> >   /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
> > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-05-16 13:10:49.874240999 +0200
> > *************** int main(int argc, char **argv) {
> > *** 14,21 ****
> >   
> >   /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > --- 14,21 ----
> >   
> >   /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-05-16 13:10:49.874240999 +0200
> > *************** int main() {
> > *** 12,22 ****
> >   /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
> >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > --- 12,22 ----
> >   /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
> >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> >   /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > Index: early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C
> > ===================================================================
> > *** early-lto-debug.orig/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-05-16 13:10:49.874240999 +0200
> > *************** int main() {
> > *** 38,44 ****
> >   // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
> >   // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
> >   // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
> > ! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" }
> >   // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
> >   // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
> >   // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
> > --- 38,44 ----
> >   // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
> >   // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
> >   // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
> > ! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" }
> >   // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
> >   // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
> >   // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
> > Index: early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp
> > ===================================================================
> > *** early-lto-debug.orig/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-05-16 13:10:47.554202813 +0200
> > --- early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-05-16 13:10:49.874240999 +0200
> > ***************
> > *** 15,20 ****
> > --- 15,21 ----
> >   # <http://www.gnu.org/licenses/>.
> >   
> >   load_lib gdb-test.exp
> > + load_lib target-supports.exp
> >   
> >   dg-init
> >   v3-build_support
> > *************** global PCH_CXXFLAGS
> > *** 46,51 ****
> > --- 47,60 ----
> >   gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
> >     "" "$DEFAULT_CXXFLAGS $PCH_CXXFLAGS"
> >   
> > + if { [check_effective_target_lto] } {
> > +   append cxxflags " -flto"
> > +   # work around sourceware.org 20882
> > +   regsub {^(.*)-Wl,--gc-sections(.*)$} $cxxldflags {\1\2} cxxldflags
> > +   gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
> > +     "" "$DEFAULT_CXXFLAGS -flto $PCH_CXXFLAGS"
> > + }
> > + 
> >   if [info exists guality_gdb_name] {
> >       unsetenv GUALITY_GDB_NAME
> >   }
> > Index: early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90
> > ===================================================================
> > *** /dev/null	1970-01-01 00:00:00.000000000 +0000
> > --- early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90	2017-05-18 09:39:31.394914888 +0200
> > ***************
> > *** 0 ****
> > --- 1,54 ----
> > + ! { dg-do run }
> > + ! { dg-require-effective-target lto }
> > + ! { dg-options "-fno-automatic -flto -g" }
> > + !
> > + ! PR fortran/55733
> > + !
> > + ! Check that -fno-automatic makes the local variable SAVEd
> > + ! Check that -flto -g works
> > + !
> > + 
> > + ! Scalar allocatable
> > + subroutine foo(i)
> > +   integer :: i
> > +   integer, allocatable :: j
> > +   if (i == 1) j = 42
> > +   if (.not. allocated (j)) call abort ()
> > +   if (j /= 42) call abort ()
> > + end
> > + 
> > + ! Deferred-length string scalar
> > + subroutine bar()
> > +   logical, save :: first = .true.
> > +   character(len=:), allocatable :: str
> > +   if (first) then
> > +     first = .false.
> > +     if (allocated (str)) call abort ()
> > +     str = "ABCDEF"
> > +   end if
> > +   if (.not. allocated (str)) call abort ()
> > +   if (len (str) /= 6) call abort ()
> > +   if (str(1:6) /= "ABCDEF") call abort ()
> > + end subroutine bar
> > + 
> > + ! Deferred-length string array
> > + subroutine bar_array()
> > +   logical, save :: first = .true.
> > +   character(len=:), allocatable :: str
> > +   if (first) then
> > +     first = .false.
> > +     if (allocated (str)) call abort ()
> > +     str = "ABCDEF"
> > +   end if
> > +   if (.not. allocated (str)) call abort ()
> > +   if (len (str) /= 6) call abort ()
> > +   if (str(1:6) /= "ABCDEF") call abort ()
> > + end subroutine bar_array
> > + 
> > + call foo(1)
> > + call foo(2)
> > + call bar()
> > + call bar_array()
> > + call bar()
> > + call bar_array()
> > + end
> > Index: early-lto-debug/gcc/config/i386/i386.c
> > ===================================================================
> > *** early-lto-debug.orig/gcc/config/i386/i386.c	2017-05-15 10:57:19.923567540 +0200
> > --- early-lto-debug/gcc/config/i386/i386.c	2017-05-19 11:27:19.565373271 +0200
> > *************** make_resolver_func (const tree default_d
> > *** 33840,33846 ****
> >     DECL_NAME (decl) = decl_name;
> >     TREE_USED (decl) = 1;
> >     DECL_ARTIFICIAL (decl) = 1;
> > !   DECL_IGNORED_P (decl) = 0;
> >     /* IFUNC resolvers have to be externally visible.  */
> >     TREE_PUBLIC (decl) = 1;
> >     DECL_UNINLINABLE (decl) = 1;
> > --- 33840,33846 ----
> >     DECL_NAME (decl) = decl_name;
> >     TREE_USED (decl) = 1;
> >     DECL_ARTIFICIAL (decl) = 1;
> > !   DECL_IGNORED_P (decl) = 1;
> >     /* IFUNC resolvers have to be externally visible.  */
> >     TREE_PUBLIC (decl) = 1;
> >     DECL_UNINLINABLE (decl) = 1;
> > 
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-06-20 11:16   ` Richard Biener
@ 2017-07-04 11:10     ` Richard Biener
  2017-07-28 12:55       ` Richard Biener
  0 siblings, 1 reply; 22+ messages in thread
From: Richard Biener @ 2017-07-04 11:10 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason

On Tue, 20 Jun 2017, Richard Biener wrote:

> On Wed, 7 Jun 2017, Richard Biener wrote:
> 
> > On Fri, 19 May 2017, Richard Biener wrote:
> > 
> > > 
> > > This is a repost of the main part of the early LTO debug support.
> > > The only changes relative to the last post is in the dwarf2out.c
> > > pieces due to Jasons review and Jakubs introduction of
> > > DW_OP_GNU_variable_value.
> > > 
> > > I've also adjusted testcases for fallout (the asan backtraces do
> > > give files / line numbers because libbacktrace doesn't understand
> > > the DWARF) plus added a -flto run over the libstdc++ pretty printer
> > > testsuite -- after all the goal was to make those work with LTO,
> > > and they now nicely do.
> > > 
> > > [LTO-]bootstrapped and tested on x86_64-unknown-linux-gnu.
> > > 
> > > I've also tested with -flto -g and compared to before the patch and
> > > the outcome doesn't contain any surprises.
> > > 
> > > I've also ran the gdb testsuite with no differences (but I guess
> > > it doesn't exercise LTO).
> > > 
> > > I've also built SPEC 2k6 with -flto -g.
> > > 
> > > I've also debugged optimized LTO bootstrapped cc1 a bit - not that
> > > debugging (LTO) optimized cc1 is a pleasant experience, but at least
> > > gdb doesn't crash.
> > > 
> > > Ok for trunk?
> > 
> > Ping.
> 
> Ping^2.

Ping^3.

> > > Both darwin and mingw maintainers were not concerned about LTO with -g
> > > being broken for them.
> > > 
> > > This patch allows us to go forward with freeing more stuff after
> > > the frontend finished, in particular remove LTO streaming of a lot
> > > of type information that is referenced from trees (and, as a first
> > > step, enable free-lang-data for non-LTO compiles).
> > > 
> > > Thanks,
> > > Richard.
> > > 
> > > 2017-05-19  Richard Biener  <rguenther@suse.de>
> > > 
> > >         * debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and
> > >         register_external_die hooks.
> > >         (debug_false_tree_charstarstar_uhwistar): Declare.
> > >         (debug_nothing_tree_charstar_uhwi): Likewise.
> > >         * debug.c (do_nothing_debug_hooks): Adjust.
> > >         (debug_false_tree_charstarstar_uhwistar): New do nothing.
> > >         (debug_nothing_tree_charstar_uhwi): Likewise.
> > >         * dbxout.c (dbx_debug_hooks): Adjust.
> > >         (xcoff_debug_hooks): Likewise.
> > >         * sdbout.c (sdb_debug_hooks): Likewise.
> > >         * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
> > > 
> > >         * dwarf2out.c (macinfo_label_base): New global.
> > > 	(dwarf2out_register_external_die): New function for the
> > > 	register_external_die hook.
> > >         (dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl.
> > >         (dwarf2_debug_hooks): Use them.
> > >         (dwarf2_lineno_debug_hooks): Adjust.
> > >         (struct die_struct): Add with_offset flag.
> > >         (DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION,
> > >         DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION,
> > >         DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION,
> > >         DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION,
> > >         DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
> > >         DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros
> > >         defining section names for the early LTO debug variants.
> > > 	(reset_indirect_string): New helper.
> > >         (add_AT_external_die_ref): Helper for dwarf2out_register_external_die.
> > >         (print_dw_val): Add support for offsetted symbol references.
> > >         (compute_section_prefix_1): Split out worker to distinguish
> > >         the comdat from the LTO case.
> > >         (compute_section_prefix): Wrap old comdat case here.
> > >         (output_die): Skip DIE symbol output for the LTO added one.
> > >         Handle DIE symbol references with offset.
> > >         (output_comp_unit): Guard section name mangling properly.
> > >         For LTO debug sections emit a symbol at the section beginning
> > >         which we use to refer to its DIEs.
> > >         (add_abstract_origin_attribute): For DIEs registered via
> > >         dwarf2out_register_external_die directly refer to the early
> > >         DIE rather than indirectly through the shadow one we created.
> > >         (gen_array_type_die): When generating early LTO debug do
> > >         not emit DW_AT_string_length.
> > >         (gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs
> > >         late when in LTO.
> > >         (gen_subprogram_die): Adjust the check for whether we face
> > >         a concrete instance DIE for an inline we can reuse for the
> > >         late LTO case.  Likewise avoid another specification DIE
> > >         for early built declarations/definitions for the late LTO case.
> > >         (gen_variable_die): Add type references for late duplicated VLA dies
> > >         when in late LTO.
> > >         (gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function,
> > >         we have the abstract instance already.
> > >         (process_scope_var): Adjust decl DIE contexts in LTO which
> > >         first puts them in limbo.
> > >         (gen_decl_die): Do not generate type DIEs late apart from
> > >         types for VLAs or for decls we do not yet have a DIE.
> > >         (dwarf2out_early_global_decl): Make sure to create DIEs
> > >         for abstract instances of a decl first.
> > >         (dwarf2out_late_global_decl): Adjust comment.
> > >         (output_macinfo_op): With multiple macro sections use
> > > 	macinfo_label_base to distinguish labels.
> > >         (output_macinfo): Likewise.  Update macinfo_label_base.
> > > 	Pass in the line info label.
> > > 	(note_variable_value_in_expr): When generating LTO resolve
> > > 	all variable values here by generating DIEs as needed.
> > >         (init_sections_and_labels): Add early LTO debug flag parameter
> > >         and generate different sections and names if set.  Add generation
> > >         counter for the labels so we can have multiple of them.
> > >         (reset_dies): Helper to allow DIEs to be output multiple times.
> > >         (dwarf2out_finish): When outputting DIEs to the fat part of an
> > > 	LTO object first reset DIEs.
> > >         (dwarf2out_early_finish): Output early DIEs when generating LTO.
> > > 
> > > Cleanups we can do (and need) when removing the "old" LTO path and add
> > > the early LTO path.
> > > 
> > >         (set_decl_abstract_flags): Remove.
> > >         (set_block_abstract_flags): Likewise.
> > >         (dwarf2out_abstract_function): Treat the early generated DIEs
> > >         as the abstract copy and only add DW_AT_inline and
> > >         DW_AT_artificial here.
> > > 
> > > 	* tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL
> > > 	if we have none yet (Go fails to build one, PR78628).
> > >         * lto-streamer-in.c: Include debug.h.
> > >         (dref_queue): New global.
> > >         (lto_read_tree_1): Stream in DIE references.
> > >         (lto_input_tree): Register DIE references.
> > > 	(input_function): Stream DECL_DEBUG_ARGS.
> > >         * lto-streamer-out.c: Include debug.h.
> > >         (lto_write_tree_1): Output DIE references.
> > >         (DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN.
> > > 	Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls.
> > > 	(output_function): Stream DECL_DEBUG_ARGS.
> > >         * tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers):
> > >         Stream DECL_ABSTRACT_ORIGIN.
> > >         * tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise.
> > > 	(write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL
> > > 	DECL_CONTEXT for file-scope decls.
> > >         * lto-streamer.h (struct dref_entry): Declare.
> > >         (dref_queue): Likewise.
> > > 
> > >         * lto-wrapper.c (debug_obj): New global.
> > >         (tool_cleanup): Unlink it if required.
> > >         (debug_objcopy): New function.
> > >         (run_gcc): Handle early debug sections in the IL files by
> > >         extracting them to separate files, partially linkin them and
> > >         feeding the result back as result to the linker.
> > > 
> > >         * config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION,
> > >         DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION,
> > >         DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug
> > >         sections into a separate segment.
> > >         * config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO
> > >         segments.
> > >         (darwin_asm_dwarf_section): Likewise.
> > >         (darwin_asm_output_dwarf_offset): Likewise.
> > > 
> > > 	* config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P.
> > > 
> > >         lto/
> > >         * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
> > >         (lto_read_decls): Process TRANSLATION_UNIT_DECLs.  Remove
> > >         TYPE_DECL debug processing, register DIE references from
> > >         prevailing SCCs with the debug machinery.
> > >         (lto_section_with_id): Handle LTO debug sections.
> > > 
> > > 	libstdc++/
> > > 	* testsuite/libstdc++-prettyprinters/prettyprinters.exp: Run all
> > > 	tests with -flto as well if supported.
> > > 
> > > 	* c-c++-common/asan/global-overflow-1.c: Adjust diagnostic location
> > > 	regex to handle the LTO case.
> > > 	* c-c++-common/asan/heap-overflow-1.c: Likewise.
> > > 	* c-c++-common/asan/misalign-1.c: Likewise.
> > > 	* c-c++-common/asan/misalign-2.c: Likewise.
> > > 	* c-c++-common/asan/null-deref-1.c: Likewise.
> > > 	* c-c++-common/asan/stack-overflow-1.c: Likewise.
> > > 	* c-c++-common/asan/strncpy-overflow-1.c: Likewise.
> > > 	* c-c++-common/asan/use-after-free-1.c: Likewise.
> > > 	* g++.dg/asan/large-func-test-1.C: Likewise.
> > > 	* gfortran.dg/save_6.f90: Add -flto -g variant of save_5.f90.
> > > 
> > > Index: early-lto-debug/gcc/dwarf2out.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/dwarf2out.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/dwarf2out.c	2017-05-19 12:29:43.933873285 +0200
> > > *************** static GTY(()) section *debug_aranges_se
> > > *** 162,167 ****
> > > --- 162,168 ----
> > >   static GTY(()) section *debug_addr_section;
> > >   static GTY(()) section *debug_macinfo_section;
> > >   static const char *debug_macinfo_section_name;
> > > + static unsigned macinfo_label_base = 1;
> > >   static GTY(()) section *debug_line_section;
> > >   static GTY(()) section *debug_skeleton_line_section;
> > >   static GTY(()) section *debug_loc_section;
> > > *************** static void dwarf2out_begin_function (tr
> > > *** 2686,2691 ****
> > > --- 2687,2696 ----
> > >   static void dwarf2out_end_function (unsigned int);
> > >   static void dwarf2out_register_main_translation_unit (tree unit);
> > >   static void dwarf2out_set_name (tree, tree);
> > > + static void dwarf2out_register_external_die (tree decl, const char *sym,
> > > + 					     unsigned HOST_WIDE_INT off);
> > > + static bool dwarf2out_die_ref_for_decl (tree decl, const char **sym,
> > > + 					unsigned HOST_WIDE_INT *off);
> > >   
> > >   /* The debug hooks structure.  */
> > >   
> > > *************** const struct gcc_debug_hooks dwarf2_debu
> > > *** 2720,2725 ****
> > > --- 2725,2732 ----
> > >     dwarf2out_late_global_decl,
> > >     dwarf2out_type_decl,		/* type_decl */
> > >     dwarf2out_imported_module_or_decl,
> > > +   dwarf2out_die_ref_for_decl,
> > > +   dwarf2out_register_external_die,
> > >     debug_nothing_tree,		/* deferred_inline_function */
> > >     /* The DWARF 2 backend tries to reduce debugging bloat by not
> > >        emitting the abstract description of inline functions until
> > > *************** const struct gcc_debug_hooks dwarf2_line
> > > *** 2761,2766 ****
> > > --- 2768,2775 ----
> > >     debug_nothing_tree,		         /* late_global_decl */
> > >     debug_nothing_tree_int,		 /* type_decl */
> > >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> > >     debug_nothing_tree,		         /* deferred_inline_function */
> > >     debug_nothing_tree,		         /* outlining_inline_function */
> > >     debug_nothing_rtx_code_label,	         /* label */
> > > *************** typedef struct GTY((chain_circular ("%h.
> > > *** 2889,2894 ****
> > > --- 2898,2906 ----
> > >     /* Die is used and must not be pruned as unused.  */
> > >     BOOL_BITFIELD die_perennial_p : 1;
> > >     BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
> > > +   /* For an external ref to die_symbol if die_offset contains an extra
> > > +      offset to that symbol.  */
> > > +   BOOL_BITFIELD with_offset : 1;
> > >     /* Whether this DIE was removed from the DIE tree, for example via
> > >        prune_unused_types.  We don't consider those present from the
> > >        DIE lookup routines.  */
> > > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > > *** 3692,3703 ****
> > > --- 3704,3727 ----
> > >   #ifndef DEBUG_DWO_INFO_SECTION
> > >   #define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
> > >   #endif
> > > + #ifndef DEBUG_LTO_DWO_INFO_SECTION
> > > + #define DEBUG_LTO_DWO_INFO_SECTION ".gnu.debuglto_.debug_info.dwo"
> > > + #endif
> > > + #ifndef DEBUG_LTO_INFO_SECTION
> > > + #define DEBUG_LTO_INFO_SECTION	".gnu.debuglto_.debug_info"
> > > + #endif
> > >   #ifndef DEBUG_ABBREV_SECTION
> > >   #define DEBUG_ABBREV_SECTION	".debug_abbrev"
> > >   #endif
> > >   #ifndef DEBUG_DWO_ABBREV_SECTION
> > >   #define DEBUG_DWO_ABBREV_SECTION ".debug_abbrev.dwo"
> > >   #endif
> > > + #ifndef DEBUG_LTO_DWO_ABBREV_SECTION
> > > + #define DEBUG_LTO_DWO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev.dwo"
> > > + #endif
> > > + #ifndef DEBUG_LTO_ABBREV_SECTION
> > > + #define DEBUG_LTO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev"
> > > + #endif
> > >   #ifndef DEBUG_ARANGES_SECTION
> > >   #define DEBUG_ARANGES_SECTION	".debug_aranges"
> > >   #endif
> > > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > > *** 3710,3727 ****
> > > --- 3734,3766 ----
> > >   #ifndef DEBUG_DWO_MACINFO_SECTION
> > >   #define DEBUG_DWO_MACINFO_SECTION      ".debug_macinfo.dwo"
> > >   #endif
> > > + #ifndef DEBUG_LTO_DWO_MACINFO_SECTION
> > > + #define DEBUG_LTO_DWO_MACINFO_SECTION  ".gnu.debuglto_.debug_macinfo.dwo"
> > > + #endif
> > > + #ifndef DEBUG_LTO_MACINFO_SECTION
> > > + #define DEBUG_LTO_MACINFO_SECTION      ".gnu.debuglto_.debug_macinfo"
> > > + #endif
> > >   #ifndef DEBUG_DWO_MACRO_SECTION
> > >   #define DEBUG_DWO_MACRO_SECTION        ".debug_macro.dwo"
> > >   #endif
> > >   #ifndef DEBUG_MACRO_SECTION
> > >   #define DEBUG_MACRO_SECTION	".debug_macro"
> > >   #endif
> > > + #ifndef DEBUG_LTO_DWO_MACRO_SECTION
> > > + #define DEBUG_LTO_DWO_MACRO_SECTION    ".gnu.debuglto_.debug_macro.dwo"
> > > + #endif
> > > + #ifndef DEBUG_LTO_MACRO_SECTION
> > > + #define DEBUG_LTO_MACRO_SECTION ".gnu.debuglto_.debug_macro"
> > > + #endif
> > >   #ifndef DEBUG_LINE_SECTION
> > >   #define DEBUG_LINE_SECTION	".debug_line"
> > >   #endif
> > >   #ifndef DEBUG_DWO_LINE_SECTION
> > >   #define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
> > >   #endif
> > > + #ifndef DEBUG_LTO_LINE_SECTION
> > > + #define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
> > > + #endif
> > >   #ifndef DEBUG_LOC_SECTION
> > >   #define DEBUG_LOC_SECTION	".debug_loc"
> > >   #endif
> > > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > > *** 3750,3761 ****
> > > --- 3789,3809 ----
> > >   #ifndef DEBUG_DWO_STR_OFFSETS_SECTION
> > >   #define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo"
> > >   #endif
> > > + #ifndef DEBUG_LTO_DWO_STR_OFFSETS_SECTION
> > > + #define DEBUG_LTO_DWO_STR_OFFSETS_SECTION ".gnu.debuglto_.debug_str_offsets.dwo"
> > > + #endif
> > >   #ifndef DEBUG_STR_DWO_SECTION
> > >   #define DEBUG_STR_DWO_SECTION   ".debug_str.dwo"
> > >   #endif
> > > + #ifndef DEBUG_LTO_STR_DWO_SECTION
> > > + #define DEBUG_LTO_STR_DWO_SECTION ".gnu.debuglto_.debug_str.dwo"
> > > + #endif
> > >   #ifndef DEBUG_STR_SECTION
> > >   #define DEBUG_STR_SECTION  ".debug_str"
> > >   #endif
> > > + #ifndef DEBUG_LTO_STR_SECTION
> > > + #define DEBUG_LTO_STR_SECTION ".gnu.debuglto_.debug_str"
> > > + #endif
> > >   #ifndef DEBUG_RANGES_SECTION
> > >   #define DEBUG_RANGES_SECTION	".debug_ranges"
> > >   #endif
> > > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > > *** 3780,3785 ****
> > > --- 3828,3837 ----
> > >   /* Section flags for .debug_str.dwo section.  */
> > >   #define DEBUG_STR_DWO_SECTION_FLAGS (SECTION_DEBUG | SECTION_EXCLUDE)
> > >   
> > > + /* Attribute used to refer to the macro section.  */
> > > + #define DEBUG_MACRO_ATTRIBUTE (dwarf_version >= 5 ? DW_AT_macros \
> > > + 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros)
> > > + 
> > >   /* Labels we insert at beginning sections we can reference instead of
> > >      the section names themselves.  */
> > >   
> > > *************** set_indirect_string (struct indirect_str
> > > *** 4368,4373 ****
> > > --- 4420,4443 ----
> > >       }
> > >   }
> > >   
> > > + /* A helper function for dwarf2out_finish, called to reset indirect
> > > +    string decisions done for early LTO dwarf output before fat object
> > > +    dwarf output.  */
> > > + 
> > > + int
> > > + reset_indirect_string (indirect_string_node **h, void *)
> > > + {
> > > +   struct indirect_string_node *node = *h;
> > > +   if (node->form == DW_FORM_strp || node->form == DW_FORM_GNU_str_index)
> > > +     {
> > > +       free (node->label);
> > > +       node->label = NULL;
> > > +       node->form = (dwarf_form) 0;
> > > +       node->index = 0;
> > > +     }
> > > +   return 1;
> > > + }
> > > + 
> > >   /* Find out whether a string should be output inline in DIE
> > >      or out-of-line in .debug_str section.  */
> > >   
> > > *************** lookup_decl_die (tree decl)
> > > *** 5413,5418 ****
> > > --- 5483,5668 ----
> > >     return *die;
> > >   }
> > >   
> > > + 
> > > + /* For DECL which might have early dwarf output query a SYMBOL + OFFSET
> > > +    style reference.  Return true if we found one refering to a DIE for
> > > +    DECL, otherwise return false.  */
> > > + 
> > > + static bool
> > > + dwarf2out_die_ref_for_decl (tree decl, const char **sym,
> > > + 			    unsigned HOST_WIDE_INT *off)
> > > + {
> > > +   dw_die_ref die;
> > > + 
> > > +   if (flag_wpa && !decl_die_table)
> > > +     return false;
> > > + 
> > > +   if (TREE_CODE (decl) == BLOCK)
> > > +     die = BLOCK_DIE (decl);
> > > +   else
> > > +     die = lookup_decl_die (decl);
> > > +   if (!die)
> > > +     return false;
> > > + 
> > > +   /* During WPA stage we currently use DIEs to store the
> > > +      decl <-> label + offset map.  That's quite inefficient but it
> > > +      works for now.  */
> > > +   if (flag_wpa)
> > > +     {
> > > +       dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
> > > +       if (!ref)
> > > + 	{
> > > + 	  gcc_assert (die == comp_unit_die ());
> > > + 	  return false;
> > > + 	}
> > > +       *off = ref->die_offset;
> > > +       *sym = ref->die_id.die_symbol;
> > > +       return true;
> > > +     }
> > > + 
> > > +   /* Similar to get_ref_die_offset_label, but using the "correct"
> > > +      label.  */
> > > +   *off = die->die_offset;
> > > +   while (die->die_parent)
> > > +     die = die->die_parent;
> > > +   /* For the containing CU DIE we compute a die_symbol in
> > > +      compute_section_prefix.  */
> > > +   gcc_assert (die->die_tag == DW_TAG_compile_unit
> > > + 	      && die->die_id.die_symbol != NULL);
> > > +   *sym = die->die_id.die_symbol;
> > > +   return true;
> > > + }
> > > + 
> > > + /* Add a reference of kind ATTR_KIND to a DIE at SYMBOL + OFFSET to DIE.  */
> > > + 
> > > + static void
> > > + add_AT_external_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind,
> > > + 			 const char *symbol, HOST_WIDE_INT offset)
> > > + {
> > > +   /* Create a fake DIE that contains the reference.  Don't use
> > > +      new_die because we don't want to end up in the limbo list.  */
> > > +   dw_die_ref ref = ggc_cleared_alloc<die_node> ();
> > > +   ref->die_tag = die->die_tag;
> > > +   ref->die_id.die_symbol = IDENTIFIER_POINTER (get_identifier (symbol));
> > > +   ref->die_offset = offset;
> > > +   ref->with_offset = 1;
> > > +   add_AT_die_ref (die, attr_kind, ref);
> > > + }
> > > + 
> > > + /* Create a DIE for DECL if required and add a reference to a DIE
> > > +    at SYMBOL + OFFSET which contains attributes dumped early.  */
> > > + 
> > > + static void
> > > + dwarf2out_register_external_die (tree decl, const char *sym,
> > > + 				 unsigned HOST_WIDE_INT off)
> > > + {
> > > +   if (debug_info_level == DINFO_LEVEL_NONE)
> > > +     return;
> > > + 
> > > +   if (flag_wpa && !decl_die_table)
> > > +     decl_die_table = hash_table<decl_die_hasher>::create_ggc (1000);
> > > + 
> > > +   dw_die_ref die
> > > +     = TREE_CODE (decl) == BLOCK ? BLOCK_DIE (decl) : lookup_decl_die (decl);
> > > +   gcc_assert (!die);
> > > + 
> > > +   tree ctx;
> > > +   dw_die_ref parent = NULL;
> > > +   /* Need to lookup a DIE for the decls context - the containing
> > > +      function or translation unit.  */
> > > +   if (TREE_CODE (decl) == BLOCK)
> > > +     {
> > > +       ctx = BLOCK_SUPERCONTEXT (decl);
> > > +       /* ???  We do not output DIEs for all scopes thus skip as
> > > + 	 many DIEs as needed.  */
> > > +       while (TREE_CODE (ctx) == BLOCK
> > > + 	     && !BLOCK_DIE (ctx))
> > > + 	ctx = BLOCK_SUPERCONTEXT (ctx);
> > > +     }
> > > +   else
> > > +     ctx = DECL_CONTEXT (decl);
> > > +   while (ctx && TYPE_P (ctx))
> > > +     ctx = TYPE_CONTEXT (ctx);
> > > +   if (ctx)
> > > +     {
> > > +       if (TREE_CODE (ctx) == BLOCK)
> > > + 	parent = BLOCK_DIE (ctx);
> > > +       else if (TREE_CODE (ctx) == TRANSLATION_UNIT_DECL
> > > + 	       /* Keep the 1:1 association during WPA.  */
> > > + 	       && !flag_wpa)
> > > + 	/* Otherwise all late annotations go to the main CU which
> > > + 	   imports the original CUs.  */
> > > + 	parent = comp_unit_die ();
> > > +       else if (TREE_CODE (ctx) == FUNCTION_DECL
> > > + 	       && TREE_CODE (decl) != PARM_DECL
> > > + 	       && TREE_CODE (decl) != BLOCK)
> > > + 	/* Leave function local entities parent determination to when
> > > + 	   we process scope vars.  */
> > > + 	;
> > > +       else
> > > + 	parent = lookup_decl_die (ctx);
> > > +     }
> > > +   else
> > > +     /* ???  In some cases the C++ FE (at least) fails to
> > > +        set DECL_CONTEXT properly.  Simply globalize stuff
> > > +        in this case.  For example
> > > +        __dso_handle created via iostream line 74 col 25.  */
> > > +     parent = comp_unit_die ();
> > > +   /* Create a DIE "stub".  */
> > > +   switch (TREE_CODE (decl))
> > > +     {
> > > +     case TRANSLATION_UNIT_DECL:
> > > +       if (! flag_wpa)
> > > + 	{
> > > + 	  die = comp_unit_die ();
> > > + 	  dw_die_ref import = new_die (DW_TAG_imported_unit, die, NULL_TREE);
> > > + 	  add_AT_external_die_ref (import, DW_AT_import, sym, off);
> > > + 	  /* We re-target all CU decls to the LTRANS CU DIE, so no need
> > > + 	     to create a DIE for the original CUs.  */
> > > + 	  return;
> > > + 	}
> > > +       /* Keep the 1:1 association during WPA.  */
> > > +       die = new_die (DW_TAG_compile_unit, NULL, decl);
> > > +       break;
> > > +     case NAMESPACE_DECL:
> > > +       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
> > > + 	 at the input language (if we have enough DECL_CONTEXT to follow)
> > > + 	 or use a bit in tree_decl_with_vis to record the distinction.  */
> > > +       die = new_die (DW_TAG_namespace, parent, decl);
> > > +       break;
> > > +     case FUNCTION_DECL:
> > > +       die = new_die (DW_TAG_subprogram, parent, decl);
> > > +       break;
> > > +     case VAR_DECL:
> > > +       die = new_die (DW_TAG_variable, parent, decl);
> > > +       break;
> > > +     case RESULT_DECL:
> > > +       die = new_die (DW_TAG_variable, parent, decl);
> > > +       break;
> > > +     case PARM_DECL:
> > > +       die = new_die (DW_TAG_formal_parameter, parent, decl);
> > > +       break;
> > > +     case CONST_DECL:
> > > +       die = new_die (DW_TAG_constant, parent, decl);
> > > +       break;
> > > +     case LABEL_DECL:
> > > +       die = new_die (DW_TAG_label, parent, decl);
> > > +       break;
> > > +     case BLOCK:
> > > +       die = new_die (DW_TAG_lexical_block, parent, decl);
> > > +       break;
> > > +     default:
> > > +       gcc_unreachable ();
> > > +     }
> > > +   if (TREE_CODE (decl) == BLOCK)
> > > +     BLOCK_DIE (decl) = die;
> > > +   else
> > > +     equate_decl_number_to_die (decl, die);
> > > + 
> > > +   /* Add a reference to the DIE providing early debug at $sym + off.  */
> > > +   add_AT_external_die_ref (die, DW_AT_abstract_origin, sym, off);
> > > + }
> > > + 
> > >   /* Returns a hash value for X (which really is a var_loc_list).  */
> > >   
> > >   inline hashval_t
> > > *************** print_dw_val (dw_val_node *val, bool rec
> > > *** 5900,5906 ****
> > >   			       die->die_id.die_type_node->signature);
> > >   	    }
> > >   	  else if (die->die_id.die_symbol)
> > > ! 	    fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
> > >   	  else
> > >   	    fprintf (outfile, "die -> %ld", die->die_offset);
> > >   	  fprintf (outfile, " (%p)", (void *) die);
> > > --- 6150,6160 ----
> > >   			       die->die_id.die_type_node->signature);
> > >   	    }
> > >   	  else if (die->die_id.die_symbol)
> > > ! 	    {
> > > ! 	      fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
> > > ! 	      if (die->with_offset)
> > > ! 		fprintf (outfile, " + %ld", die->die_offset);
> > > ! 	    }
> > >   	  else
> > >   	    fprintf (outfile, "die -> %ld", die->die_offset);
> > >   	  fprintf (outfile, " (%p)", (void *) die);
> > > *************** static unsigned int comdat_symbol_number
> > > *** 7216,7222 ****
> > >      children, and set comdat_symbol_id accordingly.  */
> > >   
> > >   static void
> > > ! compute_section_prefix (dw_die_ref unit_die)
> > >   {
> > >     const char *die_name = get_AT_string (unit_die, DW_AT_name);
> > >     const char *base = die_name ? lbasename (die_name) : "anonymous";
> > > --- 7470,7476 ----
> > >      children, and set comdat_symbol_id accordingly.  */
> > >   
> > >   static void
> > > ! compute_section_prefix_1 (dw_die_ref unit_die, bool comdat_p)
> > >   {
> > >     const char *die_name = get_AT_string (unit_die, DW_AT_name);
> > >     const char *base = die_name ? lbasename (die_name) : "anonymous";
> > > *************** compute_section_prefix (dw_die_ref unit_
> > > *** 7235,7241 ****
> > >     unmark_all_dies (unit_die);
> > >     md5_finish_ctx (&ctx, checksum);
> > >   
> > > !   sprintf (name, "%s.", base);
> > >     clean_symbol_name (name);
> > >   
> > >     p = name + strlen (name);
> > > --- 7489,7499 ----
> > >     unmark_all_dies (unit_die);
> > >     md5_finish_ctx (&ctx, checksum);
> > >   
> > > !   /* When we this for comp_unit_die () we have a DW_AT_name that might
> > > !      not start with a letter but with anything valid for filenames and
> > > !      clean_symbol_name doesn't fix that up.  Prepend 'g' if the first
> > > !      character is not a letter.  */
> > > !   sprintf (name, "%s%s.", ISALPHA (*base) ? "" : "g", base);
> > >     clean_symbol_name (name);
> > >   
> > >     p = name + strlen (name);
> > > *************** compute_section_prefix (dw_die_ref unit_
> > > *** 7245,7251 ****
> > >         p += 2;
> > >       }
> > >   
> > > !   comdat_symbol_id = unit_die->die_id.die_symbol = xstrdup (name);
> > >     comdat_symbol_number = 0;
> > >   }
> > >   
> > > --- 7503,7517 ----
> > >         p += 2;
> > >       }
> > >   
> > > !   unit_die->die_id.die_symbol = xstrdup (name);
> > > !   unit_die->comdat_type_p = comdat_p;
> > > ! }
> > > ! 
> > > ! static void
> > > ! compute_section_prefix (dw_die_ref unit_die)
> > > ! {
> > > !   compute_section_prefix_1 (unit_die, true);
> > > !   comdat_symbol_id = unit_die->die_id.die_symbol;
> > >     comdat_symbol_number = 0;
> > >   }
> > >   
> > > *************** output_die (dw_die_ref die)
> > > *** 9971,9977 ****
> > >   
> > >     /* If someone in another CU might refer to us, set up a symbol for
> > >        them to point to.  */
> > > !   if (! die->comdat_type_p && die->die_id.die_symbol)
> > >       output_die_symbol (die);
> > >   
> > >     dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
> > > --- 10237,10247 ----
> > >   
> > >     /* If someone in another CU might refer to us, set up a symbol for
> > >        them to point to.  */
> > > !   if (! die->comdat_type_p && die->die_id.die_symbol
> > > !       /* Don't output the symbol twice.  For LTO we want the label
> > > !          on the section beginning, not on the actual DIE.  */
> > > !       && (!flag_generate_lto
> > > ! 	  || die->die_tag != DW_TAG_compile_unit))
> > >       output_die_symbol (die);
> > >   
> > >     dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
> > > *************** output_die (dw_die_ref die)
> > > *** 10164,10171 ****
> > >   		    size = DWARF2_ADDR_SIZE;
> > >   		  else
> > >   		    size = DWARF_OFFSET_SIZE;
> > > ! 		  dw2_asm_output_offset (size, sym, debug_info_section, "%s",
> > > ! 					 name);
> > >   		}
> > >   	    }
> > >   	  else
> > > --- 10434,10453 ----
> > >   		    size = DWARF2_ADDR_SIZE;
> > >   		  else
> > >   		    size = DWARF_OFFSET_SIZE;
> > > ! 		  /* ???  We cannot unconditionally output die_offset if
> > > ! 		     non-zero - at least -feliminate-dwarf2-dups will
> > > ! 		     create references to those DIEs via symbols.  And we
> > > ! 		     do not clear its DIE offset after outputting it
> > > ! 		     (and the label refers to the actual DIEs, not the
> > > ! 		     DWARF CU unit header which is when using label + offset
> > > ! 		     would be the correct thing to do).
> > > ! 		     ???  This is the reason for the with_offset flag.  */
> > > ! 		  if (AT_ref (a)->with_offset)
> > > ! 		    dw2_asm_output_offset (size, sym, AT_ref (a)->die_offset,
> > > ! 					   debug_info_section, "%s", name);
> > > ! 		  else
> > > ! 		    dw2_asm_output_offset (size, sym, debug_info_section, "%s",
> > > ! 					   name);
> > >   		}
> > >   	    }
> > >   	  else
> > > *************** output_comp_unit (dw_die_ref die, int ou
> > > *** 10391,10397 ****
> > >     calc_die_sizes (die);
> > >   
> > >     oldsym = die->die_id.die_symbol;
> > > !   if (oldsym)
> > >       {
> > >         tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
> > >   
> > > --- 10673,10679 ----
> > >     calc_die_sizes (die);
> > >   
> > >     oldsym = die->die_id.die_symbol;
> > > !   if (oldsym && die->comdat_type_p)
> > >       {
> > >         tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
> > >   
> > > *************** output_comp_unit (dw_die_ref die, int ou
> > > *** 10407,10412 ****
> > > --- 10689,10721 ----
> > >         info_section_emitted = true;
> > >       }
> > >   
> > > +   /* For LTO cross unit DIE refs we want a symbol on the start of the
> > > +      debuginfo section, not on the CU DIE.
> > > +      ???  We could simply use the symbol as it would be output by output_die
> > > +      and account for the extra offset produced by the CU header which has fixed
> > > +      size.  OTOH it currently only supports linkonce globals which would
> > > +      be less than ideal?.  */
> > > +   if (flag_generate_lto && oldsym)
> > > +     {
> > > +       /* ???  No way to get visibility assembled without a decl.  */
> > > +       tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
> > > + 			      get_identifier (oldsym), char_type_node);
> > > +       TREE_PUBLIC (decl) = true;
> > > +       TREE_STATIC (decl) = true;
> > > +       DECL_ARTIFICIAL (decl) = true;
> > > +       DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
> > > +       DECL_VISIBILITY_SPECIFIED (decl) = true;
> > > +       targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
> > > + #ifdef ASM_WEAKEN_LABEL
> > > +       /* We prefer a .weak because that handles duplicates from duplicate
> > > +          archive members in a graceful way.  */
> > > +       ASM_WEAKEN_LABEL (asm_out_file, oldsym);
> > > + #else
> > > +       targetm.asm_out.globalize_label (asm_out_file, oldsym);
> > > + #endif
> > > +       ASM_OUTPUT_LABEL (asm_out_file, oldsym);
> > > +     }
> > > + 
> > >     /* Output debugging information.  */
> > >     output_compilation_unit_header (dwo_id
> > >   				  ? DW_UT_split_compile : DW_UT_compile);
> > > *************** parameter_ref_descriptor (rtx rtl)
> > > *** 14523,14528 ****
> > > --- 14832,14840 ----
> > >     if (dwarf_strict)
> > >       return NULL;
> > >     gcc_assert (TREE_CODE (DEBUG_PARAMETER_REF_DECL (rtl)) == PARM_DECL);
> > > +   /* With LTO during LTRANS we get the late DIE that refers to the early
> > > +      DIE, thus we add another indirection here.  This seems to confuse
> > > +      gdb enough to make gcc.dg/guality/pr68860-1.c FAIL with LTO.  */
> > >     ref = lookup_decl_die (DEBUG_PARAMETER_REF_DECL (rtl));
> > >     ret = new_loc_descr (DW_OP_GNU_parameter_ref, 0, 0);
> > >     if (ref)
> > > *************** add_abstract_origin_attribute (dw_die_re
> > > *** 20216,20222 ****
> > >       }
> > >   
> > >     if (DECL_P (origin))
> > > !     origin_die = lookup_decl_die (origin);
> > >     else if (TYPE_P (origin))
> > >       origin_die = lookup_type_die (origin);
> > >     else if (TREE_CODE (origin) == BLOCK)
> > > --- 20528,20547 ----
> > >       }
> > >   
> > >     if (DECL_P (origin))
> > > !     {
> > > !       dw_die_ref c;
> > > !       origin_die = lookup_decl_die (origin);
> > > !       /* "Unwrap" the decls DIE which we put in the imported unit context.
> > > !           ???  If we finish dwarf2out_function_decl refactoring we can
> > > ! 	  do this in a better way from the start and only lazily emit
> > > ! 	  the early DIE references.  */
> > > !       if (in_lto_p
> > > ! 	  && origin_die
> > > ! 	  && (c = get_AT_ref (origin_die, DW_AT_abstract_origin))
> > > ! 	  /* ???  Identify this better.  */
> > > ! 	  && c->with_offset)
> > > ! 	origin_die = c;
> > > !     }
> > >     else if (TYPE_P (origin))
> > >       origin_die = lookup_type_die (origin);
> > >     else if (TREE_CODE (origin) == BLOCK)
> > > *************** gen_array_type_die (tree type, dw_die_re
> > > *** 20775,20781 ****
> > >         size = int_size_in_bytes (type);
> > >         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)
> > >   	{
> > >   	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> > > --- 21100,21109 ----
> > >         size = int_size_in_bytes (type);
> > >         if (size >= 0)
> > >   	add_AT_unsigned (array_die, DW_AT_byte_size, size);
> > > !       /* ???  We can't annotate types late, but for LTO we may not
> > > ! 	 generate a location early either (gfortran.dg/save_6.f90).  */
> > > !       else if (! (early_dwarf && flag_generate_lto)
> > > ! 	       && TYPE_DOMAIN (type) != NULL_TREE
> > >   	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE)
> > >   	{
> > >   	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> > > *************** gen_formal_parameter_die (tree node, tre
> > > *** 21188,21194 ****
> > >   	 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
> > > --- 21516,21524 ----
> > >   	 thing.  */
> > >         if (parm_die && parm_die->die_parent != context_die)
> > >   	{
> > > ! 	  /* ???  The DIE parent is the "abstract" copy and the context_die
> > > ! 	     is the specification "copy".  */
> > > ! 	  if (!DECL_ABSTRACT_P (node) && !in_lto_p)
> > >   	    {
> > >   	      /* This can happen when creating an inlined instance, in
> > >   		 which case we need to create a new DIE that will get
> > > *************** gen_type_die_for_member (tree type, tree
> > > *** 21462,21468 ****
> > >   /* 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, 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
> > > --- 21792,21797 ----
> > > *************** set_decl_origin_self (tree decl)
> > > *** 21535,21685 ****
> > >       }
> > >   }
> > >   \f
> > > ! /* 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, vec<tree> &abstract_vec)
> > > ! {
> > > !   tree local_decl;
> > > !   tree subblock;
> > > !   unsigned int i;
> > > ! 
> > > !   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, abstract_vec);
> > > ! 
> > > !   for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
> > > !     {
> > > !       local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i);
> > > !       if ((VAR_P (local_decl) && !TREE_STATIC (local_decl))
> > > ! 	  || TREE_CODE (local_decl) == PARM_DECL)
> > > ! 	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, abstract_vec);
> > > ! }
> > > ! 
> > > ! /* 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, vec<tree> &abstract_vec)
> > > ! {
> > > !   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))
> > > ! 	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), 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.
> > > ! 
> > > !    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)
> > >   {
> > >     dw_die_ref old_die;
> > > -   tree save_fn;
> > > -   tree context;
> > > -   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;
> > > -   struct call_arg_loc_node *old_call_arg_locations;
> > >   
> > >     /* Make sure we have the actual abstract inline, not a clone.  */
> > >     decl = DECL_ORIGIN (decl);
> > >   
> > >     old_die = lookup_decl_die (decl);
> > > !   if (old_die && get_AT (old_die, DW_AT_inline))
> > >       /* We've already generated the abstract instance.  */
> > >       return;
> > >   
> > > !   /* We can be called while recursively when seeing block defining inlined subroutine
> > > !      DIE.  Be sure to not clobber the outer location table nor use it or we would
> > > !      get locations in abstract instantces.  */
> > > !   old_decl_loc_table = decl_loc_table;
> > > !   decl_loc_table = NULL;
> > > !   old_cached_dw_loc_list_table = cached_dw_loc_list_table;
> > > !   cached_dw_loc_list_table = NULL;
> > > !   old_call_arg_locations = call_arg_locations;
> > > !   call_arg_locations = NULL;
> > > !   old_call_site_count = call_site_count;
> > > !   call_site_count = -1;
> > > !   old_tail_call_site_count = tail_call_site_count;
> > > !   tail_call_site_count = -1;
> > > ! 
> > > !   /* Be sure we've emitted the in-class declaration DIE (if any) first, so
> > > !      we don't get confused by DECL_ABSTRACT_P.  */
> > > !   if (debug_info_level > DINFO_LEVEL_TERSE)
> > >       {
> > > !       context = decl_class_context (decl);
> > > !       if (context)
> > > ! 	gen_type_die_for_member
> > > ! 	  (context, decl, decl_function_context (decl) ? NULL : comp_unit_die ());
> > >       }
> > >   
> > > !   /* Pretend we've just finished compiling this function.  */
> > > !   save_fn = current_function_decl;
> > > !   current_function_decl = decl;
> > > ! 
> > > !   auto_vec<tree, 64> abstract_vec;
> > > !   set_decl_abstract_flags (decl, abstract_vec);
> > > !   dwarf2out_decl (decl);
> > > !   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;
> > > !   cached_dw_loc_list_table = old_cached_dw_loc_list_table;
> > > !   call_arg_locations = old_call_arg_locations;
> > > !   call_site_count = old_call_site_count;
> > > !   tail_call_site_count = old_tail_call_site_count;
> > >   }
> > >   
> > >   /* Helper function of premark_used_types() which gets called through
> > > --- 21864,21908 ----
> > >       }
> > >   }
> > >   \f
> > > ! /* Mark the early DIE for DECL as the abstract instance.  */
> > >   
> > >   static void
> > >   dwarf2out_abstract_function (tree decl)
> > >   {
> > >     dw_die_ref old_die;
> > >   
> > >     /* Make sure we have the actual abstract inline, not a clone.  */
> > >     decl = DECL_ORIGIN (decl);
> > >   
> > > +   if (DECL_IGNORED_P (decl))
> > > +     return;
> > > + 
> > >     old_die = lookup_decl_die (decl);
> > > !   /* With early debug we always have an old DIE.  */
> > > !   gcc_assert (old_die != NULL);
> > > !   if (get_AT (old_die, DW_AT_inline))
> > >       /* We've already generated the abstract instance.  */
> > >       return;
> > >   
> > > !   /* Go ahead and put DW_AT_inline on the DIE.  */
> > > !   if (DECL_DECLARED_INLINE_P (decl))
> > >       {
> > > !       if (cgraph_function_possibly_inlined_p (decl))
> > > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_inlined);
> > > !       else
> > > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_not_inlined);
> > > !     }
> > > !   else
> > > !     {
> > > !       if (cgraph_function_possibly_inlined_p (decl))
> > > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_inlined);
> > > !       else
> > > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_not_inlined);
> > >       }
> > >   
> > > !   if (DECL_DECLARED_INLINE_P (decl)
> > > !       && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
> > > !     add_AT_flag (old_die, DW_AT_artificial, 1);
> > >   }
> > >   
> > >   /* Helper function of premark_used_types() which gets called through
> > > *************** gen_subprogram_die (tree decl, dw_die_re
> > > *** 21901,21907 ****
> > >         if (old_die && old_die->die_parent == NULL)
> > >   	add_child_die (context_die, old_die);
> > >   
> > > !       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.  */
> > > --- 22124,22135 ----
> > >         if (old_die && old_die->die_parent == NULL)
> > >   	add_child_die (context_die, old_die);
> > >   
> > > !       dw_die_ref c;
> > > !       if (old_die
> > > ! 	  && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
> > > ! 	  /* ???  In LTO all origin DIEs still refer to the early
> > > ! 	     debug copy.  Detect that.  */
> > > ! 	  && get_AT (c, DW_AT_inline))
> > >   	{
> > >   	  /* If we have a DW_AT_abstract_origin we have a working
> > >   	     cached version.  */
> > > *************** gen_subprogram_die (tree decl, dw_die_re
> > > *** 21969,21975 ****
> > >   	   || (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)
> > > --- 22197,22204 ----
> > >   	   || (old_die->die_parent
> > >   	       && old_die->die_parent->die_tag == DW_TAG_module)
> > >   	   || context_die == NULL)
> > > ! 	  /* ???  In LTO we do not see any of the location attributes.  */
> > > ! 	   && ((DECL_ARTIFICIAL (decl) || in_lto_p)
> > >   	       || (get_AT_file (old_die, DW_AT_decl_file) == file_index
> > >   		   && (get_AT_unsigned (old_die, DW_AT_decl_line)
> > >   		       == (unsigned) s.line)
> > > *************** gen_variable_die (tree decl, tree origin
> > > *** 22836,22841 ****
> > > --- 23065,23088 ----
> > >   	  /* If a DIE was dumped early, it still needs location info.
> > >   	     Skip to where we fill the location bits.  */
> > >   	  var_die = old_die;
> > > + 
> > > + 	  /* ???  In LTRANS we cannot annotate early created variably
> > > + 	     modified type DIEs without copying them and adjusting all
> > > + 	     references to them.  Thus we dumped them again, also add a
> > > + 	     reference to them.  */
> > > + 	  tree type = TREE_TYPE (decl_or_origin);
> > > + 	  if (in_lto_p
> > > + 	      && variably_modified_type_p
> > > + 		   (type, decl_function_context (decl_or_origin)))
> > > + 	    {
> > > + 	      if (decl_by_reference_p (decl_or_origin))
> > > + 		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),
> > > + 				    false, context_die);
> > > + 	    }
> > > + 
> > >   	  goto gen_variable_die_location;
> > >   	}
> > >       }
> > > *************** gen_inlined_subroutine_die (tree stmt, d
> > > *** 23236,23247 ****
> > >     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
> > > -      a die whose origin die hasn't been emitted, and crashing.  */
> > > -   dwarf2out_abstract_function (decl);
> > > - 
> > >     if (! BLOCK_ABSTRACT (stmt))
> > >       {
> > >         dw_die_ref subr_die
> > > --- 23483,23488 ----
> > > *************** process_scope_var (tree stmt, tree decl,
> > > *** 24868,24874 ****
> > >   					     stmt, context_die);
> > >       }
> > >     else
> > > !     gen_decl_die (decl, origin, NULL, context_die);
> > >   }
> > >   
> > >   /* Generate all of the decls declared within a given scope and (recursively)
> > > --- 25109,25128 ----
> > >   					     stmt, context_die);
> > >       }
> > >     else
> > > !     {
> > > !       if (decl && DECL_P (decl))
> > > ! 	{
> > > ! 	  die = lookup_decl_die (decl);
> > > ! 
> > > ! 	  /* Early created DIEs do not have a parent as the decls refer
> > > ! 	     to the function as DECL_CONTEXT rather than the BLOCK.  */
> > > ! 	  if (in_lto_p
> > > ! 	      && die && die->die_parent == NULL)
> > > ! 	    add_child_die (context_die, die);
> > > ! 	}
> > > ! 
> > > !       gen_decl_die (decl, origin, NULL, context_die);
> > > !     }
> > >   }
> > >   
> > >   /* Generate all of the decls declared within a given scope and (recursively)
> > > *************** gen_decl_die (tree decl, tree origin, st
> > > *** 25288,25295 ****
> > >   				     ? DECL_ORIGIN (origin)
> > >   				     : DECL_ABSTRACT_ORIGIN (decl));
> > >   
> > > !       /* If we're emitting an out-of-line copy of an inline function,
> > > ! 	 emit info for the abstract instance and set up to refer to it.  */
> > >         else if (cgraph_function_possibly_inlined_p (decl)
> > >   	       && ! DECL_ABSTRACT_P (decl)
> > >   	       && ! class_or_namespace_scope_p (context_die)
> > > --- 25542,25549 ----
> > >   				     ? DECL_ORIGIN (origin)
> > >   				     : DECL_ABSTRACT_ORIGIN (decl));
> > >   
> > > !       /* If we're emitting a possibly inlined function emit it as
> > > !          abstract instance.  */
> > >         else if (cgraph_function_possibly_inlined_p (decl)
> > >   	       && ! DECL_ABSTRACT_P (decl)
> > >   	       && ! class_or_namespace_scope_p (context_die)
> > > *************** gen_decl_die (tree decl, tree origin, st
> > > *** 25303,25309 ****
> > >   	}
> > >   
> > >         /* Otherwise we're emitting the primary DIE for this decl.  */
> > > !       else if (debug_info_level > DINFO_LEVEL_TERSE)
> > >   	{
> > >   	  /* Before we describe the FUNCTION_DECL itself, make sure that we
> > >   	     have its containing type.  */
> > > --- 25557,25565 ----
> > >   	}
> > >   
> > >         /* Otherwise we're emitting the primary DIE for this decl.  */
> > > !       else if (debug_info_level > DINFO_LEVEL_TERSE
> > > ! 	       /* Do not generate stray type DIEs in late LTO dumping.  */
> > > ! 	       && early_dwarf)
> > >   	{
> > >   	  /* Before we describe the FUNCTION_DECL itself, make sure that we
> > >   	     have its containing type.  */
> > > *************** gen_decl_die (tree decl, tree origin, st
> > > *** 25370,25389 ****
> > >         if (debug_info_level <= DINFO_LEVEL_TERSE)
> > >   	break;
> > >   
> > > !       /* Output any DIEs that are needed to specify the type of this data
> > > ! 	 object.  */
> > > !       if (decl_by_reference_p (decl_or_origin))
> > > ! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > > !       else
> > > ! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> > >   
> > > !       /* And its containing type.  */
> > > !       class_origin = decl_class_context (decl_or_origin);
> > > !       if (class_origin != NULL_TREE)
> > > ! 	gen_type_die_for_member (class_origin, decl_or_origin, context_die);
> > >   
> > > !       /* And its containing namespace.  */
> > > !       context_die = declare_in_namespace (decl_or_origin, context_die);
> > >   
> > >         /* Now output the DIE to represent the data object itself.  This gets
> > >   	 complicated because of the possibility that the VAR_DECL really
> > > --- 25626,25661 ----
> > >         if (debug_info_level <= DINFO_LEVEL_TERSE)
> > >   	break;
> > >   
> > > !       /* Avoid generating stray type DIEs during late dwarf dumping.
> > > !          All types have been dumped early.  */
> > > !       if (! lookup_decl_die (decl_or_origin)
> > > ! 	  /* ???  But in LTRANS we cannot annotate early created variably
> > > ! 	     modified type DIEs without copying them and adjusting all
> > > ! 	     references to them.  Dump them again as happens for inlining
> > > ! 	     which copies both the decl and the types.  */
> > > ! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
> > > ! 	     in VLA bound information for example.  */
> > > ! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
> > > ! 						current_function_decl)))
> > > ! 	{
> > > ! 	  /* Output any DIEs that are needed to specify the type of this data
> > > ! 	     object.  */
> > > ! 	  if (decl_by_reference_p (decl_or_origin))
> > > ! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > > ! 	  else
> > > ! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> > > ! 	}
> > >   
> > > !       if (early_dwarf)
> > > ! 	{
> > > ! 	  /* And its containing type.  */
> > > ! 	  class_origin = decl_class_context (decl_or_origin);
> > > ! 	  if (class_origin != NULL_TREE)
> > > ! 	    gen_type_die_for_member (class_origin, decl_or_origin, context_die);
> > >   
> > > ! 	  /* And its containing namespace.  */
> > > ! 	  context_die = declare_in_namespace (decl_or_origin, context_die);
> > > ! 	}
> > >   
> > >         /* Now output the DIE to represent the data object itself.  This gets
> > >   	 complicated because of the possibility that the VAR_DECL really
> > > *************** gen_decl_die (tree decl, tree origin, st
> > > *** 25413,25422 ****
> > >         break;
> > >   
> > >       case PARM_DECL:
> > > !       if (DECL_BY_REFERENCE (decl_or_origin))
> > > ! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > > !       else
> > > ! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> > >         return gen_formal_parameter_die (decl, origin,
> > >   				       true /* Emit name attribute.  */,
> > >   				       context_die);
> > > --- 25685,25707 ----
> > >         break;
> > >   
> > >       case PARM_DECL:
> > > !       /* Avoid generating stray type DIEs during late dwarf dumping.
> > > !          All types have been dumped early.  */
> > > !       if (! lookup_decl_die (decl_or_origin)
> > > ! 	  /* ???  But in LTRANS we cannot annotate early created variably
> > > ! 	     modified type DIEs without copying them and adjusting all
> > > ! 	     references to them.  Dump them again as happens for inlining
> > > ! 	     which copies both the decl and the types.  */
> > > ! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
> > > ! 	     in VLA bound information for example.  */
> > > ! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
> > > ! 						current_function_decl)))
> > > ! 	{
> > > ! 	  if (DECL_BY_REFERENCE (decl_or_origin))
> > > ! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > > ! 	  else
> > > ! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> > > ! 	}
> > >         return gen_formal_parameter_die (decl, origin,
> > >   				       true /* Emit name attribute.  */,
> > >   				       context_die);
> > > *************** dwarf2out_early_global_decl (tree decl)
> > > *** 25493,25498 ****
> > > --- 25778,25793 ----
> > >   	      dwarf2out_decl (context);
> > >   	    }
> > >   
> > > + 	  /* Emit an abstract origin of a function first.  This happens
> > > + 	     with C++ constructor clones for example and makes
> > > + 	     dwarf2out_abstract_function happy which requires the early
> > > + 	     DIE of the abstract instance to be present.  */
> > > + 	  if (DECL_ABSTRACT_ORIGIN (decl))
> > > + 	    {
> > > + 	      current_function_decl = DECL_ABSTRACT_ORIGIN (decl);
> > > + 	      dwarf2out_decl (DECL_ABSTRACT_ORIGIN (decl));
> > > + 	    }
> > > + 
> > >   	  current_function_decl = decl;
> > >   	}
> > >         dwarf2out_decl (decl);
> > > *************** dwarf2out_late_global_decl (tree decl)
> > > *** 25515,25521 ****
> > >       {
> > >         dw_die_ref die = lookup_decl_die (decl);
> > >   
> > > !       /* We have to generate early debug late for LTO.  */
> > >         if (! die && in_lto_p)
> > >   	{
> > >   	  dwarf2out_decl (decl);
> > > --- 25810,25818 ----
> > >       {
> > >         dw_die_ref die = lookup_decl_die (decl);
> > >   
> > > !       /* We may have to generate early debug late for LTO in case debug
> > > !          was not enabled at compile-time or the target doesn't support
> > > ! 	 the LTO early debug scheme.  */
> > >         if (! die && in_lto_p)
> > >   	{
> > >   	  dwarf2out_decl (decl);
> > > *************** output_macinfo_op (macinfo_entry *ref)
> > > *** 26892,26898 ****
> > >       case DW_MACRO_import:
> > >         dw2_asm_output_data (1, ref->code, "Import");
> > >         ASM_GENERATE_INTERNAL_LABEL (label,
> > > ! 				   DEBUG_MACRO_SECTION_LABEL, ref->lineno);
> > >         dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
> > >         break;
> > >       default:
> > > --- 27189,27196 ----
> > >       case DW_MACRO_import:
> > >         dw2_asm_output_data (1, ref->code, "Import");
> > >         ASM_GENERATE_INTERNAL_LABEL (label,
> > > ! 				   DEBUG_MACRO_SECTION_LABEL,
> > > ! 				   ref->lineno + macinfo_label_base);
> > >         dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
> > >         break;
> > >       default:
> > > *************** save_macinfo_strings (void)
> > > *** 27066,27072 ****
> > >   /* Output macinfo section(s).  */
> > >   
> > >   static void
> > > ! output_macinfo (void)
> > >   {
> > >     unsigned i;
> > >     unsigned long length = vec_safe_length (macinfo_table);
> > > --- 27364,27370 ----
> > >   /* Output macinfo section(s).  */
> > >   
> > >   static void
> > > ! output_macinfo (const char *debug_line_label, bool early_lto_debug)
> > >   {
> > >     unsigned i;
> > >     unsigned long length = vec_safe_length (macinfo_table);
> > > *************** output_macinfo (void)
> > > *** 27092,27100 ****
> > >   	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
> > >         else
> > >   	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
> > > !       dw2_asm_output_offset (DWARF_OFFSET_SIZE,
> > > !                              (!dwarf_split_debug_info ? debug_line_section_label
> > > !                               : debug_skeleton_line_section_label),
> > >                                debug_line_section, NULL);
> > >       }
> > >   
> > > --- 27390,27396 ----
> > >   	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
> > >         else
> > >   	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
> > > !       dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_line_label,
> > >                                debug_line_section, NULL);
> > >       }
> > >   
> > > *************** output_macinfo (void)
> > > *** 27148,27153 ****
> > > --- 27444,27453 ----
> > >     if (!macinfo_htab)
> > >       return;
> > >   
> > > +   /* Save the number of transparent includes so we can adjust the
> > > +      label number for the fat LTO object DWARF.  */
> > > +   unsigned macinfo_label_base_adj = macinfo_htab->elements ();
> > > + 
> > >     delete macinfo_htab;
> > >     macinfo_htab = NULL;
> > >   
> > > *************** output_macinfo (void)
> > > *** 27167,27177 ****
> > >   	  dw2_asm_output_data (1, 0, "End compilation unit");
> > >   	  targetm.asm_out.named_section (debug_macinfo_section_name,
> > >   					 SECTION_DEBUG
> > > ! 					 | SECTION_LINKONCE,
> > >   					 comdat_key);
> > >   	  ASM_GENERATE_INTERNAL_LABEL (label,
> > >   				       DEBUG_MACRO_SECTION_LABEL,
> > > ! 				       ref->lineno);
> > >   	  ASM_OUTPUT_LABEL (asm_out_file, label);
> > >   	  ref->code = 0;
> > >   	  ref->info = NULL;
> > > --- 27467,27479 ----
> > >   	  dw2_asm_output_data (1, 0, "End compilation unit");
> > >   	  targetm.asm_out.named_section (debug_macinfo_section_name,
> > >   					 SECTION_DEBUG
> > > ! 					 | SECTION_LINKONCE
> > > ! 					 | (early_lto_debug
> > > ! 					    ? SECTION_EXCLUDE : 0),
> > >   					 comdat_key);
> > >   	  ASM_GENERATE_INTERNAL_LABEL (label,
> > >   				       DEBUG_MACRO_SECTION_LABEL,
> > > ! 				       ref->lineno + macinfo_label_base);
> > >   	  ASM_OUTPUT_LABEL (asm_out_file, label);
> > >   	  ref->code = 0;
> > >   	  ref->info = NULL;
> > > *************** output_macinfo (void)
> > > *** 27192,27300 ****
> > >         default:
> > >   	gcc_unreachable ();
> > >         }
> > >   }
> > >   
> > > ! /* Initialize the various sections and labels for dwarf output.  */
> > >   
> > >   static void
> > > ! init_sections_and_labels (void)
> > >   {
> > > !   if (!dwarf_split_debug_info)
> > >       {
> > > !       debug_info_section = get_section (DEBUG_INFO_SECTION,
> > > !                                         SECTION_DEBUG, NULL);
> > > !       debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > > !                                           SECTION_DEBUG, NULL);
> > > !       debug_loc_section = get_section (dwarf_version >= 5
> > > ! 				       ? DEBUG_LOCLISTS_SECTION
> > > ! 				       : DEBUG_LOC_SECTION,
> > > !                                        SECTION_DEBUG, NULL);
> > > !       debug_macinfo_section_name
> > > ! 	= (dwarf_strict && dwarf_version < 5)
> > > ! 	  ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
> > > !       debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > ! 					   SECTION_DEBUG, NULL);
> > >       }
> > >     else
> > >       {
> > > !       debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
> > > !                                         SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > !       debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
> > > !                                           SECTION_DEBUG | SECTION_EXCLUDE,
> > > !                                           NULL);
> > > !       debug_addr_section = get_section (DEBUG_ADDR_SECTION,
> > > !                                         SECTION_DEBUG, NULL);
> > > !       debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
> > > !                                                  SECTION_DEBUG, NULL);
> > > !       debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > > !                                                    SECTION_DEBUG, NULL);
> > > !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> > > !                                   DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0);
> > > ! 
> > > !       /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
> > > !          the main .o, but the skeleton_line goes into the split off dwo.  */
> > > !       debug_skeleton_line_section
> > > !         = get_section (DEBUG_DWO_LINE_SECTION,
> > > ! 		       SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > > !                                    DEBUG_SKELETON_LINE_SECTION_LABEL, 0);
> > > !       debug_str_offsets_section = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
> > > !                                                SECTION_DEBUG | SECTION_EXCLUDE,
> > > !                                                NULL);
> > > !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> > > !                                    DEBUG_SKELETON_INFO_SECTION_LABEL, 0);
> > > !       debug_loc_section = get_section (dwarf_version >= 5
> > > ! 				       ? DEBUG_DWO_LOCLISTS_SECTION
> > > ! 				       : DEBUG_DWO_LOC_SECTION,
> > > !                                        SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > !       debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
> > > !                                            DEBUG_STR_DWO_SECTION_FLAGS, NULL);
> > > !       debug_macinfo_section_name
> > > ! 	= (dwarf_strict && dwarf_version < 5)
> > > ! 	  ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
> > > !       debug_macinfo_section = get_section (debug_macinfo_section_name,
> > >   					   SECTION_DEBUG | SECTION_EXCLUDE,
> > >   					   NULL);
> > > !     }
> > > !   debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
> > > ! 				       SECTION_DEBUG, NULL);
> > > !   debug_line_section = get_section (DEBUG_LINE_SECTION,
> > > ! 				    SECTION_DEBUG, NULL);
> > > !   debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
> > > ! 					SECTION_DEBUG, NULL);
> > > !   debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
> > >   					SECTION_DEBUG, NULL);
> > > !   debug_str_section = get_section (DEBUG_STR_SECTION,
> > > ! 				   DEBUG_STR_SECTION_FLAGS, NULL);
> > > !   if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
> > > !     debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
> > > ! 					  DEBUG_STR_SECTION_FLAGS, NULL);
> > > ! 
> > > !   debug_ranges_section = get_section (dwarf_version >= 5
> > > ! 				      ? DEBUG_RNGLISTS_SECTION
> > > ! 				      : DEBUG_RANGES_SECTION,
> > > ! 				      SECTION_DEBUG, NULL);
> > > !   debug_frame_section = get_section (DEBUG_FRAME_SECTION,
> > > ! 				     SECTION_DEBUG, NULL);
> > >   
> > >     ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
> > > ! 			       DEBUG_ABBREV_SECTION_LABEL, 0);
> > >     ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
> > > ! 			       DEBUG_INFO_SECTION_LABEL, 0);
> > >     ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
> > > ! 			       DEBUG_LINE_SECTION_LABEL, 0);
> > >     ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
> > > ! 			       DEBUG_RANGES_SECTION_LABEL, 0);
> > >     if (dwarf_version >= 5 && dwarf_split_debug_info)
> > >       ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
> > > ! 				 DEBUG_RANGES_SECTION_LABEL, 1);
> > >     ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
> > > !                                DEBUG_ADDR_SECTION_LABEL, 0);
> > >     ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
> > >   			       (dwarf_strict && dwarf_version < 5)
> > >   			       ? DEBUG_MACINFO_SECTION_LABEL
> > > ! 			       : DEBUG_MACRO_SECTION_LABEL, 0);
> > > !   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0);
> > >   }
> > >   
> > >   /* Set up for Dwarf output at the start of compilation.  */
> > > --- 27494,27685 ----
> > >         default:
> > >   	gcc_unreachable ();
> > >         }
> > > + 
> > > +   macinfo_label_base += macinfo_label_base_adj;
> > >   }
> > >   
> > > ! /* Initialize the various sections and labels for dwarf output and prefix
> > > !    them with PREFIX if non-NULL.  */
> > >   
> > >   static void
> > > ! init_sections_and_labels (bool early_lto_debug)
> > >   {
> > > !   /* As we may get called multiple times have a generation count for labels.  */
> > > !   static unsigned generation = 0;
> > > ! 
> > > !   if (early_lto_debug)
> > >       {
> > > !       if (!dwarf_split_debug_info)
> > > ! 	{
> > > ! 	  debug_info_section = get_section (DEBUG_LTO_INFO_SECTION,
> > > ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> > > ! 					    NULL);
> > > ! 	  debug_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
> > > ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> > > ! 					      NULL);
> > > ! 	  debug_macinfo_section_name = ((dwarf_strict && dwarf_version < 5)
> > > ! 					? DEBUG_LTO_MACINFO_SECTION
> > > ! 					: DEBUG_LTO_MACRO_SECTION);
> > > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > ! 					       SECTION_DEBUG
> > > ! 					       | SECTION_EXCLUDE, NULL);
> > > ! 	  /* For macro info we have to refer to a debug_line section, so similar
> > > ! 	     to split-dwarf emit a skeleton one for early debug.  */
> > > ! 	  debug_skeleton_line_section
> > > ! 	    = get_section (DEBUG_LTO_LINE_SECTION,
> > > ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > > ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> > > ! 				       generation);
> > > ! 	}
> > > !       else
> > > ! 	{
> > > ! 	  /* ???  Which of the following do we need early?  */
> > > ! 	  debug_info_section = get_section (DEBUG_LTO_DWO_INFO_SECTION,
> > > ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> > > ! 					    NULL);
> > > ! 	  debug_abbrev_section = get_section (DEBUG_LTO_DWO_ABBREV_SECTION,
> > > ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> > > ! 					      NULL);
> > > ! 	  debug_skeleton_info_section = get_section (DEBUG_LTO_INFO_SECTION,
> > > ! 						     SECTION_DEBUG
> > > ! 						     | SECTION_EXCLUDE, NULL);
> > > ! 	  debug_skeleton_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
> > > ! 						       SECTION_DEBUG
> > > ! 						       | SECTION_EXCLUDE, NULL);
> > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> > > ! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
> > > ! 				       generation);
> > > ! 
> > > ! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
> > > ! 	     the main .o, but the skeleton_line goes into the split off dwo.  */
> > > ! 	  debug_skeleton_line_section
> > > ! 	    = get_section (DEBUG_LTO_LINE_SECTION,
> > > ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > > ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> > > ! 				       generation);
> > > ! 	  debug_str_offsets_section
> > > ! 	    = get_section (DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
> > > ! 			   SECTION_DEBUG | SECTION_EXCLUDE,
> > > ! 			   NULL);
> > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> > > ! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
> > > ! 				       generation);
> > > ! 	  debug_str_dwo_section = get_section (DEBUG_LTO_STR_DWO_SECTION,
> > > ! 					       DEBUG_STR_DWO_SECTION_FLAGS, NULL);
> > > ! 	  debug_macinfo_section_name
> > > ! 	    = (dwarf_strict
> > > ! 	       ? DEBUG_LTO_DWO_MACINFO_SECTION : DEBUG_LTO_DWO_MACRO_SECTION);
> > > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > ! 					       SECTION_DEBUG | SECTION_EXCLUDE,
> > > ! 					       NULL);
> > > ! 	}
> > > !       debug_str_section = get_section (DEBUG_LTO_STR_SECTION,
> > > ! 				       DEBUG_STR_SECTION_FLAGS
> > > ! 				       | SECTION_EXCLUDE, NULL);
> > >       }
> > >     else
> > >       {
> > > !       if (!dwarf_split_debug_info)
> > > ! 	{
> > > ! 	  debug_info_section = get_section (DEBUG_INFO_SECTION,
> > > ! 					    SECTION_DEBUG, NULL);
> > > ! 	  debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > > ! 					      SECTION_DEBUG, NULL);
> > > ! 	  debug_loc_section = get_section (DEBUG_LOC_SECTION,
> > > ! 					   SECTION_DEBUG, NULL);
> > > ! 	  debug_macinfo_section_name
> > > ! 	      = dwarf_strict ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
> > > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > ! 					       SECTION_DEBUG, NULL);
> > > ! 	}
> > > !       else
> > > ! 	{
> > > ! 	  debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
> > > ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> > > ! 					    NULL);
> > > ! 	  debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
> > > ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> > > ! 					      NULL);
> > > ! 	  debug_addr_section = get_section (DEBUG_ADDR_SECTION,
> > > ! 					    SECTION_DEBUG, NULL);
> > > ! 	  debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
> > > ! 						     SECTION_DEBUG, NULL);
> > > ! 	  debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > > ! 						       SECTION_DEBUG, NULL);
> > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> > > ! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
> > > ! 				       generation);
> > > ! 
> > > ! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections
> > > ! 	     stay in the main .o, but the skeleton_line goes into the
> > > ! 	     split off dwo.  */
> > > ! 	  debug_skeleton_line_section
> > > ! 	      = get_section (DEBUG_DWO_LINE_SECTION,
> > > ! 			     SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > > ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> > > ! 				       generation);
> > > ! 	  debug_str_offsets_section
> > > ! 	    = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
> > > ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> > > ! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
> > > ! 				       generation);
> > > ! 	  debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION,
> > >   					   SECTION_DEBUG | SECTION_EXCLUDE,
> > >   					   NULL);
> > > ! 	  debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
> > > ! 					       DEBUG_STR_DWO_SECTION_FLAGS,
> > > ! 					       NULL);
> > > ! 	  debug_macinfo_section_name
> > > ! 	    = (dwarf_strict && dwarf_version < 5)
> > > ! 	      ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
> > > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > ! 					       SECTION_DEBUG | SECTION_EXCLUDE,
> > > ! 					       NULL);
> > > ! 	}
> > > !       debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
> > > ! 					   SECTION_DEBUG, NULL);
> > > !       debug_line_section = get_section (DEBUG_LINE_SECTION,
> > >   					SECTION_DEBUG, NULL);
> > > !       debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
> > > ! 					    SECTION_DEBUG, NULL);
> > > !       debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
> > > ! 					    SECTION_DEBUG, NULL);
> > > !       debug_str_section = get_section (DEBUG_STR_SECTION,
> > > ! 				       DEBUG_STR_SECTION_FLAGS, NULL);
> > > !       debug_ranges_section = get_section (dwarf_version >= 5
> > > ! 					  ? DEBUG_RNGLISTS_SECTION
> > > ! 					  : DEBUG_RANGES_SECTION,
> > > ! 					  SECTION_DEBUG, NULL);
> > > !       debug_frame_section = get_section (DEBUG_FRAME_SECTION,
> > > ! 					 SECTION_DEBUG, NULL);
> > > !     }
> > >   
> > >     ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
> > > ! 			       DEBUG_ABBREV_SECTION_LABEL, generation);
> > >     ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
> > > ! 			       DEBUG_INFO_SECTION_LABEL, generation);
> > > !   info_section_emitted = false;
> > >     ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
> > > ! 			       DEBUG_LINE_SECTION_LABEL, generation);
> > >     ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
> > > ! 			       DEBUG_RANGES_SECTION_LABEL, generation);
> > >     if (dwarf_version >= 5 && dwarf_split_debug_info)
> > >       ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
> > > ! 				 DEBUG_RANGES_SECTION_LABEL, 2 + generation);
> > >     ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
> > > !                                DEBUG_ADDR_SECTION_LABEL, generation);
> > >     ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
> > >   			       (dwarf_strict && dwarf_version < 5)
> > >   			       ? DEBUG_MACINFO_SECTION_LABEL
> > > ! 			       : DEBUG_MACRO_SECTION_LABEL, generation);
> > > !   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL,
> > > ! 			       generation);
> > > ! 
> > > !   ++generation;
> > >   }
> > >   
> > >   /* Set up for Dwarf output at the start of compilation.  */
> > > *************** flush_limbo_die_list (void)
> > > *** 29641,29646 ****
> > > --- 30026,30047 ----
> > >       }
> > >   }
> > >   
> > > + /* Reset DIEs so we can output them again.  */
> > > + 
> > > + static void
> > > + reset_dies (dw_die_ref die)
> > > + {
> > > +   dw_die_ref c;
> > > + 
> > > +   /* Remove stuff we re-generate.  */
> > > +   die->die_mark = 0;
> > > +   die->die_offset = 0;
> > > +   die->die_abbrev = 0;
> > > +   remove_AT (die, DW_AT_sibling);
> > > + 
> > > +   FOR_EACH_CHILD (die, c, reset_dies (c));
> > > + }
> > > + 
> > >   /* Output stuff that dwarf requires at the end of every file,
> > >      and generate the DWARF-2 debugging info.  */
> > >   
> > > *************** dwarf2out_finish (const char *)
> > > *** 29667,29672 ****
> > > --- 30068,30113 ----
> > >   
> > >     gen_remaining_tmpl_value_param_die_attribute ();
> > >   
> > > +   if (flag_generate_lto)
> > > +     {
> > > +       gcc_assert (flag_fat_lto_objects);
> > > + 
> > > +       /* Prune stuff so that dwarf2out_finish runs successfully
> > > + 	 for the fat part of the object.  */
> > > +       reset_dies (comp_unit_die ());
> > > +       for (limbo_die_node *node = cu_die_list; node; node = node->next)
> > > + 	reset_dies (node->die);
> > > + 
> > > +       hash_table<comdat_type_hasher> comdat_type_table (100);
> > > +       for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
> > > + 	{
> > > + 	  comdat_type_node **slot
> > > + 	      = comdat_type_table.find_slot (ctnode, INSERT);
> > > + 
> > > + 	  /* Don't reset types twice.  */
> > > + 	  if (*slot != HTAB_EMPTY_ENTRY)
> > > + 	    continue;
> > > + 
> > > + 	  /* Add a pointer to the line table for the main compilation unit
> > > + 	     so that the debugger can make sense of DW_AT_decl_file
> > > + 	     attributes.  */
> > > + 	  if (debug_info_level >= DINFO_LEVEL_TERSE)
> > > + 	    reset_dies (ctnode->root_die);
> > > + 
> > > + 	  *slot = ctnode;
> > > + 	}
> > > + 
> > > +       /* Reset die CU symbol so we don't output it twice.  */
> > > +       comp_unit_die ()->die_id.die_symbol = NULL;
> > > + 
> > > +       /* Remove DW_AT_macro from the early output.  */
> > > +       if (have_macinfo)
> > > + 	remove_AT (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE);
> > > + 
> > > +       /* Remove indirect string decisions.  */
> > > +       debug_str_hash->traverse<void *, reset_indirect_string> (NULL);
> > > +     }
> > > + 
> > >   #if ENABLE_ASSERT_CHECKING
> > >     {
> > >       dw_die_ref die = comp_unit_die (), c;
> > > *************** dwarf2out_finish (const char *)
> > > *** 29677,29683 ****
> > >     move_marked_base_types ();
> > >   
> > >     /* Initialize sections and labels used for actual assembler output.  */
> > > !   init_sections_and_labels ();
> > >   
> > >     /* Traverse the DIE's and add sibling attributes to those DIE's that
> > >        have children.  */
> > > --- 30118,30124 ----
> > >     move_marked_base_types ();
> > >   
> > >     /* Initialize sections and labels used for actual assembler output.  */
> > > !   init_sections_and_labels (false);
> > >   
> > >     /* Traverse the DIE's and add sibling attributes to those DIE's that
> > >        have children.  */
> > > *************** dwarf2out_finish (const char *)
> > > *** 29772,29780 ****
> > >   		    debug_line_section_label);
> > >   
> > >     if (have_macinfo)
> > > !     add_AT_macptr (comp_unit_die (),
> > > ! 		   dwarf_version >= 5 ? DW_AT_macros
> > > ! 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
> > >   		   macinfo_section_label);
> > >   
> > >     if (dwarf_split_debug_info)
> > > --- 30213,30219 ----
> > >   		    debug_line_section_label);
> > >   
> > >     if (have_macinfo)
> > > !     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
> > >   		   macinfo_section_label);
> > >   
> > >     if (dwarf_split_debug_info)
> > > *************** dwarf2out_finish (const char *)
> > > *** 29979,29985 ****
> > >       {
> > >         switch_to_section (debug_macinfo_section);
> > >         ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> > > !       output_macinfo ();
> > >         dw2_asm_output_data (1, 0, "End compilation unit");
> > >       }
> > >   
> > > --- 30418,30425 ----
> > >       {
> > >         switch_to_section (debug_macinfo_section);
> > >         ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> > > !       output_macinfo (!dwarf_split_debug_info ? debug_line_section_label
> > > ! 		      : debug_skeleton_line_section_label, false);
> > >         dw2_asm_output_data (1, 0, "End compilation unit");
> > >       }
> > >   
> > > *************** note_variable_value_in_expr (dw_die_ref
> > > *** 30200,30205 ****
> > > --- 30640,30659 ----
> > >         {
> > >   	tree decl = loc->dw_loc_oprnd1.v.val_decl_ref;
> > >   	dw_die_ref ref = lookup_decl_die (decl);
> > > + 	if (! ref && flag_generate_lto)
> > > + 	  {
> > > + 	    /* ???  This is somewhat a hack because we do not create DIEs
> > > + 	       for variables not in BLOCK trees early but when generating
> > > + 	       early LTO output we need the dw_val_class_decl_ref to be
> > > + 	       fully resolved.  For fat LTO objects we'd also like to
> > > + 	       undo this after LTO dwarf output.  */
> > > + 	    gcc_assert (DECL_CONTEXT (decl));
> > > + 	    dw_die_ref ctx = lookup_decl_die (DECL_CONTEXT (decl));
> > > + 	    gcc_assert (ctx != NULL);
> > > + 	    gen_decl_die (decl, NULL_TREE, NULL, ctx);
> > > + 	    ref = lookup_decl_die (decl);
> > > + 	    gcc_assert (ref != NULL);
> > > + 	  }
> > >   	if (ref)
> > >   	  {
> > >   	    loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
> > > *************** dwarf2out_early_finish (const char *file
> > > *** 30410,30415 ****
> > > --- 30864,30982 ----
> > >   
> > >     /* The early debug phase is now finished.  */
> > >     early_dwarf_finished = true;
> > > + 
> > > +   /* Do not generate DWARF assembler now when not producing LTO bytecode.  */
> > > +   if (!flag_generate_lto)
> > > +     return;
> > > + 
> > > +   /* Now as we are going to output for LTO initialize sections and labels
> > > +      to the LTO variants.  We don't need a random-seed postfix as other
> > > +      LTO sections as linking the LTO debug sections into one in a partial
> > > +      link is fine.  */
> > > +   init_sections_and_labels (true);
> > > + 
> > > +   /* The output below is modeled after dwarf2out_finish with all
> > > +      location related output removed and some LTO specific changes.
> > > +      Some refactoring might make both smaller and easier to match up.  */
> > > + 
> > > +   /* Traverse the DIE's and add add sibling attributes to those DIE's
> > > +      that have children.  */
> > > +   add_sibling_attributes (comp_unit_die ());
> > > +   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
> > > +     add_sibling_attributes (node->die);
> > > +   for (comdat_type_node *ctnode = comdat_type_list;
> > > +        ctnode != NULL; ctnode = ctnode->next)
> > > +     add_sibling_attributes (ctnode->root_die);
> > > + 
> > > +   if (have_macinfo)
> > > +     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
> > > + 		   macinfo_section_label);
> > > + 
> > > +   save_macinfo_strings ();
> > > + 
> > > +   /* Output all of the compilation units.  We put the main one last so that
> > > +      the offsets are available to output_pubnames.  */
> > > +   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
> > > +     output_comp_unit (node->die, 0, NULL);
> > > + 
> > > +   hash_table<comdat_type_hasher> comdat_type_table (100);
> > > +   for (comdat_type_node *ctnode = comdat_type_list;
> > > +        ctnode != NULL; ctnode = ctnode->next)
> > > +     {
> > > +       comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT);
> > > + 
> > > +       /* Don't output duplicate types.  */
> > > +       if (*slot != HTAB_EMPTY_ENTRY)
> > > +         continue;
> > > + 
> > > +       /* Add a pointer to the line table for the main compilation unit
> > > +          so that the debugger can make sense of DW_AT_decl_file
> > > +          attributes.  */
> > > +       if (debug_info_level >= DINFO_LEVEL_TERSE)
> > > +         add_AT_lineptr (ctnode->root_die, DW_AT_stmt_list,
> > > +                         (!dwarf_split_debug_info
> > > +                          ? debug_line_section_label
> > > +                          : debug_skeleton_line_section_label));
> > > + 
> > > +       output_comdat_type_unit (ctnode);
> > > +       *slot = ctnode;
> > > +     }
> > > + 
> > > +   /* The AT_pubnames attribute needs to go in all skeleton dies, including
> > > +      both the main_cu and all skeleton TUs.  Making this call unconditional
> > > +      would end up either adding a second copy of the AT_pubnames attribute, or
> > > +      requiring a special case in add_top_level_skeleton_die_attrs.  */
> > > +   if (!dwarf_split_debug_info)
> > > +     add_AT_pubnames (comp_unit_die ());
> > > + 
> > > +   /* Stick a unique symbol to the main debuginfo section.  */
> > > +   compute_section_prefix_1 (comp_unit_die (), false);
> > > + 
> > > +   /* Output the main compilation unit.  We always need it if only for
> > > +      the CU symbol.  */
> > > +   output_comp_unit (comp_unit_die (), true, NULL);
> > > + 
> > > +   /* Output the abbreviation table.  */
> > > +   if (vec_safe_length (abbrev_die_table) != 1)
> > > +     {
> > > +       switch_to_section (debug_abbrev_section);
> > > +       ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
> > > +       output_abbrev_section ();
> > > +     }
> > > + 
> > > +   /* Have to end the macro section.  */
> > > +   if (have_macinfo)
> > > +     {
> > > +       /* We have to save macinfo state if we need to output it again
> > > + 	 for the FAT part of the object.  */
> > > +       vec<macinfo_entry, va_gc> *saved_macinfo_table = macinfo_table;
> > > +       if (flag_fat_lto_objects)
> > > + 	macinfo_table = macinfo_table->copy ();
> > > + 
> > > +       switch_to_section (debug_macinfo_section);
> > > +       ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> > > +       output_macinfo (debug_skeleton_line_section_label, true);
> > > +       dw2_asm_output_data (1, 0, "End compilation unit");
> > > + 
> > > +       /* Emit a skeleton debug_line section.  */
> > > +       switch_to_section (debug_skeleton_line_section);
> > > +       ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_line_section_label);
> > > +       output_line_info (true);
> > > + 
> > > +       if (flag_fat_lto_objects)
> > > + 	{
> > > + 	  vec_free (macinfo_table);
> > > + 	  macinfo_table = saved_macinfo_table;
> > > + 	}
> > > +     }
> > > + 
> > > + 
> > > +   /* If we emitted any indirect strings, output the string table too.  */
> > > +   if (debug_str_hash || skeleton_debug_str_hash)
> > > +     output_indirect_strings ();
> > > + 
> > > +   /* Switch back to the text section.  */
> > > +   switch_to_section (text_section);
> > >   }
> > >   
> > >   /* Reset all state within dwarf2out.c so that we can rerun the compiler
> > > Index: early-lto-debug/gcc/debug.h
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/debug.h	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/debug.h	2017-05-16 13:10:49.774239353 +0200
> > > *************** struct gcc_debug_hooks
> > > *** 147,152 ****
> > > --- 147,160 ----
> > >     void (* imported_module_or_decl) (tree decl, tree name,
> > >   				    tree context, bool child);
> > >   
> > > +   /* Return true if a DIE for the tree is available and return a symbol
> > > +      and offset that can be used to refer to it externally.  */
> > > +   bool (* die_ref_for_decl) (tree, const char **, unsigned HOST_WIDE_INT *);
> > > + 
> > > +   /* Early debug information for the tree is available at symbol plus
> > > +      offset externally.  */
> > > +   void (* register_external_die) (tree, const char *, unsigned HOST_WIDE_INT);
> > > + 
> > >     /* DECL is an inline function, whose body is present, but which is
> > >        not being output at this point.  */
> > >     void (* deferred_inline_function) (tree decl);
> > > *************** extern void debug_nothing_tree_tree_tree
> > > *** 210,215 ****
> > > --- 218,227 ----
> > >   extern bool debug_true_const_tree (const_tree);
> > >   extern void debug_nothing_rtx_insn (rtx_insn *);
> > >   extern void debug_nothing_rtx_code_label (rtx_code_label *);
> > > + extern bool debug_false_tree_charstarstar_uhwistar (tree, const char **,
> > > + 						    unsigned HOST_WIDE_INT *);
> > > + extern void debug_nothing_tree_charstar_uhwi (tree, const char *,
> > > + 					      unsigned HOST_WIDE_INT);
> > >   
> > >   /* Hooks for various debug formats.  */
> > >   extern const struct gcc_debug_hooks do_nothing_debug_hooks;
> > > Index: early-lto-debug/gcc/debug.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/debug.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/debug.c	2017-05-16 13:10:49.774239353 +0200
> > > *************** const struct gcc_debug_hooks do_nothing_
> > > *** 48,53 ****
> > > --- 48,55 ----
> > >     debug_nothing_tree,	         	 /* late_global_decl */
> > >     debug_nothing_tree_int,		 /* type_decl */
> > >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> > >     debug_nothing_tree,		         /* deferred_inline_function */
> > >     debug_nothing_tree,		         /* outlining_inline_function */
> > >     debug_nothing_rtx_code_label,	         /* label */
> > > *************** debug_nothing_tree_int (tree decl ATTRIB
> > > *** 146,148 ****
> > > --- 148,163 ----
> > >   			int local ATTRIBUTE_UNUSED)
> > >   {
> > >   }
> > > + 
> > > + bool
> > > + debug_false_tree_charstarstar_uhwistar (tree, const char **,
> > > + 					unsigned HOST_WIDE_INT *)
> > > + {
> > > +   return false;
> > > + }
> > > + 
> > > + void
> > > + debug_nothing_tree_charstar_uhwi (tree, const char *,
> > > + 				  unsigned HOST_WIDE_INT)
> > > + {
> > > + }
> > > Index: early-lto-debug/gcc/dbxout.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/dbxout.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/dbxout.c	2017-05-16 13:10:49.778239419 +0200
> > > *************** const struct gcc_debug_hooks dbx_debug_h
> > > *** 372,377 ****
> > > --- 372,379 ----
> > >     dbxout_late_global_decl,		 /* late_global_decl */
> > >     dbxout_type_decl,			 /* type_decl */
> > >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> > >     debug_nothing_tree,		         /* deferred_inline_function */
> > >     debug_nothing_tree,		         /* outlining_inline_function */
> > >     debug_nothing_rtx_code_label,	         /* label */
> > > *************** const struct gcc_debug_hooks xcoff_debug
> > > *** 412,417 ****
> > > --- 414,421 ----
> > >     dbxout_late_global_decl,		 /* late_global_decl */
> > >     dbxout_type_decl,			 /* type_decl */
> > >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > +   debug_nothing_tree_charstar_uhwi,      /* register_external_die */
> > >     debug_nothing_tree,		         /* deferred_inline_function */
> > >     debug_nothing_tree,		         /* outlining_inline_function */
> > >     debug_nothing_rtx_code_label,	         /* label */
> > > Index: early-lto-debug/gcc/sdbout.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/sdbout.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/sdbout.c	2017-05-16 13:10:49.778239419 +0200
> > > *************** const struct gcc_debug_hooks sdb_debug_h
> > > *** 302,307 ****
> > > --- 302,309 ----
> > >     sdbout_late_global_decl,		 /* late_global_decl */
> > >     sdbout_symbol,			 /* type_decl */
> > >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> > >     debug_nothing_tree,		         /* deferred_inline_function */
> > >     debug_nothing_tree,		         /* outlining_inline_function */
> > >     sdbout_label,			         /* label */
> > > Index: early-lto-debug/gcc/lto/lto.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/lto/lto.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/lto/lto.c	2017-05-16 13:10:49.778239419 +0200
> > > *************** unify_scc (struct data_in *data_in, unsi
> > > *** 1632,1637 ****
> > > --- 1632,1640 ----
> > >   	      free_node (scc->entries[i]);
> > >   	    }
> > >   
> > > + 	  /* Drop DIE references.  */
> > > + 	  dref_queue.truncate (0);
> > > + 
> > >   	  break;
> > >   	}
> > >   
> > > *************** lto_read_decls (struct lto_file_decl_dat
> > > *** 1707,1714 ****
> > >   						     from);
> > >   	  if (len == 1
> > >   	      && (TREE_CODE (first) == IDENTIFIER_NODE
> > > ! 		  || TREE_CODE (first) == INTEGER_CST
> > > ! 		  || TREE_CODE (first) == TRANSLATION_UNIT_DECL))
> > >   	    continue;
> > >   
> > >   	  /* Try to unify the SCC with already existing ones.  */
> > > --- 1710,1716 ----
> > >   						     from);
> > >   	  if (len == 1
> > >   	      && (TREE_CODE (first) == IDENTIFIER_NODE
> > > ! 		  || TREE_CODE (first) == INTEGER_CST))
> > >   	    continue;
> > >   
> > >   	  /* Try to unify the SCC with already existing ones.  */
> > > *************** lto_read_decls (struct lto_file_decl_dat
> > > *** 1747,1762 ****
> > >   	      if (TREE_CODE (t) == INTEGER_CST
> > >   		  && !TREE_OVERFLOW (t))
> > >   		cache_integer_cst (t);
> > > - 	      /* Register TYPE_DECLs with the debuginfo machinery.  */
> > > - 	      if (!flag_wpa
> > > - 		  && TREE_CODE (t) == TYPE_DECL)
> > > - 		{
> > > - 		  /* Dwarf2out needs location information.
> > > - 		     TODO: Moving this out of the streamer loop may noticealy
> > > - 		     improve ltrans linemap memory use.  */
> > > - 		  data_in->location_cache.apply_location_cache ();
> > > - 		  debug_hooks->type_decl (t, !DECL_FILE_SCOPE_P (t));
> > > - 		}
> > >   	      if (!flag_ltrans)
> > >   		{
> > >   		  /* Register variables and functions with the
> > > --- 1749,1754 ----
> > > *************** lto_read_decls (struct lto_file_decl_dat
> > > *** 1772,1777 ****
> > > --- 1764,1777 ----
> > >   		    vec_safe_push (tree_with_vars, t);
> > >   		}
> > >   	    }
> > > + 
> > > + 	  /* Register DECLs with the debuginfo machinery.  */
> > > + 	  while (!dref_queue.is_empty ())
> > > + 	    {
> > > + 	      dref_entry e = dref_queue.pop ();
> > > + 	      debug_hooks->register_external_die (e.decl, e.sym, e.off);
> > > + 	    }
> > > + 
> > >   	  if (seen_type)
> > >   	    num_type_scc_trees += len;
> > >   	}
> > > *************** lto_section_with_id (const char *name, u
> > > *** 1951,1957 ****
> > >     if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
> > >       return 0;
> > >     s = strrchr (name, '.');
> > > !   return s && sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
> > >   }
> > >   
> > >   /* Create file_data of each sub file id */
> > > --- 1951,1962 ----
> > >     if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
> > >       return 0;
> > >     s = strrchr (name, '.');
> > > !   if (!s)
> > > !     return 0;
> > > !   /* If the section is not suffixed with an ID return.  */
> > > !   if ((size_t)(s - name) == strlen (section_name_prefix))
> > > !     return 0;
> > > !   return sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
> > >   }
> > >   
> > >   /* Create file_data of each sub file id */
> > > Index: early-lto-debug/gcc/lto-streamer-in.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/lto-streamer-in.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/lto-streamer-in.c	2017-05-16 13:10:49.858240736 +0200
> > > *************** along with GCC; see the file COPYING3.
> > > *** 41,46 ****
> > > --- 41,47 ----
> > >   #include "except.h"
> > >   #include "cgraph.h"
> > >   #include "cfgloop.h"
> > > + #include "debug.h"
> > >   
> > >   
> > >   struct freeing_string_slot_hasher : string_slot_hasher
> > > *************** input_function (tree fn_decl, struct dat
> > > *** 1038,1043 ****
> > > --- 1039,1054 ----
> > >     DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in);
> > >     DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in);
> > >   
> > > +   /* Read debug args if available.  */
> > > +   unsigned n_debugargs = streamer_read_uhwi (ib);
> > > +   if (n_debugargs)
> > > +     {
> > > +       vec<tree, va_gc> **debugargs = decl_debug_args_insert (fn_decl);
> > > +       vec_safe_grow (*debugargs, n_debugargs);
> > > +       for (unsigned i = 0; i < n_debugargs; ++i)
> > > + 	(**debugargs)[i] = stream_read_tree (ib, data_in);
> > > +     }
> > > + 
> > >     /* Read the tree of lexical scopes for the function.  */
> > >     DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
> > >     unsigned block_leaf_count = streamer_read_uhwi (ib);
> > > *************** lto_input_variable_constructor (struct l
> > > *** 1318,1323 ****
> > > --- 1329,1338 ----
> > >   }
> > >   
> > >   
> > > + /* Queue of acummulated decl -> DIE mappings.  Similar to locations those
> > > +    are only applied to prevailing tree nodes during tree merging.  */
> > > + vec<dref_entry> dref_queue;
> > > + 
> > >   /* Read the physical representation of a tree node EXPR from
> > >      input block IB using the per-file context in DATA_IN.  */
> > >   
> > > *************** lto_read_tree_1 (struct lto_input_block
> > > *** 1337,1342 ****
> > > --- 1352,1374 ----
> > >         && TREE_CODE (expr) != FUNCTION_DECL
> > >         && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
> > >       DECL_INITIAL (expr) = stream_read_tree (ib, data_in);
> > > + 
> > > +   /* Stream references to early generated DIEs.  Keep in sync with the
> > > +      trees handled in dwarf2out_register_external_die.  */
> > > +   if ((DECL_P (expr)
> > > +        && TREE_CODE (expr) != FIELD_DECL
> > > +        && TREE_CODE (expr) != DEBUG_EXPR_DECL
> > > +        && TREE_CODE (expr) != TYPE_DECL)
> > > +       || TREE_CODE (expr) == BLOCK)
> > > +     {
> > > +       const char *str = streamer_read_string (data_in, ib);
> > > +       if (str)
> > > + 	{
> > > + 	  unsigned HOST_WIDE_INT off = streamer_read_uhwi (ib);
> > > + 	  dref_entry e = { expr, str, off };
> > > + 	  dref_queue.safe_push (e);
> > > + 	}
> > > +     }
> > >   }
> > >   
> > >   /* Read the physical representation of a tree node with tag TAG from
> > > *************** lto_input_tree (struct lto_input_block *
> > > *** 1482,1487 ****
> > > --- 1514,1526 ----
> > >       {
> > >         unsigned len, entry_len;
> > >         lto_input_scc (ib, data_in, &len, &entry_len);
> > > + 
> > > +       /* Register DECLs with the debuginfo machinery.  */
> > > +       while (!dref_queue.is_empty ())
> > > + 	{
> > > + 	  dref_entry e = dref_queue.pop ();
> > > + 	  debug_hooks->register_external_die (e.decl, e.sym, e.off);
> > > + 	}
> > >       }
> > >     return lto_input_tree_1 (ib, data_in, tag, 0);
> > >   }
> > > Index: early-lto-debug/gcc/lto-streamer-out.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/lto-streamer-out.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/lto-streamer-out.c	2017-05-16 13:10:49.858240736 +0200
> > > *************** along with GCC; see the file COPYING3.
> > > *** 40,45 ****
> > > --- 40,46 ----
> > >   #include "cfgloop.h"
> > >   #include "builtins.h"
> > >   #include "gomp-constants.h"
> > > + #include "debug.h"
> > >   
> > >   
> > >   static void lto_write_tree (struct output_block*, tree, bool);
> > > *************** lto_write_tree_1 (struct output_block *o
> > > *** 406,411 ****
> > > --- 407,432 ----
> > >   			 (ob->decl_state->symtab_node_encoder, expr);
> > >         stream_write_tree (ob, initial, ref_p);
> > >       }
> > > + 
> > > +   /* Stream references to early generated DIEs.  Keep in sync with the
> > > +      trees handled in dwarf2out_die_ref_for_decl.  */
> > > +   if ((DECL_P (expr)
> > > +        && TREE_CODE (expr) != FIELD_DECL
> > > +        && TREE_CODE (expr) != DEBUG_EXPR_DECL
> > > +        && TREE_CODE (expr) != TYPE_DECL)
> > > +       || TREE_CODE (expr) == BLOCK)
> > > +     {
> > > +       const char *sym;
> > > +       unsigned HOST_WIDE_INT off;
> > > +       if (debug_info_level > DINFO_LEVEL_NONE
> > > + 	  && debug_hooks->die_ref_for_decl (expr, &sym, &off))
> > > + 	{
> > > + 	  streamer_write_string (ob, ob->main_stream, sym, true);
> > > + 	  streamer_write_uhwi (ob, off);
> > > + 	}
> > > +       else
> > > + 	streamer_write_string (ob, ob->main_stream, NULL, true);
> > > +     }
> > >   }
> > >   
> > >   /* Write a physical representation of tree node EXPR to output block
> > > *************** DFS::DFS_write_tree_body (struct output_
> > > *** 745,751 ****
> > >   	;
> > >         else
> > >   	DFS_follow_tree_edge (DECL_NAME (expr));
> > > !       DFS_follow_tree_edge (DECL_CONTEXT (expr));
> > >       }
> > >   
> > >     if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> > > --- 766,776 ----
> > >   	;
> > >         else
> > >   	DFS_follow_tree_edge (DECL_NAME (expr));
> > > !       if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
> > > ! 	  && ! DECL_CONTEXT (expr))
> > > ! 	DFS_follow_tree_edge ((*all_translation_units)[0]);
> > > !       else
> > > ! 	DFS_follow_tree_edge (DECL_CONTEXT (expr));
> > >       }
> > >   
> > >     if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> > > *************** DFS::DFS_write_tree_body (struct output_
> > > *** 765,770 ****
> > > --- 790,796 ----
> > >   	 declarations which should be eliminated by decl merging. Be sure none
> > >   	 leaks to this point.  */
> > >         gcc_assert (DECL_ABSTRACT_ORIGIN (expr) != error_mark_node);
> > > +       DFS_follow_tree_edge (DECL_ABSTRACT_ORIGIN (expr));
> > >   
> > >         if ((VAR_P (expr)
> > >   	   || TREE_CODE (expr) == PARM_DECL)
> > > *************** output_function (struct cgraph_node *nod
> > > *** 2061,2066 ****
> > > --- 2087,2103 ----
> > >     stream_write_tree (ob, DECL_RESULT (function), true);
> > >     streamer_write_chain (ob, DECL_ARGUMENTS (function), true);
> > >   
> > > +   /* Output debug args if available. */
> > > +   vec<tree, va_gc> **debugargs = decl_debug_args_lookup (function);
> > > +   if (! debugargs)
> > > +     streamer_write_uhwi (ob, 0);
> > > +   else
> > > +     {
> > > +       streamer_write_uhwi (ob, (*debugargs)->length ());
> > > +       for (unsigned i = 0; i < (*debugargs)->length (); ++i)
> > > + 	stream_write_tree (ob, (**debugargs)[i], true);
> > > +     }
> > > + 
> > >     /* Output DECL_INITIAL for the function, which contains the tree of
> > >        lexical scopes.  */
> > >     stream_write_tree (ob, DECL_INITIAL (function), true);
> > > Index: early-lto-debug/gcc/lto-streamer.h
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/lto-streamer.h	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/lto-streamer.h	2017-05-16 13:10:49.858240736 +0200
> > > *************** DEFINE_DECL_STREAM_FUNCS (TYPE_DECL, typ
> > > *** 1212,1215 ****
> > > --- 1212,1225 ----
> > >   DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl)
> > >   DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl)
> > >   
> > > + /* Entry for the delayed registering of decl -> DIE references.  */
> > > + struct dref_entry {
> > > +     tree decl;
> > > +     const char *sym;
> > > +     unsigned HOST_WIDE_INT off;
> > > + };
> > > + 
> > > + extern vec<dref_entry> dref_queue;
> > > + 
> > > + 
> > >   #endif /* GCC_LTO_STREAMER_H  */
> > > Index: early-lto-debug/gcc/lto-wrapper.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/lto-wrapper.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/lto-wrapper.c	2017-05-16 13:10:49.858240736 +0200
> > > *************** static char **output_names;
> > > *** 70,75 ****
> > > --- 70,76 ----
> > >   static char **offload_names;
> > >   static char *offload_objects_file_name;
> > >   static char *makefile;
> > > + static char *debug_obj;
> > >   
> > >   const char tool_name[] = "lto-wrapper";
> > >   
> > > *************** tool_cleanup (bool)
> > > *** 88,93 ****
> > > --- 89,96 ----
> > >       maybe_unlink (offload_objects_file_name);
> > >     if (makefile)
> > >       maybe_unlink (makefile);
> > > +   if (debug_obj)
> > > +     maybe_unlink (debug_obj);
> > >     for (i = 0; i < nr; ++i)
> > >       {
> > >         maybe_unlink (input_names[i]);
> > > *************** find_and_merge_options (int fd, off_t fi
> > > *** 938,943 ****
> > > --- 941,1007 ----
> > >     return true;
> > >   }
> > >   
> > > + /* Copy early debug info sections from INFILE to a new file whose name
> > > +    is returned.  Return NULL on error.  */
> > > + 
> > > + const char *
> > > + debug_objcopy (const char *infile)
> > > + {
> > > +   const char *outfile;
> > > +   const char *errmsg;
> > > +   int err;
> > > + 
> > > +   const char *p;
> > > +   off_t inoff = 0;
> > > +   long loffset;
> > > +   int consumed;
> > > +   if ((p = strrchr (infile, '@'))
> > > +       && p != infile
> > > +       && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
> > > +       && strlen (p) == (unsigned int) consumed)
> > > +     {
> > > +       char *fname = xstrdup (infile);
> > > +       fname[p - infile] = '\0';
> > > +       infile = fname;
> > > +       inoff = (off_t) loffset;
> > > +     }
> > > +   int infd = open (infile, O_RDONLY);
> > > +   if (infd == -1)
> > > +     return NULL;
> > > +   simple_object_read *inobj = simple_object_start_read (infd, inoff,
> > > + 							"__GNU_LTO",
> > > + 							&errmsg, &err);
> > > +   if (!inobj)
> > > +     return NULL;
> > > + 
> > > +   off_t off, len;
> > > +   if (simple_object_find_section (inobj, ".gnu.debuglto_.debug_info",
> > > + 				  &off, &len, &errmsg, &err) != 1)
> > > +     {
> > > +       if (errmsg)
> > > + 	fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
> > > + 
> > > +       simple_object_release_read (inobj);
> > > +       close (infd);
> > > +       return NULL;
> > > +     }
> > > + 
> > > +   outfile = make_temp_file ("debugobjtem");
> > > +   errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err);
> > > +   if (errmsg)
> > > +     {
> > > +       unlink_if_ordinary (outfile);
> > > +       fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
> > > +     }
> > > + 
> > > +   simple_object_release_read (inobj);
> > > +   close (infd);
> > > + 
> > > +   return outfile;
> > > + }
> > > + 
> > > + 
> > > + 
> > >   /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
> > >   
> > >   static void
> > > *************** run_gcc (unsigned argc, char *argv[])
> > > *** 962,969 ****
> > >     int new_head_argc;
> > >     bool have_lto = false;
> > >     bool have_offload = false;
> > > !   unsigned lto_argc = 0;
> > > !   char **lto_argv;
> > >   
> > >     /* Get the driver and options.  */
> > >     collect_gcc = getenv ("COLLECT_GCC");
> > > --- 1026,1035 ----
> > >     int new_head_argc;
> > >     bool have_lto = false;
> > >     bool have_offload = false;
> > > !   unsigned lto_argc = 0, ltoobj_argc = 0;
> > > !   char **lto_argv, **ltoobj_argv;
> > > !   bool skip_debug = false;
> > > !   unsigned n_debugobj;
> > >   
> > >     /* Get the driver and options.  */
> > >     collect_gcc = getenv ("COLLECT_GCC");
> > > *************** run_gcc (unsigned argc, char *argv[])
> > > *** 982,987 ****
> > > --- 1048,1054 ----
> > >     /* Allocate array for input object files with LTO IL,
> > >        and for possible preceding arguments.  */
> > >     lto_argv = XNEWVEC (char *, argc);
> > > +   ltoobj_argv = XNEWVEC (char *, argc);
> > >   
> > >     /* Look at saved options in the IL files.  */
> > >     for (i = 1; i < argc; ++i)
> > > *************** run_gcc (unsigned argc, char *argv[])
> > > *** 1024,1030 ****
> > >   				  collect_gcc))
> > >   	{
> > >   	  have_lto = true;
> > > ! 	  lto_argv[lto_argc++] = argv[i];
> > >   	}
> > >         close (fd);
> > >       }
> > > --- 1091,1097 ----
> > >   				  collect_gcc))
> > >   	{
> > >   	  have_lto = true;
> > > ! 	  ltoobj_argv[ltoobj_argc++] = argv[i];
> > >   	}
> > >         close (fd);
> > >       }
> > > *************** run_gcc (unsigned argc, char *argv[])
> > > *** 1085,1090 ****
> > > --- 1152,1168 ----
> > >   	}
> > >       }
> > >   
> > > +   /* Output lto-wrapper invocation command.  */
> > > +   if (verbose)
> > > +     {
> > > +       for (i = 0; i < argc; ++i)
> > > + 	{
> > > + 	  fputs (argv[i], stderr);
> > > + 	  fputc (' ', stderr);
> > > + 	}
> > > +       fputc ('\n', stderr);
> > > +     }
> > > + 
> > >     if (no_partition)
> > >       {
> > >         lto_mode = LTO_MODE_LTO;
> > > *************** cont1:
> > > *** 1274,1291 ****
> > >           obstack_ptr_grow (&argv_obstack, "-fwpa");
> > >       }
> > >   
> > > !   /* Append the input objects and possible preceding arguments.  */
> > >     for (i = 0; i < lto_argc; ++i)
> > >       obstack_ptr_grow (&argv_obstack, lto_argv[i]);
> > >     obstack_ptr_grow (&argv_obstack, NULL);
> > >   
> > >     new_argv = XOBFINISH (&argv_obstack, const char **);
> > >     argv_ptr = &new_argv[new_head_argc];
> > >     fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
> > >   
> > >     if (lto_mode == LTO_MODE_LTO)
> > >       {
> > >         printf ("%s\n", flto_out);
> > >         free (flto_out);
> > >         flto_out = NULL;
> > >       }
> > > --- 1352,1456 ----
> > >           obstack_ptr_grow (&argv_obstack, "-fwpa");
> > >       }
> > >   
> > > !   /* Append input arguments.  */
> > >     for (i = 0; i < lto_argc; ++i)
> > >       obstack_ptr_grow (&argv_obstack, lto_argv[i]);
> > > +   /* Append the input objects.  */
> > > +   for (i = 0; i < ltoobj_argc; ++i)
> > > +     obstack_ptr_grow (&argv_obstack, ltoobj_argv[i]);
> > >     obstack_ptr_grow (&argv_obstack, NULL);
> > >   
> > >     new_argv = XOBFINISH (&argv_obstack, const char **);
> > >     argv_ptr = &new_argv[new_head_argc];
> > >     fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
> > >   
> > > +   /* Handle early generated debug information.  At compile-time
> > > +      we output early DWARF debug info into .gnu.debuglto_ prefixed
> > > +      sections.  LTRANS object DWARF debug info refers to that.
> > > +      So we need to transfer the .gnu.debuglto_ sections to the final
> > > +      link.  Ideally the linker plugin interface would allow us to
> > > +      not claim those sections and instruct the linker to keep
> > > +      them, renaming them in the process.  For now we extract and
> > > +      rename those sections via a simple-object interface to produce
> > > +      regular objects containing only the early debug info.  We
> > > +      then partially link those to a single early debug info object
> > > +      and pass that as additional output back to the linker plugin.  */
> > > + 
> > > +   /* Prepare the partial link to gather the compile-time generated
> > > +      debug-info into a single input for the final link.  */
> > > +   debug_obj = make_temp_file ("debugobj");
> > > +   obstack_ptr_grow (&argv_obstack, collect_gcc);
> > > +   for (i = 1; i < decoded_options_count; ++i)
> > > +     {
> > > +       /* Retain linker choice and -B.  */
> > > +       if (decoded_options[i].opt_index == OPT_B
> > > + 	  || decoded_options[i].opt_index == OPT_fuse_ld_bfd
> > > + 	  || decoded_options[i].opt_index == OPT_fuse_ld_gold)
> > > + 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
> > > +       /* Retain all target options, this preserves -m32 for example.  */
> > > +       if (cl_options[decoded_options[i].opt_index].flags & CL_TARGET)
> > > + 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
> > > +       /* Recognize -g0.  */
> > > +       if (decoded_options[i].opt_index == OPT_g
> > > + 	  && strcmp (decoded_options[i].arg, "0") == 0)
> > > + 	skip_debug = true;
> > > +     }
> > > +   obstack_ptr_grow (&argv_obstack, "-r");
> > > +   obstack_ptr_grow (&argv_obstack, "-nostdlib");
> > > +   obstack_ptr_grow (&argv_obstack, "-o");
> > > +   obstack_ptr_grow (&argv_obstack, debug_obj);
> > > + 
> > > +   /* Copy the early generated debug info from the objects to temporary
> > > +      files and append those to the partial link commandline.  */
> > > +   n_debugobj = 0;
> > > +   if (! skip_debug)
> > > +     for (i = 0; i < ltoobj_argc; ++i)
> > > +       {
> > > + 	const char *tem;
> > > + 	if ((tem = debug_objcopy (ltoobj_argv[i])))
> > > + 	  {
> > > + 	    obstack_ptr_grow (&argv_obstack, tem);
> > > + 	    n_debugobj++;
> > > + 	  }
> > > +       }
> > > + 
> > > +   /* Link them all into a single object.  Ideally this would reduce
> > > +      disk space usage mainly due to .debug_str merging but unfortunately
> > > +      GNU ld doesn't perform this with -r.  */
> > > +   if (n_debugobj)
> > > +     {
> > > +       obstack_ptr_grow (&argv_obstack, NULL);
> > > +       const char **debug_link_argv = XOBFINISH (&argv_obstack, const char **);
> > > +       fork_execute (debug_link_argv[0],
> > > + 		    CONST_CAST (char **, debug_link_argv), false);
> > > + 
> > > +       /* And dispose the temporaries.  */
> > > +       for (i = 0; debug_link_argv[i]; ++i)
> > > + 	;
> > > +       for (--i; i > 0; --i)
> > > + 	{
> > > + 	  if (strcmp (debug_link_argv[i], debug_obj) == 0)
> > > + 	    break;
> > > + 	  maybe_unlink (debug_link_argv[i]);
> > > + 	}
> > > +     }
> > > +   else
> > > +     {
> > > +       unlink_if_ordinary (debug_obj);
> > > +       free (debug_obj);
> > > +       debug_obj = NULL;
> > > +       skip_debug = true;
> > > +     }
> > > + 
> > >     if (lto_mode == LTO_MODE_LTO)
> > >       {
> > >         printf ("%s\n", flto_out);
> > > +       if (!skip_debug)
> > > + 	{
> > > + 	  printf ("%s\n", debug_obj);
> > > + 	  free (debug_obj);
> > > + 	  debug_obj = NULL;
> > > + 	}
> > >         free (flto_out);
> > >         flto_out = NULL;
> > >       }
> > > *************** cont:
> > > *** 1434,1439 ****
> > > --- 1599,1610 ----
> > >   	  for (i = 0; i < nr; ++i)
> > >   	    maybe_unlink (input_names[i]);
> > >   	}
> > > +       if (!skip_debug)
> > > + 	{
> > > + 	  printf ("%s\n", debug_obj);
> > > + 	  free (debug_obj);
> > > + 	  debug_obj = NULL;
> > > + 	}
> > >         for (i = 0; i < nr; ++i)
> > >   	{
> > >   	  fputs (output_names[i], stdout);
> > > Index: early-lto-debug/gcc/tree-streamer-in.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/tree-streamer-in.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/tree-streamer-in.c	2017-05-16 13:10:49.862240801 +0200
> > > *************** lto_input_ts_decl_common_tree_pointers (
> > > *** 688,697 ****
> > >     DECL_SIZE (expr) = stream_read_tree (ib, data_in);
> > >     DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
> > >     DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
> > > ! 
> > > !   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
> > > !      for early inlining so drop it on the floor instead of ICEing in
> > > !      dwarf2out.c.  */
> > >   
> > >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> > >         && DECL_HAS_VALUE_EXPR_P (expr))
> > > --- 688,694 ----
> > >     DECL_SIZE (expr) = stream_read_tree (ib, data_in);
> > >     DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
> > >     DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
> > > !   DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
> > >   
> > >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> > >         && DECL_HAS_VALUE_EXPR_P (expr))
> > > Index: early-lto-debug/gcc/tree-streamer-out.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/tree-streamer-out.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/tree-streamer-out.c	2017-05-16 13:10:49.862240801 +0200
> > > *************** write_ts_decl_minimal_tree_pointers (str
> > > *** 566,572 ****
> > >       stream_write_tree (ob, NULL_TREE, ref_p);
> > >     else
> > >       stream_write_tree (ob, DECL_NAME (expr), ref_p);
> > > !   stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
> > >   }
> > >   
> > >   
> > > --- 566,576 ----
> > >       stream_write_tree (ob, NULL_TREE, ref_p);
> > >     else
> > >       stream_write_tree (ob, DECL_NAME (expr), ref_p);
> > > !   if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
> > > !       && ! DECL_CONTEXT (expr))
> > > !     stream_write_tree (ob, (*all_translation_units)[0], ref_p);
> > > !   else
> > > !     stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
> > >   }
> > >   
> > >   
> > > *************** write_ts_decl_common_tree_pointers (stru
> > > *** 585,594 ****
> > >        special handling in LTO, it must be handled by streamer hooks.  */
> > >   
> > >     stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
> > > ! 
> > > !   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
> > > !      for early inlining so drop it on the floor instead of ICEing in
> > > !      dwarf2out.c.  */
> > >   
> > >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> > >         && DECL_HAS_VALUE_EXPR_P (expr))
> > > --- 589,595 ----
> > >        special handling in LTO, it must be handled by streamer hooks.  */
> > >   
> > >     stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
> > > !   stream_write_tree (ob, DECL_ABSTRACT_ORIGIN (expr), ref_p);
> > >   
> > >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> > >         && DECL_HAS_VALUE_EXPR_P (expr))
> > > Index: early-lto-debug/gcc/config/darwin.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/config/darwin.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/config/darwin.c	2017-05-16 13:10:49.862240801 +0200
> > > *************** darwin_asm_lto_end (void)
> > > *** 1959,1965 ****
> > >   }
> > >   
> > >   static void
> > > ! darwin_asm_dwarf_section (const char *name, unsigned int flags, tree decl);
> > >   
> > >   /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
> > >   
> > > --- 1959,1966 ----
> > >   }
> > >   
> > >   static void
> > > ! darwin_asm_dwarf_section (const char *name, unsigned int flags,
> > > ! 			  tree decl, bool is_for_lto);
> > >   
> > >   /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
> > >   
> > > *************** darwin_asm_named_section (const char *na
> > > *** 2001,2007 ****
> > >         vec_safe_push (lto_section_names, e);
> > >      }
> > >     else if (strncmp (name, "__DWARF,", 8) == 0)
> > > !     darwin_asm_dwarf_section (name, flags, decl);
> > >     else
> > >       fprintf (asm_out_file, "\t.section %s\n", name);
> > >   }
> > > --- 2002,2010 ----
> > >         vec_safe_push (lto_section_names, e);
> > >      }
> > >     else if (strncmp (name, "__DWARF,", 8) == 0)
> > > !     darwin_asm_dwarf_section (name, flags, decl, false);
> > > !   else if (strncmp (name, "__GNU_DWARF_LTO,", 16) == 0)
> > > !     darwin_asm_dwarf_section (name, flags, decl, true);
> > >     else
> > >       fprintf (asm_out_file, "\t.section %s\n", name);
> > >   }
> > > *************** static GTY (()) vec<dwarf_sect_used_entr
> > > *** 2783,2801 ****
> > >   
> > >   static void
> > >   darwin_asm_dwarf_section (const char *name, unsigned int flags,
> > > ! 			  tree ARG_UNUSED (decl))
> > >   {
> > >     unsigned i;
> > > !   int namelen;
> > > !   const char * sname;
> > >     dwarf_sect_used_entry *ref;
> > >     bool found = false;
> > > !   gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
> > > ! 		    == (SECTION_DEBUG | SECTION_NAMED));
> > > !   /* We know that the name starts with __DWARF,  */
> > > !   sname = name + 8;
> > > !   namelen = strchr (sname, ',') - sname;
> > > !   gcc_assert (namelen);
> > >     if (dwarf_sect_names_table == NULL)
> > >       vec_alloc (dwarf_sect_names_table, 16);
> > >     else
> > > --- 2786,2822 ----
> > >   
> > >   static void
> > >   darwin_asm_dwarf_section (const char *name, unsigned int flags,
> > > ! 			  tree ARG_UNUSED (decl), bool is_for_lto)
> > >   {
> > >     unsigned i;
> > > !   int namelen, extra = 0;
> > > !   const char *sect, *lto_add = "";
> > > !   char sname[64];
> > >     dwarf_sect_used_entry *ref;
> > >     bool found = false;
> > > ! 
> > > !   gcc_checking_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
> > > ! 			== (SECTION_DEBUG | SECTION_NAMED));
> > > ! 
> > > !   /* We know that the name starts with __DWARF, or __GNU_DAWRF_LTO  */
> > > !   sect = strchr (name, ',') + 1;
> > > !   namelen = strchr (sect, ',') - sect;
> > > !   gcc_checking_assert (namelen);
> > > ! 
> > > !   /* The section switch is output as written...  */
> > > !   fprintf (asm_out_file, "\t.section %s\n", name);
> > > ! 
> > > !   /* ... but the string we keep to make section start labels needs
> > > !      adjustment for lto cases.  */
> > > !   if (is_for_lto)
> > > !     {
> > > !       lto_add = "_lto";
> > > !       extra = 4;
> > > !     }
> > > ! 
> > > !   snprintf (sname, 64, "%.*s%.*s", namelen, sect, extra, lto_add);
> > > !   namelen += extra;
> > > ! 
> > >     if (dwarf_sect_names_table == NULL)
> > >       vec_alloc (dwarf_sect_names_table, 16);
> > >     else
> > > *************** darwin_asm_dwarf_section (const char *na
> > > *** 2813,2819 ****
> > >   	  }
> > >         }
> > >   
> > > -   fprintf (asm_out_file, "\t.section %s\n", name);
> > >     if (!found)
> > >       {
> > >         dwarf_sect_used_entry e;
> > > --- 2834,2839 ----
> > > *************** darwin_asm_output_dwarf_offset (FILE *fi
> > > *** 2866,2879 ****
> > >   				HOST_WIDE_INT offset, section *base)
> > >   {
> > >     char sname[64];
> > > !   int namelen;
> > >   
> > > !   gcc_assert (base->common.flags & SECTION_NAMED);
> > > !   gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
> > > !   gcc_assert (strchr (base->named.name + 8, ','));
> > > ! 
> > > !   namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
> > > !   sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
> > >     darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
> > >   }
> > >   
> > > --- 2886,2909 ----
> > >   				HOST_WIDE_INT offset, section *base)
> > >   {
> > >     char sname[64];
> > > !   int namelen, extra = 0;
> > > !   bool is_for_lto;
> > > !   const char *lto_add = "";
> > > ! 
> > > !   gcc_checking_assert (base->common.flags & SECTION_NAMED);
> > > !   is_for_lto = strncmp (base->named.name, "__GNU_DWARF_LTO,", 16) == 0;
> > > !   gcc_checking_assert (is_for_lto
> > > ! 		       || strncmp (base->named.name, "__DWARF,", 8) == 0);
> > > !   const char *name = strchr (base->named.name, ',') + 1;
> > > !   gcc_checking_assert (name);
> > >   
> > > !   namelen = strchr (name, ',') - (name);
> > > !   if (is_for_lto)
> > > !     {
> > > !       lto_add = "_lto";
> > > !       extra = 4;
> > > !     }
> > > !   snprintf (sname, 64, "*Lsection%.*s%.*s", namelen, name, extra, lto_add);
> > >     darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
> > >   }
> > >   
> > > Index: early-lto-debug/gcc/config/darwin.h
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/config/darwin.h	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/config/darwin.h	2017-05-16 13:10:49.866240867 +0200
> > > *************** extern GTY(()) int darwin_ms_struct;
> > > *** 445,451 ****
> > >   #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
> > >   #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
> > >   #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
> > > ! #define DEBUG_MACRO_SECTION    "__DWARF,__debug_macro,regular,debug"
> > >   
> > >   #define TARGET_WANT_DEBUG_PUB_SECTIONS true
> > >   
> > > --- 445,458 ----
> > >   #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
> > >   #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
> > >   #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
> > > ! #define DEBUG_MACRO_SECTION     "__DWARF,__debug_macro,regular,debug"
> > > ! 
> > > ! #define DEBUG_LTO_INFO_SECTION	  "__GNU_DWARF_LTO,__debug_info,regular,debug"
> > > ! #define DEBUG_LTO_ABBREV_SECTION  "__GNU_DWARF_LTO,__debug_abbrev,regular,debug"
> > > ! #define DEBUG_LTO_MACINFO_SECTION "__GNU_DWARF_LTO,__debug_macinfo,regular,debug"
> > > ! #define DEBUG_LTO_LINE_SECTION	  "__GNU_DWARF_LTO,__debug_line,regular,debug"
> > > ! #define DEBUG_LTO_STR_SECTION	  "__GNU_DWARF_LTO,__debug_str,regular,debug"
> > > ! #define DEBUG_LTO_MACRO_SECTION   "__GNU_DWARF_LTO,__debug_macro,regular,debug"
> > >   
> > >   #define TARGET_WANT_DEBUG_PUB_SECTIONS true
> > >   
> > > Index: early-lto-debug/gcc/vmsdbgout.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/vmsdbgout.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/vmsdbgout.c	2017-05-16 13:10:49.866240867 +0200
> > > *************** const struct gcc_debug_hooks vmsdbg_debu
> > > *** 198,203 ****
> > > --- 198,205 ----
> > >      vmsdbgout_late_global_decl,
> > >      vmsdbgout_type_decl,		  /* type_decl */
> > >      debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
> > > +    debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > +    debug_nothing_tree_charstar_uhwi, /* register_external_die */
> > >      debug_nothing_tree,		  /* deferred_inline_function */
> > >      vmsdbgout_abstract_function,
> > >      debug_nothing_rtx_code_label,  /* label */
> > > Index: early-lto-debug/gcc/tree.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/tree.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/tree.c	2017-05-16 13:10:49.870240933 +0200
> > > *************** free_lang_data (void)
> > > *** 5974,5979 ****
> > > --- 5974,5983 ----
> > >         || (!flag_generate_lto && !flag_generate_offload))
> > >       return 0;
> > >   
> > > +   /* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one.  */
> > > +   if (vec_safe_is_empty (all_translation_units))
> > > +     build_translation_unit_decl (NULL_TREE);
> > > + 
> > >     /* Allocate and assign alias sets to the standard integer types
> > >        while the slots are still in the way the frontends generated them.  */
> > >     for (i = 0; i < itk_none; ++i)
> > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-05-16 13:10:49.870240933 +0200
> > > *************** int main() {
> > > *** 23,28 ****
> > >   }
> > >   
> > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
> > >   /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
> > >   /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
> > > --- 23,28 ----
> > >   }
> > >   
> > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
> > >   /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
> > >   /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
> > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-05-16 13:10:49.870240933 +0200
> > > *************** int main(int argc, char **argv) {
> > > *** 24,31 ****
> > >   }
> > >   
> > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > --- 24,31 ----
> > >   }
> > >   
> > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-05-16 13:10:49.870240933 +0200
> > > *************** main ()
> > > *** 39,43 ****
> > >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > > --- 39,43 ----
> > >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-05-16 13:10:49.870240933 +0200
> > > *************** main ()
> > > *** 39,43 ****
> > >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > > --- 39,43 ----
> > >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-05-16 13:10:49.870240933 +0200
> > > *************** int main()
> > > *** 18,22 ****
> > >   
> > >   /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
> > >   /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > --- 18,22 ----
> > >   
> > >   /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
> > >   /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-05-16 13:10:49.874240999 +0200
> > > *************** int main() {
> > > *** 18,23 ****
> > >   }
> > >   
> > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
> > >   /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
> > > --- 18,23 ----
> > >   }
> > >   
> > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
> > >   /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
> > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-05-16 13:10:49.874240999 +0200
> > > *************** int main(int argc, char **argv) {
> > > *** 14,21 ****
> > >   
> > >   /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > --- 14,21 ----
> > >   
> > >   /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-05-16 13:10:49.874240999 +0200
> > > *************** int main() {
> > > *** 12,22 ****
> > >   /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
> > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > --- 12,22 ----
> > >   /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
> > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > >   /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > Index: early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-05-16 13:10:49.874240999 +0200
> > > *************** int main() {
> > > *** 38,44 ****
> > >   // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
> > >   // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
> > >   // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
> > > ! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" }
> > >   // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
> > >   // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
> > >   // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
> > > --- 38,44 ----
> > >   // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
> > >   // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
> > >   // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
> > > ! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" }
> > >   // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
> > >   // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
> > >   // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
> > > Index: early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp
> > > ===================================================================
> > > *** early-lto-debug.orig/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-05-16 13:10:47.554202813 +0200
> > > --- early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-05-16 13:10:49.874240999 +0200
> > > ***************
> > > *** 15,20 ****
> > > --- 15,21 ----
> > >   # <http://www.gnu.org/licenses/>.
> > >   
> > >   load_lib gdb-test.exp
> > > + load_lib target-supports.exp
> > >   
> > >   dg-init
> > >   v3-build_support
> > > *************** global PCH_CXXFLAGS
> > > *** 46,51 ****
> > > --- 47,60 ----
> > >   gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
> > >     "" "$DEFAULT_CXXFLAGS $PCH_CXXFLAGS"
> > >   
> > > + if { [check_effective_target_lto] } {
> > > +   append cxxflags " -flto"
> > > +   # work around sourceware.org 20882
> > > +   regsub {^(.*)-Wl,--gc-sections(.*)$} $cxxldflags {\1\2} cxxldflags
> > > +   gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
> > > +     "" "$DEFAULT_CXXFLAGS -flto $PCH_CXXFLAGS"
> > > + }
> > > + 
> > >   if [info exists guality_gdb_name] {
> > >       unsetenv GUALITY_GDB_NAME
> > >   }
> > > Index: early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90
> > > ===================================================================
> > > *** /dev/null	1970-01-01 00:00:00.000000000 +0000
> > > --- early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90	2017-05-18 09:39:31.394914888 +0200
> > > ***************
> > > *** 0 ****
> > > --- 1,54 ----
> > > + ! { dg-do run }
> > > + ! { dg-require-effective-target lto }
> > > + ! { dg-options "-fno-automatic -flto -g" }
> > > + !
> > > + ! PR fortran/55733
> > > + !
> > > + ! Check that -fno-automatic makes the local variable SAVEd
> > > + ! Check that -flto -g works
> > > + !
> > > + 
> > > + ! Scalar allocatable
> > > + subroutine foo(i)
> > > +   integer :: i
> > > +   integer, allocatable :: j
> > > +   if (i == 1) j = 42
> > > +   if (.not. allocated (j)) call abort ()
> > > +   if (j /= 42) call abort ()
> > > + end
> > > + 
> > > + ! Deferred-length string scalar
> > > + subroutine bar()
> > > +   logical, save :: first = .true.
> > > +   character(len=:), allocatable :: str
> > > +   if (first) then
> > > +     first = .false.
> > > +     if (allocated (str)) call abort ()
> > > +     str = "ABCDEF"
> > > +   end if
> > > +   if (.not. allocated (str)) call abort ()
> > > +   if (len (str) /= 6) call abort ()
> > > +   if (str(1:6) /= "ABCDEF") call abort ()
> > > + end subroutine bar
> > > + 
> > > + ! Deferred-length string array
> > > + subroutine bar_array()
> > > +   logical, save :: first = .true.
> > > +   character(len=:), allocatable :: str
> > > +   if (first) then
> > > +     first = .false.
> > > +     if (allocated (str)) call abort ()
> > > +     str = "ABCDEF"
> > > +   end if
> > > +   if (.not. allocated (str)) call abort ()
> > > +   if (len (str) /= 6) call abort ()
> > > +   if (str(1:6) /= "ABCDEF") call abort ()
> > > + end subroutine bar_array
> > > + 
> > > + call foo(1)
> > > + call foo(2)
> > > + call bar()
> > > + call bar_array()
> > > + call bar()
> > > + call bar_array()
> > > + end
> > > Index: early-lto-debug/gcc/config/i386/i386.c
> > > ===================================================================
> > > *** early-lto-debug.orig/gcc/config/i386/i386.c	2017-05-15 10:57:19.923567540 +0200
> > > --- early-lto-debug/gcc/config/i386/i386.c	2017-05-19 11:27:19.565373271 +0200
> > > *************** make_resolver_func (const tree default_d
> > > *** 33840,33846 ****
> > >     DECL_NAME (decl) = decl_name;
> > >     TREE_USED (decl) = 1;
> > >     DECL_ARTIFICIAL (decl) = 1;
> > > !   DECL_IGNORED_P (decl) = 0;
> > >     /* IFUNC resolvers have to be externally visible.  */
> > >     TREE_PUBLIC (decl) = 1;
> > >     DECL_UNINLINABLE (decl) = 1;
> > > --- 33840,33846 ----
> > >     DECL_NAME (decl) = decl_name;
> > >     TREE_USED (decl) = 1;
> > >     DECL_ARTIFICIAL (decl) = 1;
> > > !   DECL_IGNORED_P (decl) = 1;
> > >     /* IFUNC resolvers have to be externally visible.  */
> > >     TREE_PUBLIC (decl) = 1;
> > >     DECL_UNINLINABLE (decl) = 1;
> > > 
> > 
> > 
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-07-04 11:10     ` Richard Biener
@ 2017-07-28 12:55       ` Richard Biener
  0 siblings, 0 replies; 22+ messages in thread
From: Richard Biener @ 2017-07-28 12:55 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason, Jakub Jelinek, law

On Tue, 4 Jul 2017, Richard Biener wrote:

> On Tue, 20 Jun 2017, Richard Biener wrote:
> 
> > On Wed, 7 Jun 2017, Richard Biener wrote:
> > 
> > > On Fri, 19 May 2017, Richard Biener wrote:
> > > 
> > > > 
> > > > This is a repost of the main part of the early LTO debug support.
> > > > The only changes relative to the last post is in the dwarf2out.c
> > > > pieces due to Jasons review and Jakubs introduction of
> > > > DW_OP_GNU_variable_value.
> > > > 
> > > > I've also adjusted testcases for fallout (the asan backtraces do
> > > > give files / line numbers because libbacktrace doesn't understand
> > > > the DWARF) plus added a -flto run over the libstdc++ pretty printer
> > > > testsuite -- after all the goal was to make those work with LTO,
> > > > and they now nicely do.
> > > > 
> > > > [LTO-]bootstrapped and tested on x86_64-unknown-linux-gnu.
> > > > 
> > > > I've also tested with -flto -g and compared to before the patch and
> > > > the outcome doesn't contain any surprises.
> > > > 
> > > > I've also ran the gdb testsuite with no differences (but I guess
> > > > it doesn't exercise LTO).
> > > > 
> > > > I've also built SPEC 2k6 with -flto -g.
> > > > 
> > > > I've also debugged optimized LTO bootstrapped cc1 a bit - not that
> > > > debugging (LTO) optimized cc1 is a pleasant experience, but at least
> > > > gdb doesn't crash.
> > > > 
> > > > Ok for trunk?
> > > 
> > > Ping.
> > 
> > Ping^2.
> 
> Ping^3.

Ping^4.  Adding some more global reviewers to CC.

Richard.

> > > > Both darwin and mingw maintainers were not concerned about LTO with -g
> > > > being broken for them.
> > > > 
> > > > This patch allows us to go forward with freeing more stuff after
> > > > the frontend finished, in particular remove LTO streaming of a lot
> > > > of type information that is referenced from trees (and, as a first
> > > > step, enable free-lang-data for non-LTO compiles).
> > > > 
> > > > Thanks,
> > > > Richard.
> > > > 
> > > > 2017-05-19  Richard Biener  <rguenther@suse.de>
> > > > 
> > > >         * debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and
> > > >         register_external_die hooks.
> > > >         (debug_false_tree_charstarstar_uhwistar): Declare.
> > > >         (debug_nothing_tree_charstar_uhwi): Likewise.
> > > >         * debug.c (do_nothing_debug_hooks): Adjust.
> > > >         (debug_false_tree_charstarstar_uhwistar): New do nothing.
> > > >         (debug_nothing_tree_charstar_uhwi): Likewise.
> > > >         * dbxout.c (dbx_debug_hooks): Adjust.
> > > >         (xcoff_debug_hooks): Likewise.
> > > >         * sdbout.c (sdb_debug_hooks): Likewise.
> > > >         * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
> > > > 
> > > >         * dwarf2out.c (macinfo_label_base): New global.
> > > > 	(dwarf2out_register_external_die): New function for the
> > > > 	register_external_die hook.
> > > >         (dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl.
> > > >         (dwarf2_debug_hooks): Use them.
> > > >         (dwarf2_lineno_debug_hooks): Adjust.
> > > >         (struct die_struct): Add with_offset flag.
> > > >         (DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION,
> > > >         DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION,
> > > >         DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION,
> > > >         DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION,
> > > >         DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
> > > >         DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros
> > > >         defining section names for the early LTO debug variants.
> > > > 	(reset_indirect_string): New helper.
> > > >         (add_AT_external_die_ref): Helper for dwarf2out_register_external_die.
> > > >         (print_dw_val): Add support for offsetted symbol references.
> > > >         (compute_section_prefix_1): Split out worker to distinguish
> > > >         the comdat from the LTO case.
> > > >         (compute_section_prefix): Wrap old comdat case here.
> > > >         (output_die): Skip DIE symbol output for the LTO added one.
> > > >         Handle DIE symbol references with offset.
> > > >         (output_comp_unit): Guard section name mangling properly.
> > > >         For LTO debug sections emit a symbol at the section beginning
> > > >         which we use to refer to its DIEs.
> > > >         (add_abstract_origin_attribute): For DIEs registered via
> > > >         dwarf2out_register_external_die directly refer to the early
> > > >         DIE rather than indirectly through the shadow one we created.
> > > >         (gen_array_type_die): When generating early LTO debug do
> > > >         not emit DW_AT_string_length.
> > > >         (gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs
> > > >         late when in LTO.
> > > >         (gen_subprogram_die): Adjust the check for whether we face
> > > >         a concrete instance DIE for an inline we can reuse for the
> > > >         late LTO case.  Likewise avoid another specification DIE
> > > >         for early built declarations/definitions for the late LTO case.
> > > >         (gen_variable_die): Add type references for late duplicated VLA dies
> > > >         when in late LTO.
> > > >         (gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function,
> > > >         we have the abstract instance already.
> > > >         (process_scope_var): Adjust decl DIE contexts in LTO which
> > > >         first puts them in limbo.
> > > >         (gen_decl_die): Do not generate type DIEs late apart from
> > > >         types for VLAs or for decls we do not yet have a DIE.
> > > >         (dwarf2out_early_global_decl): Make sure to create DIEs
> > > >         for abstract instances of a decl first.
> > > >         (dwarf2out_late_global_decl): Adjust comment.
> > > >         (output_macinfo_op): With multiple macro sections use
> > > > 	macinfo_label_base to distinguish labels.
> > > >         (output_macinfo): Likewise.  Update macinfo_label_base.
> > > > 	Pass in the line info label.
> > > > 	(note_variable_value_in_expr): When generating LTO resolve
> > > > 	all variable values here by generating DIEs as needed.
> > > >         (init_sections_and_labels): Add early LTO debug flag parameter
> > > >         and generate different sections and names if set.  Add generation
> > > >         counter for the labels so we can have multiple of them.
> > > >         (reset_dies): Helper to allow DIEs to be output multiple times.
> > > >         (dwarf2out_finish): When outputting DIEs to the fat part of an
> > > > 	LTO object first reset DIEs.
> > > >         (dwarf2out_early_finish): Output early DIEs when generating LTO.
> > > > 
> > > > Cleanups we can do (and need) when removing the "old" LTO path and add
> > > > the early LTO path.
> > > > 
> > > >         (set_decl_abstract_flags): Remove.
> > > >         (set_block_abstract_flags): Likewise.
> > > >         (dwarf2out_abstract_function): Treat the early generated DIEs
> > > >         as the abstract copy and only add DW_AT_inline and
> > > >         DW_AT_artificial here.
> > > > 
> > > > 	* tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL
> > > > 	if we have none yet (Go fails to build one, PR78628).
> > > >         * lto-streamer-in.c: Include debug.h.
> > > >         (dref_queue): New global.
> > > >         (lto_read_tree_1): Stream in DIE references.
> > > >         (lto_input_tree): Register DIE references.
> > > > 	(input_function): Stream DECL_DEBUG_ARGS.
> > > >         * lto-streamer-out.c: Include debug.h.
> > > >         (lto_write_tree_1): Output DIE references.
> > > >         (DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN.
> > > > 	Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls.
> > > > 	(output_function): Stream DECL_DEBUG_ARGS.
> > > >         * tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers):
> > > >         Stream DECL_ABSTRACT_ORIGIN.
> > > >         * tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise.
> > > > 	(write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL
> > > > 	DECL_CONTEXT for file-scope decls.
> > > >         * lto-streamer.h (struct dref_entry): Declare.
> > > >         (dref_queue): Likewise.
> > > > 
> > > >         * lto-wrapper.c (debug_obj): New global.
> > > >         (tool_cleanup): Unlink it if required.
> > > >         (debug_objcopy): New function.
> > > >         (run_gcc): Handle early debug sections in the IL files by
> > > >         extracting them to separate files, partially linkin them and
> > > >         feeding the result back as result to the linker.
> > > > 
> > > >         * config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION,
> > > >         DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION,
> > > >         DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug
> > > >         sections into a separate segment.
> > > >         * config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO
> > > >         segments.
> > > >         (darwin_asm_dwarf_section): Likewise.
> > > >         (darwin_asm_output_dwarf_offset): Likewise.
> > > > 
> > > > 	* config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P.
> > > > 
> > > >         lto/
> > > >         * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
> > > >         (lto_read_decls): Process TRANSLATION_UNIT_DECLs.  Remove
> > > >         TYPE_DECL debug processing, register DIE references from
> > > >         prevailing SCCs with the debug machinery.
> > > >         (lto_section_with_id): Handle LTO debug sections.
> > > > 
> > > > 	libstdc++/
> > > > 	* testsuite/libstdc++-prettyprinters/prettyprinters.exp: Run all
> > > > 	tests with -flto as well if supported.
> > > > 
> > > > 	* c-c++-common/asan/global-overflow-1.c: Adjust diagnostic location
> > > > 	regex to handle the LTO case.
> > > > 	* c-c++-common/asan/heap-overflow-1.c: Likewise.
> > > > 	* c-c++-common/asan/misalign-1.c: Likewise.
> > > > 	* c-c++-common/asan/misalign-2.c: Likewise.
> > > > 	* c-c++-common/asan/null-deref-1.c: Likewise.
> > > > 	* c-c++-common/asan/stack-overflow-1.c: Likewise.
> > > > 	* c-c++-common/asan/strncpy-overflow-1.c: Likewise.
> > > > 	* c-c++-common/asan/use-after-free-1.c: Likewise.
> > > > 	* g++.dg/asan/large-func-test-1.C: Likewise.
> > > > 	* gfortran.dg/save_6.f90: Add -flto -g variant of save_5.f90.
> > > > 
> > > > Index: early-lto-debug/gcc/dwarf2out.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/dwarf2out.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/dwarf2out.c	2017-05-19 12:29:43.933873285 +0200
> > > > *************** static GTY(()) section *debug_aranges_se
> > > > *** 162,167 ****
> > > > --- 162,168 ----
> > > >   static GTY(()) section *debug_addr_section;
> > > >   static GTY(()) section *debug_macinfo_section;
> > > >   static const char *debug_macinfo_section_name;
> > > > + static unsigned macinfo_label_base = 1;
> > > >   static GTY(()) section *debug_line_section;
> > > >   static GTY(()) section *debug_skeleton_line_section;
> > > >   static GTY(()) section *debug_loc_section;
> > > > *************** static void dwarf2out_begin_function (tr
> > > > *** 2686,2691 ****
> > > > --- 2687,2696 ----
> > > >   static void dwarf2out_end_function (unsigned int);
> > > >   static void dwarf2out_register_main_translation_unit (tree unit);
> > > >   static void dwarf2out_set_name (tree, tree);
> > > > + static void dwarf2out_register_external_die (tree decl, const char *sym,
> > > > + 					     unsigned HOST_WIDE_INT off);
> > > > + static bool dwarf2out_die_ref_for_decl (tree decl, const char **sym,
> > > > + 					unsigned HOST_WIDE_INT *off);
> > > >   
> > > >   /* The debug hooks structure.  */
> > > >   
> > > > *************** const struct gcc_debug_hooks dwarf2_debu
> > > > *** 2720,2725 ****
> > > > --- 2725,2732 ----
> > > >     dwarf2out_late_global_decl,
> > > >     dwarf2out_type_decl,		/* type_decl */
> > > >     dwarf2out_imported_module_or_decl,
> > > > +   dwarf2out_die_ref_for_decl,
> > > > +   dwarf2out_register_external_die,
> > > >     debug_nothing_tree,		/* deferred_inline_function */
> > > >     /* The DWARF 2 backend tries to reduce debugging bloat by not
> > > >        emitting the abstract description of inline functions until
> > > > *************** const struct gcc_debug_hooks dwarf2_line
> > > > *** 2761,2766 ****
> > > > --- 2768,2775 ----
> > > >     debug_nothing_tree,		         /* late_global_decl */
> > > >     debug_nothing_tree_int,		 /* type_decl */
> > > >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > > > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> > > >     debug_nothing_tree,		         /* deferred_inline_function */
> > > >     debug_nothing_tree,		         /* outlining_inline_function */
> > > >     debug_nothing_rtx_code_label,	         /* label */
> > > > *************** typedef struct GTY((chain_circular ("%h.
> > > > *** 2889,2894 ****
> > > > --- 2898,2906 ----
> > > >     /* Die is used and must not be pruned as unused.  */
> > > >     BOOL_BITFIELD die_perennial_p : 1;
> > > >     BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
> > > > +   /* For an external ref to die_symbol if die_offset contains an extra
> > > > +      offset to that symbol.  */
> > > > +   BOOL_BITFIELD with_offset : 1;
> > > >     /* Whether this DIE was removed from the DIE tree, for example via
> > > >        prune_unused_types.  We don't consider those present from the
> > > >        DIE lookup routines.  */
> > > > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > > > *** 3692,3703 ****
> > > > --- 3704,3727 ----
> > > >   #ifndef DEBUG_DWO_INFO_SECTION
> > > >   #define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
> > > >   #endif
> > > > + #ifndef DEBUG_LTO_DWO_INFO_SECTION
> > > > + #define DEBUG_LTO_DWO_INFO_SECTION ".gnu.debuglto_.debug_info.dwo"
> > > > + #endif
> > > > + #ifndef DEBUG_LTO_INFO_SECTION
> > > > + #define DEBUG_LTO_INFO_SECTION	".gnu.debuglto_.debug_info"
> > > > + #endif
> > > >   #ifndef DEBUG_ABBREV_SECTION
> > > >   #define DEBUG_ABBREV_SECTION	".debug_abbrev"
> > > >   #endif
> > > >   #ifndef DEBUG_DWO_ABBREV_SECTION
> > > >   #define DEBUG_DWO_ABBREV_SECTION ".debug_abbrev.dwo"
> > > >   #endif
> > > > + #ifndef DEBUG_LTO_DWO_ABBREV_SECTION
> > > > + #define DEBUG_LTO_DWO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev.dwo"
> > > > + #endif
> > > > + #ifndef DEBUG_LTO_ABBREV_SECTION
> > > > + #define DEBUG_LTO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev"
> > > > + #endif
> > > >   #ifndef DEBUG_ARANGES_SECTION
> > > >   #define DEBUG_ARANGES_SECTION	".debug_aranges"
> > > >   #endif
> > > > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > > > *** 3710,3727 ****
> > > > --- 3734,3766 ----
> > > >   #ifndef DEBUG_DWO_MACINFO_SECTION
> > > >   #define DEBUG_DWO_MACINFO_SECTION      ".debug_macinfo.dwo"
> > > >   #endif
> > > > + #ifndef DEBUG_LTO_DWO_MACINFO_SECTION
> > > > + #define DEBUG_LTO_DWO_MACINFO_SECTION  ".gnu.debuglto_.debug_macinfo.dwo"
> > > > + #endif
> > > > + #ifndef DEBUG_LTO_MACINFO_SECTION
> > > > + #define DEBUG_LTO_MACINFO_SECTION      ".gnu.debuglto_.debug_macinfo"
> > > > + #endif
> > > >   #ifndef DEBUG_DWO_MACRO_SECTION
> > > >   #define DEBUG_DWO_MACRO_SECTION        ".debug_macro.dwo"
> > > >   #endif
> > > >   #ifndef DEBUG_MACRO_SECTION
> > > >   #define DEBUG_MACRO_SECTION	".debug_macro"
> > > >   #endif
> > > > + #ifndef DEBUG_LTO_DWO_MACRO_SECTION
> > > > + #define DEBUG_LTO_DWO_MACRO_SECTION    ".gnu.debuglto_.debug_macro.dwo"
> > > > + #endif
> > > > + #ifndef DEBUG_LTO_MACRO_SECTION
> > > > + #define DEBUG_LTO_MACRO_SECTION ".gnu.debuglto_.debug_macro"
> > > > + #endif
> > > >   #ifndef DEBUG_LINE_SECTION
> > > >   #define DEBUG_LINE_SECTION	".debug_line"
> > > >   #endif
> > > >   #ifndef DEBUG_DWO_LINE_SECTION
> > > >   #define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
> > > >   #endif
> > > > + #ifndef DEBUG_LTO_LINE_SECTION
> > > > + #define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
> > > > + #endif
> > > >   #ifndef DEBUG_LOC_SECTION
> > > >   #define DEBUG_LOC_SECTION	".debug_loc"
> > > >   #endif
> > > > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > > > *** 3750,3761 ****
> > > > --- 3789,3809 ----
> > > >   #ifndef DEBUG_DWO_STR_OFFSETS_SECTION
> > > >   #define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo"
> > > >   #endif
> > > > + #ifndef DEBUG_LTO_DWO_STR_OFFSETS_SECTION
> > > > + #define DEBUG_LTO_DWO_STR_OFFSETS_SECTION ".gnu.debuglto_.debug_str_offsets.dwo"
> > > > + #endif
> > > >   #ifndef DEBUG_STR_DWO_SECTION
> > > >   #define DEBUG_STR_DWO_SECTION   ".debug_str.dwo"
> > > >   #endif
> > > > + #ifndef DEBUG_LTO_STR_DWO_SECTION
> > > > + #define DEBUG_LTO_STR_DWO_SECTION ".gnu.debuglto_.debug_str.dwo"
> > > > + #endif
> > > >   #ifndef DEBUG_STR_SECTION
> > > >   #define DEBUG_STR_SECTION  ".debug_str"
> > > >   #endif
> > > > + #ifndef DEBUG_LTO_STR_SECTION
> > > > + #define DEBUG_LTO_STR_SECTION ".gnu.debuglto_.debug_str"
> > > > + #endif
> > > >   #ifndef DEBUG_RANGES_SECTION
> > > >   #define DEBUG_RANGES_SECTION	".debug_ranges"
> > > >   #endif
> > > > *************** new_addr_loc_descr (rtx addr, enum dtpre
> > > > *** 3780,3785 ****
> > > > --- 3828,3837 ----
> > > >   /* Section flags for .debug_str.dwo section.  */
> > > >   #define DEBUG_STR_DWO_SECTION_FLAGS (SECTION_DEBUG | SECTION_EXCLUDE)
> > > >   
> > > > + /* Attribute used to refer to the macro section.  */
> > > > + #define DEBUG_MACRO_ATTRIBUTE (dwarf_version >= 5 ? DW_AT_macros \
> > > > + 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros)
> > > > + 
> > > >   /* Labels we insert at beginning sections we can reference instead of
> > > >      the section names themselves.  */
> > > >   
> > > > *************** set_indirect_string (struct indirect_str
> > > > *** 4368,4373 ****
> > > > --- 4420,4443 ----
> > > >       }
> > > >   }
> > > >   
> > > > + /* A helper function for dwarf2out_finish, called to reset indirect
> > > > +    string decisions done for early LTO dwarf output before fat object
> > > > +    dwarf output.  */
> > > > + 
> > > > + int
> > > > + reset_indirect_string (indirect_string_node **h, void *)
> > > > + {
> > > > +   struct indirect_string_node *node = *h;
> > > > +   if (node->form == DW_FORM_strp || node->form == DW_FORM_GNU_str_index)
> > > > +     {
> > > > +       free (node->label);
> > > > +       node->label = NULL;
> > > > +       node->form = (dwarf_form) 0;
> > > > +       node->index = 0;
> > > > +     }
> > > > +   return 1;
> > > > + }
> > > > + 
> > > >   /* Find out whether a string should be output inline in DIE
> > > >      or out-of-line in .debug_str section.  */
> > > >   
> > > > *************** lookup_decl_die (tree decl)
> > > > *** 5413,5418 ****
> > > > --- 5483,5668 ----
> > > >     return *die;
> > > >   }
> > > >   
> > > > + 
> > > > + /* For DECL which might have early dwarf output query a SYMBOL + OFFSET
> > > > +    style reference.  Return true if we found one refering to a DIE for
> > > > +    DECL, otherwise return false.  */
> > > > + 
> > > > + static bool
> > > > + dwarf2out_die_ref_for_decl (tree decl, const char **sym,
> > > > + 			    unsigned HOST_WIDE_INT *off)
> > > > + {
> > > > +   dw_die_ref die;
> > > > + 
> > > > +   if (flag_wpa && !decl_die_table)
> > > > +     return false;
> > > > + 
> > > > +   if (TREE_CODE (decl) == BLOCK)
> > > > +     die = BLOCK_DIE (decl);
> > > > +   else
> > > > +     die = lookup_decl_die (decl);
> > > > +   if (!die)
> > > > +     return false;
> > > > + 
> > > > +   /* During WPA stage we currently use DIEs to store the
> > > > +      decl <-> label + offset map.  That's quite inefficient but it
> > > > +      works for now.  */
> > > > +   if (flag_wpa)
> > > > +     {
> > > > +       dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
> > > > +       if (!ref)
> > > > + 	{
> > > > + 	  gcc_assert (die == comp_unit_die ());
> > > > + 	  return false;
> > > > + 	}
> > > > +       *off = ref->die_offset;
> > > > +       *sym = ref->die_id.die_symbol;
> > > > +       return true;
> > > > +     }
> > > > + 
> > > > +   /* Similar to get_ref_die_offset_label, but using the "correct"
> > > > +      label.  */
> > > > +   *off = die->die_offset;
> > > > +   while (die->die_parent)
> > > > +     die = die->die_parent;
> > > > +   /* For the containing CU DIE we compute a die_symbol in
> > > > +      compute_section_prefix.  */
> > > > +   gcc_assert (die->die_tag == DW_TAG_compile_unit
> > > > + 	      && die->die_id.die_symbol != NULL);
> > > > +   *sym = die->die_id.die_symbol;
> > > > +   return true;
> > > > + }
> > > > + 
> > > > + /* Add a reference of kind ATTR_KIND to a DIE at SYMBOL + OFFSET to DIE.  */
> > > > + 
> > > > + static void
> > > > + add_AT_external_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind,
> > > > + 			 const char *symbol, HOST_WIDE_INT offset)
> > > > + {
> > > > +   /* Create a fake DIE that contains the reference.  Don't use
> > > > +      new_die because we don't want to end up in the limbo list.  */
> > > > +   dw_die_ref ref = ggc_cleared_alloc<die_node> ();
> > > > +   ref->die_tag = die->die_tag;
> > > > +   ref->die_id.die_symbol = IDENTIFIER_POINTER (get_identifier (symbol));
> > > > +   ref->die_offset = offset;
> > > > +   ref->with_offset = 1;
> > > > +   add_AT_die_ref (die, attr_kind, ref);
> > > > + }
> > > > + 
> > > > + /* Create a DIE for DECL if required and add a reference to a DIE
> > > > +    at SYMBOL + OFFSET which contains attributes dumped early.  */
> > > > + 
> > > > + static void
> > > > + dwarf2out_register_external_die (tree decl, const char *sym,
> > > > + 				 unsigned HOST_WIDE_INT off)
> > > > + {
> > > > +   if (debug_info_level == DINFO_LEVEL_NONE)
> > > > +     return;
> > > > + 
> > > > +   if (flag_wpa && !decl_die_table)
> > > > +     decl_die_table = hash_table<decl_die_hasher>::create_ggc (1000);
> > > > + 
> > > > +   dw_die_ref die
> > > > +     = TREE_CODE (decl) == BLOCK ? BLOCK_DIE (decl) : lookup_decl_die (decl);
> > > > +   gcc_assert (!die);
> > > > + 
> > > > +   tree ctx;
> > > > +   dw_die_ref parent = NULL;
> > > > +   /* Need to lookup a DIE for the decls context - the containing
> > > > +      function or translation unit.  */
> > > > +   if (TREE_CODE (decl) == BLOCK)
> > > > +     {
> > > > +       ctx = BLOCK_SUPERCONTEXT (decl);
> > > > +       /* ???  We do not output DIEs for all scopes thus skip as
> > > > + 	 many DIEs as needed.  */
> > > > +       while (TREE_CODE (ctx) == BLOCK
> > > > + 	     && !BLOCK_DIE (ctx))
> > > > + 	ctx = BLOCK_SUPERCONTEXT (ctx);
> > > > +     }
> > > > +   else
> > > > +     ctx = DECL_CONTEXT (decl);
> > > > +   while (ctx && TYPE_P (ctx))
> > > > +     ctx = TYPE_CONTEXT (ctx);
> > > > +   if (ctx)
> > > > +     {
> > > > +       if (TREE_CODE (ctx) == BLOCK)
> > > > + 	parent = BLOCK_DIE (ctx);
> > > > +       else if (TREE_CODE (ctx) == TRANSLATION_UNIT_DECL
> > > > + 	       /* Keep the 1:1 association during WPA.  */
> > > > + 	       && !flag_wpa)
> > > > + 	/* Otherwise all late annotations go to the main CU which
> > > > + 	   imports the original CUs.  */
> > > > + 	parent = comp_unit_die ();
> > > > +       else if (TREE_CODE (ctx) == FUNCTION_DECL
> > > > + 	       && TREE_CODE (decl) != PARM_DECL
> > > > + 	       && TREE_CODE (decl) != BLOCK)
> > > > + 	/* Leave function local entities parent determination to when
> > > > + 	   we process scope vars.  */
> > > > + 	;
> > > > +       else
> > > > + 	parent = lookup_decl_die (ctx);
> > > > +     }
> > > > +   else
> > > > +     /* ???  In some cases the C++ FE (at least) fails to
> > > > +        set DECL_CONTEXT properly.  Simply globalize stuff
> > > > +        in this case.  For example
> > > > +        __dso_handle created via iostream line 74 col 25.  */
> > > > +     parent = comp_unit_die ();
> > > > +   /* Create a DIE "stub".  */
> > > > +   switch (TREE_CODE (decl))
> > > > +     {
> > > > +     case TRANSLATION_UNIT_DECL:
> > > > +       if (! flag_wpa)
> > > > + 	{
> > > > + 	  die = comp_unit_die ();
> > > > + 	  dw_die_ref import = new_die (DW_TAG_imported_unit, die, NULL_TREE);
> > > > + 	  add_AT_external_die_ref (import, DW_AT_import, sym, off);
> > > > + 	  /* We re-target all CU decls to the LTRANS CU DIE, so no need
> > > > + 	     to create a DIE for the original CUs.  */
> > > > + 	  return;
> > > > + 	}
> > > > +       /* Keep the 1:1 association during WPA.  */
> > > > +       die = new_die (DW_TAG_compile_unit, NULL, decl);
> > > > +       break;
> > > > +     case NAMESPACE_DECL:
> > > > +       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
> > > > + 	 at the input language (if we have enough DECL_CONTEXT to follow)
> > > > + 	 or use a bit in tree_decl_with_vis to record the distinction.  */
> > > > +       die = new_die (DW_TAG_namespace, parent, decl);
> > > > +       break;
> > > > +     case FUNCTION_DECL:
> > > > +       die = new_die (DW_TAG_subprogram, parent, decl);
> > > > +       break;
> > > > +     case VAR_DECL:
> > > > +       die = new_die (DW_TAG_variable, parent, decl);
> > > > +       break;
> > > > +     case RESULT_DECL:
> > > > +       die = new_die (DW_TAG_variable, parent, decl);
> > > > +       break;
> > > > +     case PARM_DECL:
> > > > +       die = new_die (DW_TAG_formal_parameter, parent, decl);
> > > > +       break;
> > > > +     case CONST_DECL:
> > > > +       die = new_die (DW_TAG_constant, parent, decl);
> > > > +       break;
> > > > +     case LABEL_DECL:
> > > > +       die = new_die (DW_TAG_label, parent, decl);
> > > > +       break;
> > > > +     case BLOCK:
> > > > +       die = new_die (DW_TAG_lexical_block, parent, decl);
> > > > +       break;
> > > > +     default:
> > > > +       gcc_unreachable ();
> > > > +     }
> > > > +   if (TREE_CODE (decl) == BLOCK)
> > > > +     BLOCK_DIE (decl) = die;
> > > > +   else
> > > > +     equate_decl_number_to_die (decl, die);
> > > > + 
> > > > +   /* Add a reference to the DIE providing early debug at $sym + off.  */
> > > > +   add_AT_external_die_ref (die, DW_AT_abstract_origin, sym, off);
> > > > + }
> > > > + 
> > > >   /* Returns a hash value for X (which really is a var_loc_list).  */
> > > >   
> > > >   inline hashval_t
> > > > *************** print_dw_val (dw_val_node *val, bool rec
> > > > *** 5900,5906 ****
> > > >   			       die->die_id.die_type_node->signature);
> > > >   	    }
> > > >   	  else if (die->die_id.die_symbol)
> > > > ! 	    fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
> > > >   	  else
> > > >   	    fprintf (outfile, "die -> %ld", die->die_offset);
> > > >   	  fprintf (outfile, " (%p)", (void *) die);
> > > > --- 6150,6160 ----
> > > >   			       die->die_id.die_type_node->signature);
> > > >   	    }
> > > >   	  else if (die->die_id.die_symbol)
> > > > ! 	    {
> > > > ! 	      fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
> > > > ! 	      if (die->with_offset)
> > > > ! 		fprintf (outfile, " + %ld", die->die_offset);
> > > > ! 	    }
> > > >   	  else
> > > >   	    fprintf (outfile, "die -> %ld", die->die_offset);
> > > >   	  fprintf (outfile, " (%p)", (void *) die);
> > > > *************** static unsigned int comdat_symbol_number
> > > > *** 7216,7222 ****
> > > >      children, and set comdat_symbol_id accordingly.  */
> > > >   
> > > >   static void
> > > > ! compute_section_prefix (dw_die_ref unit_die)
> > > >   {
> > > >     const char *die_name = get_AT_string (unit_die, DW_AT_name);
> > > >     const char *base = die_name ? lbasename (die_name) : "anonymous";
> > > > --- 7470,7476 ----
> > > >      children, and set comdat_symbol_id accordingly.  */
> > > >   
> > > >   static void
> > > > ! compute_section_prefix_1 (dw_die_ref unit_die, bool comdat_p)
> > > >   {
> > > >     const char *die_name = get_AT_string (unit_die, DW_AT_name);
> > > >     const char *base = die_name ? lbasename (die_name) : "anonymous";
> > > > *************** compute_section_prefix (dw_die_ref unit_
> > > > *** 7235,7241 ****
> > > >     unmark_all_dies (unit_die);
> > > >     md5_finish_ctx (&ctx, checksum);
> > > >   
> > > > !   sprintf (name, "%s.", base);
> > > >     clean_symbol_name (name);
> > > >   
> > > >     p = name + strlen (name);
> > > > --- 7489,7499 ----
> > > >     unmark_all_dies (unit_die);
> > > >     md5_finish_ctx (&ctx, checksum);
> > > >   
> > > > !   /* When we this for comp_unit_die () we have a DW_AT_name that might
> > > > !      not start with a letter but with anything valid for filenames and
> > > > !      clean_symbol_name doesn't fix that up.  Prepend 'g' if the first
> > > > !      character is not a letter.  */
> > > > !   sprintf (name, "%s%s.", ISALPHA (*base) ? "" : "g", base);
> > > >     clean_symbol_name (name);
> > > >   
> > > >     p = name + strlen (name);
> > > > *************** compute_section_prefix (dw_die_ref unit_
> > > > *** 7245,7251 ****
> > > >         p += 2;
> > > >       }
> > > >   
> > > > !   comdat_symbol_id = unit_die->die_id.die_symbol = xstrdup (name);
> > > >     comdat_symbol_number = 0;
> > > >   }
> > > >   
> > > > --- 7503,7517 ----
> > > >         p += 2;
> > > >       }
> > > >   
> > > > !   unit_die->die_id.die_symbol = xstrdup (name);
> > > > !   unit_die->comdat_type_p = comdat_p;
> > > > ! }
> > > > ! 
> > > > ! static void
> > > > ! compute_section_prefix (dw_die_ref unit_die)
> > > > ! {
> > > > !   compute_section_prefix_1 (unit_die, true);
> > > > !   comdat_symbol_id = unit_die->die_id.die_symbol;
> > > >     comdat_symbol_number = 0;
> > > >   }
> > > >   
> > > > *************** output_die (dw_die_ref die)
> > > > *** 9971,9977 ****
> > > >   
> > > >     /* If someone in another CU might refer to us, set up a symbol for
> > > >        them to point to.  */
> > > > !   if (! die->comdat_type_p && die->die_id.die_symbol)
> > > >       output_die_symbol (die);
> > > >   
> > > >     dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
> > > > --- 10237,10247 ----
> > > >   
> > > >     /* If someone in another CU might refer to us, set up a symbol for
> > > >        them to point to.  */
> > > > !   if (! die->comdat_type_p && die->die_id.die_symbol
> > > > !       /* Don't output the symbol twice.  For LTO we want the label
> > > > !          on the section beginning, not on the actual DIE.  */
> > > > !       && (!flag_generate_lto
> > > > ! 	  || die->die_tag != DW_TAG_compile_unit))
> > > >       output_die_symbol (die);
> > > >   
> > > >     dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
> > > > *************** output_die (dw_die_ref die)
> > > > *** 10164,10171 ****
> > > >   		    size = DWARF2_ADDR_SIZE;
> > > >   		  else
> > > >   		    size = DWARF_OFFSET_SIZE;
> > > > ! 		  dw2_asm_output_offset (size, sym, debug_info_section, "%s",
> > > > ! 					 name);
> > > >   		}
> > > >   	    }
> > > >   	  else
> > > > --- 10434,10453 ----
> > > >   		    size = DWARF2_ADDR_SIZE;
> > > >   		  else
> > > >   		    size = DWARF_OFFSET_SIZE;
> > > > ! 		  /* ???  We cannot unconditionally output die_offset if
> > > > ! 		     non-zero - at least -feliminate-dwarf2-dups will
> > > > ! 		     create references to those DIEs via symbols.  And we
> > > > ! 		     do not clear its DIE offset after outputting it
> > > > ! 		     (and the label refers to the actual DIEs, not the
> > > > ! 		     DWARF CU unit header which is when using label + offset
> > > > ! 		     would be the correct thing to do).
> > > > ! 		     ???  This is the reason for the with_offset flag.  */
> > > > ! 		  if (AT_ref (a)->with_offset)
> > > > ! 		    dw2_asm_output_offset (size, sym, AT_ref (a)->die_offset,
> > > > ! 					   debug_info_section, "%s", name);
> > > > ! 		  else
> > > > ! 		    dw2_asm_output_offset (size, sym, debug_info_section, "%s",
> > > > ! 					   name);
> > > >   		}
> > > >   	    }
> > > >   	  else
> > > > *************** output_comp_unit (dw_die_ref die, int ou
> > > > *** 10391,10397 ****
> > > >     calc_die_sizes (die);
> > > >   
> > > >     oldsym = die->die_id.die_symbol;
> > > > !   if (oldsym)
> > > >       {
> > > >         tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
> > > >   
> > > > --- 10673,10679 ----
> > > >     calc_die_sizes (die);
> > > >   
> > > >     oldsym = die->die_id.die_symbol;
> > > > !   if (oldsym && die->comdat_type_p)
> > > >       {
> > > >         tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
> > > >   
> > > > *************** output_comp_unit (dw_die_ref die, int ou
> > > > *** 10407,10412 ****
> > > > --- 10689,10721 ----
> > > >         info_section_emitted = true;
> > > >       }
> > > >   
> > > > +   /* For LTO cross unit DIE refs we want a symbol on the start of the
> > > > +      debuginfo section, not on the CU DIE.
> > > > +      ???  We could simply use the symbol as it would be output by output_die
> > > > +      and account for the extra offset produced by the CU header which has fixed
> > > > +      size.  OTOH it currently only supports linkonce globals which would
> > > > +      be less than ideal?.  */
> > > > +   if (flag_generate_lto && oldsym)
> > > > +     {
> > > > +       /* ???  No way to get visibility assembled without a decl.  */
> > > > +       tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
> > > > + 			      get_identifier (oldsym), char_type_node);
> > > > +       TREE_PUBLIC (decl) = true;
> > > > +       TREE_STATIC (decl) = true;
> > > > +       DECL_ARTIFICIAL (decl) = true;
> > > > +       DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
> > > > +       DECL_VISIBILITY_SPECIFIED (decl) = true;
> > > > +       targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
> > > > + #ifdef ASM_WEAKEN_LABEL
> > > > +       /* We prefer a .weak because that handles duplicates from duplicate
> > > > +          archive members in a graceful way.  */
> > > > +       ASM_WEAKEN_LABEL (asm_out_file, oldsym);
> > > > + #else
> > > > +       targetm.asm_out.globalize_label (asm_out_file, oldsym);
> > > > + #endif
> > > > +       ASM_OUTPUT_LABEL (asm_out_file, oldsym);
> > > > +     }
> > > > + 
> > > >     /* Output debugging information.  */
> > > >     output_compilation_unit_header (dwo_id
> > > >   				  ? DW_UT_split_compile : DW_UT_compile);
> > > > *************** parameter_ref_descriptor (rtx rtl)
> > > > *** 14523,14528 ****
> > > > --- 14832,14840 ----
> > > >     if (dwarf_strict)
> > > >       return NULL;
> > > >     gcc_assert (TREE_CODE (DEBUG_PARAMETER_REF_DECL (rtl)) == PARM_DECL);
> > > > +   /* With LTO during LTRANS we get the late DIE that refers to the early
> > > > +      DIE, thus we add another indirection here.  This seems to confuse
> > > > +      gdb enough to make gcc.dg/guality/pr68860-1.c FAIL with LTO.  */
> > > >     ref = lookup_decl_die (DEBUG_PARAMETER_REF_DECL (rtl));
> > > >     ret = new_loc_descr (DW_OP_GNU_parameter_ref, 0, 0);
> > > >     if (ref)
> > > > *************** add_abstract_origin_attribute (dw_die_re
> > > > *** 20216,20222 ****
> > > >       }
> > > >   
> > > >     if (DECL_P (origin))
> > > > !     origin_die = lookup_decl_die (origin);
> > > >     else if (TYPE_P (origin))
> > > >       origin_die = lookup_type_die (origin);
> > > >     else if (TREE_CODE (origin) == BLOCK)
> > > > --- 20528,20547 ----
> > > >       }
> > > >   
> > > >     if (DECL_P (origin))
> > > > !     {
> > > > !       dw_die_ref c;
> > > > !       origin_die = lookup_decl_die (origin);
> > > > !       /* "Unwrap" the decls DIE which we put in the imported unit context.
> > > > !           ???  If we finish dwarf2out_function_decl refactoring we can
> > > > ! 	  do this in a better way from the start and only lazily emit
> > > > ! 	  the early DIE references.  */
> > > > !       if (in_lto_p
> > > > ! 	  && origin_die
> > > > ! 	  && (c = get_AT_ref (origin_die, DW_AT_abstract_origin))
> > > > ! 	  /* ???  Identify this better.  */
> > > > ! 	  && c->with_offset)
> > > > ! 	origin_die = c;
> > > > !     }
> > > >     else if (TYPE_P (origin))
> > > >       origin_die = lookup_type_die (origin);
> > > >     else if (TREE_CODE (origin) == BLOCK)
> > > > *************** gen_array_type_die (tree type, dw_die_re
> > > > *** 20775,20781 ****
> > > >         size = int_size_in_bytes (type);
> > > >         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)
> > > >   	{
> > > >   	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> > > > --- 21100,21109 ----
> > > >         size = int_size_in_bytes (type);
> > > >         if (size >= 0)
> > > >   	add_AT_unsigned (array_die, DW_AT_byte_size, size);
> > > > !       /* ???  We can't annotate types late, but for LTO we may not
> > > > ! 	 generate a location early either (gfortran.dg/save_6.f90).  */
> > > > !       else if (! (early_dwarf && flag_generate_lto)
> > > > ! 	       && TYPE_DOMAIN (type) != NULL_TREE
> > > >   	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE)
> > > >   	{
> > > >   	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> > > > *************** gen_formal_parameter_die (tree node, tre
> > > > *** 21188,21194 ****
> > > >   	 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
> > > > --- 21516,21524 ----
> > > >   	 thing.  */
> > > >         if (parm_die && parm_die->die_parent != context_die)
> > > >   	{
> > > > ! 	  /* ???  The DIE parent is the "abstract" copy and the context_die
> > > > ! 	     is the specification "copy".  */
> > > > ! 	  if (!DECL_ABSTRACT_P (node) && !in_lto_p)
> > > >   	    {
> > > >   	      /* This can happen when creating an inlined instance, in
> > > >   		 which case we need to create a new DIE that will get
> > > > *************** gen_type_die_for_member (tree type, tree
> > > > *** 21462,21468 ****
> > > >   /* 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, 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
> > > > --- 21792,21797 ----
> > > > *************** set_decl_origin_self (tree decl)
> > > > *** 21535,21685 ****
> > > >       }
> > > >   }
> > > >   \f
> > > > ! /* 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, vec<tree> &abstract_vec)
> > > > ! {
> > > > !   tree local_decl;
> > > > !   tree subblock;
> > > > !   unsigned int i;
> > > > ! 
> > > > !   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, abstract_vec);
> > > > ! 
> > > > !   for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
> > > > !     {
> > > > !       local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i);
> > > > !       if ((VAR_P (local_decl) && !TREE_STATIC (local_decl))
> > > > ! 	  || TREE_CODE (local_decl) == PARM_DECL)
> > > > ! 	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, abstract_vec);
> > > > ! }
> > > > ! 
> > > > ! /* 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, vec<tree> &abstract_vec)
> > > > ! {
> > > > !   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))
> > > > ! 	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), 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.
> > > > ! 
> > > > !    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)
> > > >   {
> > > >     dw_die_ref old_die;
> > > > -   tree save_fn;
> > > > -   tree context;
> > > > -   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;
> > > > -   struct call_arg_loc_node *old_call_arg_locations;
> > > >   
> > > >     /* Make sure we have the actual abstract inline, not a clone.  */
> > > >     decl = DECL_ORIGIN (decl);
> > > >   
> > > >     old_die = lookup_decl_die (decl);
> > > > !   if (old_die && get_AT (old_die, DW_AT_inline))
> > > >       /* We've already generated the abstract instance.  */
> > > >       return;
> > > >   
> > > > !   /* We can be called while recursively when seeing block defining inlined subroutine
> > > > !      DIE.  Be sure to not clobber the outer location table nor use it or we would
> > > > !      get locations in abstract instantces.  */
> > > > !   old_decl_loc_table = decl_loc_table;
> > > > !   decl_loc_table = NULL;
> > > > !   old_cached_dw_loc_list_table = cached_dw_loc_list_table;
> > > > !   cached_dw_loc_list_table = NULL;
> > > > !   old_call_arg_locations = call_arg_locations;
> > > > !   call_arg_locations = NULL;
> > > > !   old_call_site_count = call_site_count;
> > > > !   call_site_count = -1;
> > > > !   old_tail_call_site_count = tail_call_site_count;
> > > > !   tail_call_site_count = -1;
> > > > ! 
> > > > !   /* Be sure we've emitted the in-class declaration DIE (if any) first, so
> > > > !      we don't get confused by DECL_ABSTRACT_P.  */
> > > > !   if (debug_info_level > DINFO_LEVEL_TERSE)
> > > >       {
> > > > !       context = decl_class_context (decl);
> > > > !       if (context)
> > > > ! 	gen_type_die_for_member
> > > > ! 	  (context, decl, decl_function_context (decl) ? NULL : comp_unit_die ());
> > > >       }
> > > >   
> > > > !   /* Pretend we've just finished compiling this function.  */
> > > > !   save_fn = current_function_decl;
> > > > !   current_function_decl = decl;
> > > > ! 
> > > > !   auto_vec<tree, 64> abstract_vec;
> > > > !   set_decl_abstract_flags (decl, abstract_vec);
> > > > !   dwarf2out_decl (decl);
> > > > !   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;
> > > > !   cached_dw_loc_list_table = old_cached_dw_loc_list_table;
> > > > !   call_arg_locations = old_call_arg_locations;
> > > > !   call_site_count = old_call_site_count;
> > > > !   tail_call_site_count = old_tail_call_site_count;
> > > >   }
> > > >   
> > > >   /* Helper function of premark_used_types() which gets called through
> > > > --- 21864,21908 ----
> > > >       }
> > > >   }
> > > >   \f
> > > > ! /* Mark the early DIE for DECL as the abstract instance.  */
> > > >   
> > > >   static void
> > > >   dwarf2out_abstract_function (tree decl)
> > > >   {
> > > >     dw_die_ref old_die;
> > > >   
> > > >     /* Make sure we have the actual abstract inline, not a clone.  */
> > > >     decl = DECL_ORIGIN (decl);
> > > >   
> > > > +   if (DECL_IGNORED_P (decl))
> > > > +     return;
> > > > + 
> > > >     old_die = lookup_decl_die (decl);
> > > > !   /* With early debug we always have an old DIE.  */
> > > > !   gcc_assert (old_die != NULL);
> > > > !   if (get_AT (old_die, DW_AT_inline))
> > > >       /* We've already generated the abstract instance.  */
> > > >       return;
> > > >   
> > > > !   /* Go ahead and put DW_AT_inline on the DIE.  */
> > > > !   if (DECL_DECLARED_INLINE_P (decl))
> > > >       {
> > > > !       if (cgraph_function_possibly_inlined_p (decl))
> > > > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_inlined);
> > > > !       else
> > > > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_not_inlined);
> > > > !     }
> > > > !   else
> > > > !     {
> > > > !       if (cgraph_function_possibly_inlined_p (decl))
> > > > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_inlined);
> > > > !       else
> > > > ! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_not_inlined);
> > > >       }
> > > >   
> > > > !   if (DECL_DECLARED_INLINE_P (decl)
> > > > !       && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
> > > > !     add_AT_flag (old_die, DW_AT_artificial, 1);
> > > >   }
> > > >   
> > > >   /* Helper function of premark_used_types() which gets called through
> > > > *************** gen_subprogram_die (tree decl, dw_die_re
> > > > *** 21901,21907 ****
> > > >         if (old_die && old_die->die_parent == NULL)
> > > >   	add_child_die (context_die, old_die);
> > > >   
> > > > !       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.  */
> > > > --- 22124,22135 ----
> > > >         if (old_die && old_die->die_parent == NULL)
> > > >   	add_child_die (context_die, old_die);
> > > >   
> > > > !       dw_die_ref c;
> > > > !       if (old_die
> > > > ! 	  && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
> > > > ! 	  /* ???  In LTO all origin DIEs still refer to the early
> > > > ! 	     debug copy.  Detect that.  */
> > > > ! 	  && get_AT (c, DW_AT_inline))
> > > >   	{
> > > >   	  /* If we have a DW_AT_abstract_origin we have a working
> > > >   	     cached version.  */
> > > > *************** gen_subprogram_die (tree decl, dw_die_re
> > > > *** 21969,21975 ****
> > > >   	   || (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)
> > > > --- 22197,22204 ----
> > > >   	   || (old_die->die_parent
> > > >   	       && old_die->die_parent->die_tag == DW_TAG_module)
> > > >   	   || context_die == NULL)
> > > > ! 	  /* ???  In LTO we do not see any of the location attributes.  */
> > > > ! 	   && ((DECL_ARTIFICIAL (decl) || in_lto_p)
> > > >   	       || (get_AT_file (old_die, DW_AT_decl_file) == file_index
> > > >   		   && (get_AT_unsigned (old_die, DW_AT_decl_line)
> > > >   		       == (unsigned) s.line)
> > > > *************** gen_variable_die (tree decl, tree origin
> > > > *** 22836,22841 ****
> > > > --- 23065,23088 ----
> > > >   	  /* If a DIE was dumped early, it still needs location info.
> > > >   	     Skip to where we fill the location bits.  */
> > > >   	  var_die = old_die;
> > > > + 
> > > > + 	  /* ???  In LTRANS we cannot annotate early created variably
> > > > + 	     modified type DIEs without copying them and adjusting all
> > > > + 	     references to them.  Thus we dumped them again, also add a
> > > > + 	     reference to them.  */
> > > > + 	  tree type = TREE_TYPE (decl_or_origin);
> > > > + 	  if (in_lto_p
> > > > + 	      && variably_modified_type_p
> > > > + 		   (type, decl_function_context (decl_or_origin)))
> > > > + 	    {
> > > > + 	      if (decl_by_reference_p (decl_or_origin))
> > > > + 		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),
> > > > + 				    false, context_die);
> > > > + 	    }
> > > > + 
> > > >   	  goto gen_variable_die_location;
> > > >   	}
> > > >       }
> > > > *************** gen_inlined_subroutine_die (tree stmt, d
> > > > *** 23236,23247 ****
> > > >     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
> > > > -      a die whose origin die hasn't been emitted, and crashing.  */
> > > > -   dwarf2out_abstract_function (decl);
> > > > - 
> > > >     if (! BLOCK_ABSTRACT (stmt))
> > > >       {
> > > >         dw_die_ref subr_die
> > > > --- 23483,23488 ----
> > > > *************** process_scope_var (tree stmt, tree decl,
> > > > *** 24868,24874 ****
> > > >   					     stmt, context_die);
> > > >       }
> > > >     else
> > > > !     gen_decl_die (decl, origin, NULL, context_die);
> > > >   }
> > > >   
> > > >   /* Generate all of the decls declared within a given scope and (recursively)
> > > > --- 25109,25128 ----
> > > >   					     stmt, context_die);
> > > >       }
> > > >     else
> > > > !     {
> > > > !       if (decl && DECL_P (decl))
> > > > ! 	{
> > > > ! 	  die = lookup_decl_die (decl);
> > > > ! 
> > > > ! 	  /* Early created DIEs do not have a parent as the decls refer
> > > > ! 	     to the function as DECL_CONTEXT rather than the BLOCK.  */
> > > > ! 	  if (in_lto_p
> > > > ! 	      && die && die->die_parent == NULL)
> > > > ! 	    add_child_die (context_die, die);
> > > > ! 	}
> > > > ! 
> > > > !       gen_decl_die (decl, origin, NULL, context_die);
> > > > !     }
> > > >   }
> > > >   
> > > >   /* Generate all of the decls declared within a given scope and (recursively)
> > > > *************** gen_decl_die (tree decl, tree origin, st
> > > > *** 25288,25295 ****
> > > >   				     ? DECL_ORIGIN (origin)
> > > >   				     : DECL_ABSTRACT_ORIGIN (decl));
> > > >   
> > > > !       /* If we're emitting an out-of-line copy of an inline function,
> > > > ! 	 emit info for the abstract instance and set up to refer to it.  */
> > > >         else if (cgraph_function_possibly_inlined_p (decl)
> > > >   	       && ! DECL_ABSTRACT_P (decl)
> > > >   	       && ! class_or_namespace_scope_p (context_die)
> > > > --- 25542,25549 ----
> > > >   				     ? DECL_ORIGIN (origin)
> > > >   				     : DECL_ABSTRACT_ORIGIN (decl));
> > > >   
> > > > !       /* If we're emitting a possibly inlined function emit it as
> > > > !          abstract instance.  */
> > > >         else if (cgraph_function_possibly_inlined_p (decl)
> > > >   	       && ! DECL_ABSTRACT_P (decl)
> > > >   	       && ! class_or_namespace_scope_p (context_die)
> > > > *************** gen_decl_die (tree decl, tree origin, st
> > > > *** 25303,25309 ****
> > > >   	}
> > > >   
> > > >         /* Otherwise we're emitting the primary DIE for this decl.  */
> > > > !       else if (debug_info_level > DINFO_LEVEL_TERSE)
> > > >   	{
> > > >   	  /* Before we describe the FUNCTION_DECL itself, make sure that we
> > > >   	     have its containing type.  */
> > > > --- 25557,25565 ----
> > > >   	}
> > > >   
> > > >         /* Otherwise we're emitting the primary DIE for this decl.  */
> > > > !       else if (debug_info_level > DINFO_LEVEL_TERSE
> > > > ! 	       /* Do not generate stray type DIEs in late LTO dumping.  */
> > > > ! 	       && early_dwarf)
> > > >   	{
> > > >   	  /* Before we describe the FUNCTION_DECL itself, make sure that we
> > > >   	     have its containing type.  */
> > > > *************** gen_decl_die (tree decl, tree origin, st
> > > > *** 25370,25389 ****
> > > >         if (debug_info_level <= DINFO_LEVEL_TERSE)
> > > >   	break;
> > > >   
> > > > !       /* Output any DIEs that are needed to specify the type of this data
> > > > ! 	 object.  */
> > > > !       if (decl_by_reference_p (decl_or_origin))
> > > > ! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > > > !       else
> > > > ! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> > > >   
> > > > !       /* And its containing type.  */
> > > > !       class_origin = decl_class_context (decl_or_origin);
> > > > !       if (class_origin != NULL_TREE)
> > > > ! 	gen_type_die_for_member (class_origin, decl_or_origin, context_die);
> > > >   
> > > > !       /* And its containing namespace.  */
> > > > !       context_die = declare_in_namespace (decl_or_origin, context_die);
> > > >   
> > > >         /* Now output the DIE to represent the data object itself.  This gets
> > > >   	 complicated because of the possibility that the VAR_DECL really
> > > > --- 25626,25661 ----
> > > >         if (debug_info_level <= DINFO_LEVEL_TERSE)
> > > >   	break;
> > > >   
> > > > !       /* Avoid generating stray type DIEs during late dwarf dumping.
> > > > !          All types have been dumped early.  */
> > > > !       if (! lookup_decl_die (decl_or_origin)
> > > > ! 	  /* ???  But in LTRANS we cannot annotate early created variably
> > > > ! 	     modified type DIEs without copying them and adjusting all
> > > > ! 	     references to them.  Dump them again as happens for inlining
> > > > ! 	     which copies both the decl and the types.  */
> > > > ! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
> > > > ! 	     in VLA bound information for example.  */
> > > > ! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
> > > > ! 						current_function_decl)))
> > > > ! 	{
> > > > ! 	  /* Output any DIEs that are needed to specify the type of this data
> > > > ! 	     object.  */
> > > > ! 	  if (decl_by_reference_p (decl_or_origin))
> > > > ! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > > > ! 	  else
> > > > ! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> > > > ! 	}
> > > >   
> > > > !       if (early_dwarf)
> > > > ! 	{
> > > > ! 	  /* And its containing type.  */
> > > > ! 	  class_origin = decl_class_context (decl_or_origin);
> > > > ! 	  if (class_origin != NULL_TREE)
> > > > ! 	    gen_type_die_for_member (class_origin, decl_or_origin, context_die);
> > > >   
> > > > ! 	  /* And its containing namespace.  */
> > > > ! 	  context_die = declare_in_namespace (decl_or_origin, context_die);
> > > > ! 	}
> > > >   
> > > >         /* Now output the DIE to represent the data object itself.  This gets
> > > >   	 complicated because of the possibility that the VAR_DECL really
> > > > *************** gen_decl_die (tree decl, tree origin, st
> > > > *** 25413,25422 ****
> > > >         break;
> > > >   
> > > >       case PARM_DECL:
> > > > !       if (DECL_BY_REFERENCE (decl_or_origin))
> > > > ! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > > > !       else
> > > > ! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> > > >         return gen_formal_parameter_die (decl, origin,
> > > >   				       true /* Emit name attribute.  */,
> > > >   				       context_die);
> > > > --- 25685,25707 ----
> > > >         break;
> > > >   
> > > >       case PARM_DECL:
> > > > !       /* Avoid generating stray type DIEs during late dwarf dumping.
> > > > !          All types have been dumped early.  */
> > > > !       if (! lookup_decl_die (decl_or_origin)
> > > > ! 	  /* ???  But in LTRANS we cannot annotate early created variably
> > > > ! 	     modified type DIEs without copying them and adjusting all
> > > > ! 	     references to them.  Dump them again as happens for inlining
> > > > ! 	     which copies both the decl and the types.  */
> > > > ! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
> > > > ! 	     in VLA bound information for example.  */
> > > > ! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
> > > > ! 						current_function_decl)))
> > > > ! 	{
> > > > ! 	  if (DECL_BY_REFERENCE (decl_or_origin))
> > > > ! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
> > > > ! 	  else
> > > > ! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
> > > > ! 	}
> > > >         return gen_formal_parameter_die (decl, origin,
> > > >   				       true /* Emit name attribute.  */,
> > > >   				       context_die);
> > > > *************** dwarf2out_early_global_decl (tree decl)
> > > > *** 25493,25498 ****
> > > > --- 25778,25793 ----
> > > >   	      dwarf2out_decl (context);
> > > >   	    }
> > > >   
> > > > + 	  /* Emit an abstract origin of a function first.  This happens
> > > > + 	     with C++ constructor clones for example and makes
> > > > + 	     dwarf2out_abstract_function happy which requires the early
> > > > + 	     DIE of the abstract instance to be present.  */
> > > > + 	  if (DECL_ABSTRACT_ORIGIN (decl))
> > > > + 	    {
> > > > + 	      current_function_decl = DECL_ABSTRACT_ORIGIN (decl);
> > > > + 	      dwarf2out_decl (DECL_ABSTRACT_ORIGIN (decl));
> > > > + 	    }
> > > > + 
> > > >   	  current_function_decl = decl;
> > > >   	}
> > > >         dwarf2out_decl (decl);
> > > > *************** dwarf2out_late_global_decl (tree decl)
> > > > *** 25515,25521 ****
> > > >       {
> > > >         dw_die_ref die = lookup_decl_die (decl);
> > > >   
> > > > !       /* We have to generate early debug late for LTO.  */
> > > >         if (! die && in_lto_p)
> > > >   	{
> > > >   	  dwarf2out_decl (decl);
> > > > --- 25810,25818 ----
> > > >       {
> > > >         dw_die_ref die = lookup_decl_die (decl);
> > > >   
> > > > !       /* We may have to generate early debug late for LTO in case debug
> > > > !          was not enabled at compile-time or the target doesn't support
> > > > ! 	 the LTO early debug scheme.  */
> > > >         if (! die && in_lto_p)
> > > >   	{
> > > >   	  dwarf2out_decl (decl);
> > > > *************** output_macinfo_op (macinfo_entry *ref)
> > > > *** 26892,26898 ****
> > > >       case DW_MACRO_import:
> > > >         dw2_asm_output_data (1, ref->code, "Import");
> > > >         ASM_GENERATE_INTERNAL_LABEL (label,
> > > > ! 				   DEBUG_MACRO_SECTION_LABEL, ref->lineno);
> > > >         dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
> > > >         break;
> > > >       default:
> > > > --- 27189,27196 ----
> > > >       case DW_MACRO_import:
> > > >         dw2_asm_output_data (1, ref->code, "Import");
> > > >         ASM_GENERATE_INTERNAL_LABEL (label,
> > > > ! 				   DEBUG_MACRO_SECTION_LABEL,
> > > > ! 				   ref->lineno + macinfo_label_base);
> > > >         dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
> > > >         break;
> > > >       default:
> > > > *************** save_macinfo_strings (void)
> > > > *** 27066,27072 ****
> > > >   /* Output macinfo section(s).  */
> > > >   
> > > >   static void
> > > > ! output_macinfo (void)
> > > >   {
> > > >     unsigned i;
> > > >     unsigned long length = vec_safe_length (macinfo_table);
> > > > --- 27364,27370 ----
> > > >   /* Output macinfo section(s).  */
> > > >   
> > > >   static void
> > > > ! output_macinfo (const char *debug_line_label, bool early_lto_debug)
> > > >   {
> > > >     unsigned i;
> > > >     unsigned long length = vec_safe_length (macinfo_table);
> > > > *************** output_macinfo (void)
> > > > *** 27092,27100 ****
> > > >   	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
> > > >         else
> > > >   	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
> > > > !       dw2_asm_output_offset (DWARF_OFFSET_SIZE,
> > > > !                              (!dwarf_split_debug_info ? debug_line_section_label
> > > > !                               : debug_skeleton_line_section_label),
> > > >                                debug_line_section, NULL);
> > > >       }
> > > >   
> > > > --- 27390,27396 ----
> > > >   	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
> > > >         else
> > > >   	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
> > > > !       dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_line_label,
> > > >                                debug_line_section, NULL);
> > > >       }
> > > >   
> > > > *************** output_macinfo (void)
> > > > *** 27148,27153 ****
> > > > --- 27444,27453 ----
> > > >     if (!macinfo_htab)
> > > >       return;
> > > >   
> > > > +   /* Save the number of transparent includes so we can adjust the
> > > > +      label number for the fat LTO object DWARF.  */
> > > > +   unsigned macinfo_label_base_adj = macinfo_htab->elements ();
> > > > + 
> > > >     delete macinfo_htab;
> > > >     macinfo_htab = NULL;
> > > >   
> > > > *************** output_macinfo (void)
> > > > *** 27167,27177 ****
> > > >   	  dw2_asm_output_data (1, 0, "End compilation unit");
> > > >   	  targetm.asm_out.named_section (debug_macinfo_section_name,
> > > >   					 SECTION_DEBUG
> > > > ! 					 | SECTION_LINKONCE,
> > > >   					 comdat_key);
> > > >   	  ASM_GENERATE_INTERNAL_LABEL (label,
> > > >   				       DEBUG_MACRO_SECTION_LABEL,
> > > > ! 				       ref->lineno);
> > > >   	  ASM_OUTPUT_LABEL (asm_out_file, label);
> > > >   	  ref->code = 0;
> > > >   	  ref->info = NULL;
> > > > --- 27467,27479 ----
> > > >   	  dw2_asm_output_data (1, 0, "End compilation unit");
> > > >   	  targetm.asm_out.named_section (debug_macinfo_section_name,
> > > >   					 SECTION_DEBUG
> > > > ! 					 | SECTION_LINKONCE
> > > > ! 					 | (early_lto_debug
> > > > ! 					    ? SECTION_EXCLUDE : 0),
> > > >   					 comdat_key);
> > > >   	  ASM_GENERATE_INTERNAL_LABEL (label,
> > > >   				       DEBUG_MACRO_SECTION_LABEL,
> > > > ! 				       ref->lineno + macinfo_label_base);
> > > >   	  ASM_OUTPUT_LABEL (asm_out_file, label);
> > > >   	  ref->code = 0;
> > > >   	  ref->info = NULL;
> > > > *************** output_macinfo (void)
> > > > *** 27192,27300 ****
> > > >         default:
> > > >   	gcc_unreachable ();
> > > >         }
> > > >   }
> > > >   
> > > > ! /* Initialize the various sections and labels for dwarf output.  */
> > > >   
> > > >   static void
> > > > ! init_sections_and_labels (void)
> > > >   {
> > > > !   if (!dwarf_split_debug_info)
> > > >       {
> > > > !       debug_info_section = get_section (DEBUG_INFO_SECTION,
> > > > !                                         SECTION_DEBUG, NULL);
> > > > !       debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > > > !                                           SECTION_DEBUG, NULL);
> > > > !       debug_loc_section = get_section (dwarf_version >= 5
> > > > ! 				       ? DEBUG_LOCLISTS_SECTION
> > > > ! 				       : DEBUG_LOC_SECTION,
> > > > !                                        SECTION_DEBUG, NULL);
> > > > !       debug_macinfo_section_name
> > > > ! 	= (dwarf_strict && dwarf_version < 5)
> > > > ! 	  ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
> > > > !       debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > > ! 					   SECTION_DEBUG, NULL);
> > > >       }
> > > >     else
> > > >       {
> > > > !       debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
> > > > !                                         SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > > !       debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
> > > > !                                           SECTION_DEBUG | SECTION_EXCLUDE,
> > > > !                                           NULL);
> > > > !       debug_addr_section = get_section (DEBUG_ADDR_SECTION,
> > > > !                                         SECTION_DEBUG, NULL);
> > > > !       debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
> > > > !                                                  SECTION_DEBUG, NULL);
> > > > !       debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > > > !                                                    SECTION_DEBUG, NULL);
> > > > !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> > > > !                                   DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0);
> > > > ! 
> > > > !       /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
> > > > !          the main .o, but the skeleton_line goes into the split off dwo.  */
> > > > !       debug_skeleton_line_section
> > > > !         = get_section (DEBUG_DWO_LINE_SECTION,
> > > > ! 		       SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > > !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > > > !                                    DEBUG_SKELETON_LINE_SECTION_LABEL, 0);
> > > > !       debug_str_offsets_section = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
> > > > !                                                SECTION_DEBUG | SECTION_EXCLUDE,
> > > > !                                                NULL);
> > > > !       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> > > > !                                    DEBUG_SKELETON_INFO_SECTION_LABEL, 0);
> > > > !       debug_loc_section = get_section (dwarf_version >= 5
> > > > ! 				       ? DEBUG_DWO_LOCLISTS_SECTION
> > > > ! 				       : DEBUG_DWO_LOC_SECTION,
> > > > !                                        SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > > !       debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
> > > > !                                            DEBUG_STR_DWO_SECTION_FLAGS, NULL);
> > > > !       debug_macinfo_section_name
> > > > ! 	= (dwarf_strict && dwarf_version < 5)
> > > > ! 	  ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
> > > > !       debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > >   					   SECTION_DEBUG | SECTION_EXCLUDE,
> > > >   					   NULL);
> > > > !     }
> > > > !   debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
> > > > ! 				       SECTION_DEBUG, NULL);
> > > > !   debug_line_section = get_section (DEBUG_LINE_SECTION,
> > > > ! 				    SECTION_DEBUG, NULL);
> > > > !   debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
> > > > ! 					SECTION_DEBUG, NULL);
> > > > !   debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
> > > >   					SECTION_DEBUG, NULL);
> > > > !   debug_str_section = get_section (DEBUG_STR_SECTION,
> > > > ! 				   DEBUG_STR_SECTION_FLAGS, NULL);
> > > > !   if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
> > > > !     debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
> > > > ! 					  DEBUG_STR_SECTION_FLAGS, NULL);
> > > > ! 
> > > > !   debug_ranges_section = get_section (dwarf_version >= 5
> > > > ! 				      ? DEBUG_RNGLISTS_SECTION
> > > > ! 				      : DEBUG_RANGES_SECTION,
> > > > ! 				      SECTION_DEBUG, NULL);
> > > > !   debug_frame_section = get_section (DEBUG_FRAME_SECTION,
> > > > ! 				     SECTION_DEBUG, NULL);
> > > >   
> > > >     ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
> > > > ! 			       DEBUG_ABBREV_SECTION_LABEL, 0);
> > > >     ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
> > > > ! 			       DEBUG_INFO_SECTION_LABEL, 0);
> > > >     ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
> > > > ! 			       DEBUG_LINE_SECTION_LABEL, 0);
> > > >     ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
> > > > ! 			       DEBUG_RANGES_SECTION_LABEL, 0);
> > > >     if (dwarf_version >= 5 && dwarf_split_debug_info)
> > > >       ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
> > > > ! 				 DEBUG_RANGES_SECTION_LABEL, 1);
> > > >     ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
> > > > !                                DEBUG_ADDR_SECTION_LABEL, 0);
> > > >     ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
> > > >   			       (dwarf_strict && dwarf_version < 5)
> > > >   			       ? DEBUG_MACINFO_SECTION_LABEL
> > > > ! 			       : DEBUG_MACRO_SECTION_LABEL, 0);
> > > > !   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0);
> > > >   }
> > > >   
> > > >   /* Set up for Dwarf output at the start of compilation.  */
> > > > --- 27494,27685 ----
> > > >         default:
> > > >   	gcc_unreachable ();
> > > >         }
> > > > + 
> > > > +   macinfo_label_base += macinfo_label_base_adj;
> > > >   }
> > > >   
> > > > ! /* Initialize the various sections and labels for dwarf output and prefix
> > > > !    them with PREFIX if non-NULL.  */
> > > >   
> > > >   static void
> > > > ! init_sections_and_labels (bool early_lto_debug)
> > > >   {
> > > > !   /* As we may get called multiple times have a generation count for labels.  */
> > > > !   static unsigned generation = 0;
> > > > ! 
> > > > !   if (early_lto_debug)
> > > >       {
> > > > !       if (!dwarf_split_debug_info)
> > > > ! 	{
> > > > ! 	  debug_info_section = get_section (DEBUG_LTO_INFO_SECTION,
> > > > ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> > > > ! 					    NULL);
> > > > ! 	  debug_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
> > > > ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> > > > ! 					      NULL);
> > > > ! 	  debug_macinfo_section_name = ((dwarf_strict && dwarf_version < 5)
> > > > ! 					? DEBUG_LTO_MACINFO_SECTION
> > > > ! 					: DEBUG_LTO_MACRO_SECTION);
> > > > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > > ! 					       SECTION_DEBUG
> > > > ! 					       | SECTION_EXCLUDE, NULL);
> > > > ! 	  /* For macro info we have to refer to a debug_line section, so similar
> > > > ! 	     to split-dwarf emit a skeleton one for early debug.  */
> > > > ! 	  debug_skeleton_line_section
> > > > ! 	    = get_section (DEBUG_LTO_LINE_SECTION,
> > > > ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > > > ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> > > > ! 				       generation);
> > > > ! 	}
> > > > !       else
> > > > ! 	{
> > > > ! 	  /* ???  Which of the following do we need early?  */
> > > > ! 	  debug_info_section = get_section (DEBUG_LTO_DWO_INFO_SECTION,
> > > > ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> > > > ! 					    NULL);
> > > > ! 	  debug_abbrev_section = get_section (DEBUG_LTO_DWO_ABBREV_SECTION,
> > > > ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> > > > ! 					      NULL);
> > > > ! 	  debug_skeleton_info_section = get_section (DEBUG_LTO_INFO_SECTION,
> > > > ! 						     SECTION_DEBUG
> > > > ! 						     | SECTION_EXCLUDE, NULL);
> > > > ! 	  debug_skeleton_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
> > > > ! 						       SECTION_DEBUG
> > > > ! 						       | SECTION_EXCLUDE, NULL);
> > > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> > > > ! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
> > > > ! 				       generation);
> > > > ! 
> > > > ! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
> > > > ! 	     the main .o, but the skeleton_line goes into the split off dwo.  */
> > > > ! 	  debug_skeleton_line_section
> > > > ! 	    = get_section (DEBUG_LTO_LINE_SECTION,
> > > > ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > > > ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> > > > ! 				       generation);
> > > > ! 	  debug_str_offsets_section
> > > > ! 	    = get_section (DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
> > > > ! 			   SECTION_DEBUG | SECTION_EXCLUDE,
> > > > ! 			   NULL);
> > > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> > > > ! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
> > > > ! 				       generation);
> > > > ! 	  debug_str_dwo_section = get_section (DEBUG_LTO_STR_DWO_SECTION,
> > > > ! 					       DEBUG_STR_DWO_SECTION_FLAGS, NULL);
> > > > ! 	  debug_macinfo_section_name
> > > > ! 	    = (dwarf_strict
> > > > ! 	       ? DEBUG_LTO_DWO_MACINFO_SECTION : DEBUG_LTO_DWO_MACRO_SECTION);
> > > > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > > ! 					       SECTION_DEBUG | SECTION_EXCLUDE,
> > > > ! 					       NULL);
> > > > ! 	}
> > > > !       debug_str_section = get_section (DEBUG_LTO_STR_SECTION,
> > > > ! 				       DEBUG_STR_SECTION_FLAGS
> > > > ! 				       | SECTION_EXCLUDE, NULL);
> > > >       }
> > > >     else
> > > >       {
> > > > !       if (!dwarf_split_debug_info)
> > > > ! 	{
> > > > ! 	  debug_info_section = get_section (DEBUG_INFO_SECTION,
> > > > ! 					    SECTION_DEBUG, NULL);
> > > > ! 	  debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > > > ! 					      SECTION_DEBUG, NULL);
> > > > ! 	  debug_loc_section = get_section (DEBUG_LOC_SECTION,
> > > > ! 					   SECTION_DEBUG, NULL);
> > > > ! 	  debug_macinfo_section_name
> > > > ! 	      = dwarf_strict ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
> > > > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > > ! 					       SECTION_DEBUG, NULL);
> > > > ! 	}
> > > > !       else
> > > > ! 	{
> > > > ! 	  debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
> > > > ! 					    SECTION_DEBUG | SECTION_EXCLUDE,
> > > > ! 					    NULL);
> > > > ! 	  debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
> > > > ! 					      SECTION_DEBUG | SECTION_EXCLUDE,
> > > > ! 					      NULL);
> > > > ! 	  debug_addr_section = get_section (DEBUG_ADDR_SECTION,
> > > > ! 					    SECTION_DEBUG, NULL);
> > > > ! 	  debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
> > > > ! 						     SECTION_DEBUG, NULL);
> > > > ! 	  debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
> > > > ! 						       SECTION_DEBUG, NULL);
> > > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
> > > > ! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
> > > > ! 				       generation);
> > > > ! 
> > > > ! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections
> > > > ! 	     stay in the main .o, but the skeleton_line goes into the
> > > > ! 	     split off dwo.  */
> > > > ! 	  debug_skeleton_line_section
> > > > ! 	      = get_section (DEBUG_DWO_LINE_SECTION,
> > > > ! 			     SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
> > > > ! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
> > > > ! 				       generation);
> > > > ! 	  debug_str_offsets_section
> > > > ! 	    = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
> > > > ! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> > > > ! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
> > > > ! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
> > > > ! 				       generation);
> > > > ! 	  debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION,
> > > >   					   SECTION_DEBUG | SECTION_EXCLUDE,
> > > >   					   NULL);
> > > > ! 	  debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
> > > > ! 					       DEBUG_STR_DWO_SECTION_FLAGS,
> > > > ! 					       NULL);
> > > > ! 	  debug_macinfo_section_name
> > > > ! 	    = (dwarf_strict && dwarf_version < 5)
> > > > ! 	      ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
> > > > ! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
> > > > ! 					       SECTION_DEBUG | SECTION_EXCLUDE,
> > > > ! 					       NULL);
> > > > ! 	}
> > > > !       debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
> > > > ! 					   SECTION_DEBUG, NULL);
> > > > !       debug_line_section = get_section (DEBUG_LINE_SECTION,
> > > >   					SECTION_DEBUG, NULL);
> > > > !       debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
> > > > ! 					    SECTION_DEBUG, NULL);
> > > > !       debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
> > > > ! 					    SECTION_DEBUG, NULL);
> > > > !       debug_str_section = get_section (DEBUG_STR_SECTION,
> > > > ! 				       DEBUG_STR_SECTION_FLAGS, NULL);
> > > > !       debug_ranges_section = get_section (dwarf_version >= 5
> > > > ! 					  ? DEBUG_RNGLISTS_SECTION
> > > > ! 					  : DEBUG_RANGES_SECTION,
> > > > ! 					  SECTION_DEBUG, NULL);
> > > > !       debug_frame_section = get_section (DEBUG_FRAME_SECTION,
> > > > ! 					 SECTION_DEBUG, NULL);
> > > > !     }
> > > >   
> > > >     ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
> > > > ! 			       DEBUG_ABBREV_SECTION_LABEL, generation);
> > > >     ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
> > > > ! 			       DEBUG_INFO_SECTION_LABEL, generation);
> > > > !   info_section_emitted = false;
> > > >     ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
> > > > ! 			       DEBUG_LINE_SECTION_LABEL, generation);
> > > >     ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
> > > > ! 			       DEBUG_RANGES_SECTION_LABEL, generation);
> > > >     if (dwarf_version >= 5 && dwarf_split_debug_info)
> > > >       ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
> > > > ! 				 DEBUG_RANGES_SECTION_LABEL, 2 + generation);
> > > >     ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
> > > > !                                DEBUG_ADDR_SECTION_LABEL, generation);
> > > >     ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
> > > >   			       (dwarf_strict && dwarf_version < 5)
> > > >   			       ? DEBUG_MACINFO_SECTION_LABEL
> > > > ! 			       : DEBUG_MACRO_SECTION_LABEL, generation);
> > > > !   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL,
> > > > ! 			       generation);
> > > > ! 
> > > > !   ++generation;
> > > >   }
> > > >   
> > > >   /* Set up for Dwarf output at the start of compilation.  */
> > > > *************** flush_limbo_die_list (void)
> > > > *** 29641,29646 ****
> > > > --- 30026,30047 ----
> > > >       }
> > > >   }
> > > >   
> > > > + /* Reset DIEs so we can output them again.  */
> > > > + 
> > > > + static void
> > > > + reset_dies (dw_die_ref die)
> > > > + {
> > > > +   dw_die_ref c;
> > > > + 
> > > > +   /* Remove stuff we re-generate.  */
> > > > +   die->die_mark = 0;
> > > > +   die->die_offset = 0;
> > > > +   die->die_abbrev = 0;
> > > > +   remove_AT (die, DW_AT_sibling);
> > > > + 
> > > > +   FOR_EACH_CHILD (die, c, reset_dies (c));
> > > > + }
> > > > + 
> > > >   /* Output stuff that dwarf requires at the end of every file,
> > > >      and generate the DWARF-2 debugging info.  */
> > > >   
> > > > *************** dwarf2out_finish (const char *)
> > > > *** 29667,29672 ****
> > > > --- 30068,30113 ----
> > > >   
> > > >     gen_remaining_tmpl_value_param_die_attribute ();
> > > >   
> > > > +   if (flag_generate_lto)
> > > > +     {
> > > > +       gcc_assert (flag_fat_lto_objects);
> > > > + 
> > > > +       /* Prune stuff so that dwarf2out_finish runs successfully
> > > > + 	 for the fat part of the object.  */
> > > > +       reset_dies (comp_unit_die ());
> > > > +       for (limbo_die_node *node = cu_die_list; node; node = node->next)
> > > > + 	reset_dies (node->die);
> > > > + 
> > > > +       hash_table<comdat_type_hasher> comdat_type_table (100);
> > > > +       for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
> > > > + 	{
> > > > + 	  comdat_type_node **slot
> > > > + 	      = comdat_type_table.find_slot (ctnode, INSERT);
> > > > + 
> > > > + 	  /* Don't reset types twice.  */
> > > > + 	  if (*slot != HTAB_EMPTY_ENTRY)
> > > > + 	    continue;
> > > > + 
> > > > + 	  /* Add a pointer to the line table for the main compilation unit
> > > > + 	     so that the debugger can make sense of DW_AT_decl_file
> > > > + 	     attributes.  */
> > > > + 	  if (debug_info_level >= DINFO_LEVEL_TERSE)
> > > > + 	    reset_dies (ctnode->root_die);
> > > > + 
> > > > + 	  *slot = ctnode;
> > > > + 	}
> > > > + 
> > > > +       /* Reset die CU symbol so we don't output it twice.  */
> > > > +       comp_unit_die ()->die_id.die_symbol = NULL;
> > > > + 
> > > > +       /* Remove DW_AT_macro from the early output.  */
> > > > +       if (have_macinfo)
> > > > + 	remove_AT (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE);
> > > > + 
> > > > +       /* Remove indirect string decisions.  */
> > > > +       debug_str_hash->traverse<void *, reset_indirect_string> (NULL);
> > > > +     }
> > > > + 
> > > >   #if ENABLE_ASSERT_CHECKING
> > > >     {
> > > >       dw_die_ref die = comp_unit_die (), c;
> > > > *************** dwarf2out_finish (const char *)
> > > > *** 29677,29683 ****
> > > >     move_marked_base_types ();
> > > >   
> > > >     /* Initialize sections and labels used for actual assembler output.  */
> > > > !   init_sections_and_labels ();
> > > >   
> > > >     /* Traverse the DIE's and add sibling attributes to those DIE's that
> > > >        have children.  */
> > > > --- 30118,30124 ----
> > > >     move_marked_base_types ();
> > > >   
> > > >     /* Initialize sections and labels used for actual assembler output.  */
> > > > !   init_sections_and_labels (false);
> > > >   
> > > >     /* Traverse the DIE's and add sibling attributes to those DIE's that
> > > >        have children.  */
> > > > *************** dwarf2out_finish (const char *)
> > > > *** 29772,29780 ****
> > > >   		    debug_line_section_label);
> > > >   
> > > >     if (have_macinfo)
> > > > !     add_AT_macptr (comp_unit_die (),
> > > > ! 		   dwarf_version >= 5 ? DW_AT_macros
> > > > ! 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
> > > >   		   macinfo_section_label);
> > > >   
> > > >     if (dwarf_split_debug_info)
> > > > --- 30213,30219 ----
> > > >   		    debug_line_section_label);
> > > >   
> > > >     if (have_macinfo)
> > > > !     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
> > > >   		   macinfo_section_label);
> > > >   
> > > >     if (dwarf_split_debug_info)
> > > > *************** dwarf2out_finish (const char *)
> > > > *** 29979,29985 ****
> > > >       {
> > > >         switch_to_section (debug_macinfo_section);
> > > >         ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> > > > !       output_macinfo ();
> > > >         dw2_asm_output_data (1, 0, "End compilation unit");
> > > >       }
> > > >   
> > > > --- 30418,30425 ----
> > > >       {
> > > >         switch_to_section (debug_macinfo_section);
> > > >         ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> > > > !       output_macinfo (!dwarf_split_debug_info ? debug_line_section_label
> > > > ! 		      : debug_skeleton_line_section_label, false);
> > > >         dw2_asm_output_data (1, 0, "End compilation unit");
> > > >       }
> > > >   
> > > > *************** note_variable_value_in_expr (dw_die_ref
> > > > *** 30200,30205 ****
> > > > --- 30640,30659 ----
> > > >         {
> > > >   	tree decl = loc->dw_loc_oprnd1.v.val_decl_ref;
> > > >   	dw_die_ref ref = lookup_decl_die (decl);
> > > > + 	if (! ref && flag_generate_lto)
> > > > + 	  {
> > > > + 	    /* ???  This is somewhat a hack because we do not create DIEs
> > > > + 	       for variables not in BLOCK trees early but when generating
> > > > + 	       early LTO output we need the dw_val_class_decl_ref to be
> > > > + 	       fully resolved.  For fat LTO objects we'd also like to
> > > > + 	       undo this after LTO dwarf output.  */
> > > > + 	    gcc_assert (DECL_CONTEXT (decl));
> > > > + 	    dw_die_ref ctx = lookup_decl_die (DECL_CONTEXT (decl));
> > > > + 	    gcc_assert (ctx != NULL);
> > > > + 	    gen_decl_die (decl, NULL_TREE, NULL, ctx);
> > > > + 	    ref = lookup_decl_die (decl);
> > > > + 	    gcc_assert (ref != NULL);
> > > > + 	  }
> > > >   	if (ref)
> > > >   	  {
> > > >   	    loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
> > > > *************** dwarf2out_early_finish (const char *file
> > > > *** 30410,30415 ****
> > > > --- 30864,30982 ----
> > > >   
> > > >     /* The early debug phase is now finished.  */
> > > >     early_dwarf_finished = true;
> > > > + 
> > > > +   /* Do not generate DWARF assembler now when not producing LTO bytecode.  */
> > > > +   if (!flag_generate_lto)
> > > > +     return;
> > > > + 
> > > > +   /* Now as we are going to output for LTO initialize sections and labels
> > > > +      to the LTO variants.  We don't need a random-seed postfix as other
> > > > +      LTO sections as linking the LTO debug sections into one in a partial
> > > > +      link is fine.  */
> > > > +   init_sections_and_labels (true);
> > > > + 
> > > > +   /* The output below is modeled after dwarf2out_finish with all
> > > > +      location related output removed and some LTO specific changes.
> > > > +      Some refactoring might make both smaller and easier to match up.  */
> > > > + 
> > > > +   /* Traverse the DIE's and add add sibling attributes to those DIE's
> > > > +      that have children.  */
> > > > +   add_sibling_attributes (comp_unit_die ());
> > > > +   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
> > > > +     add_sibling_attributes (node->die);
> > > > +   for (comdat_type_node *ctnode = comdat_type_list;
> > > > +        ctnode != NULL; ctnode = ctnode->next)
> > > > +     add_sibling_attributes (ctnode->root_die);
> > > > + 
> > > > +   if (have_macinfo)
> > > > +     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
> > > > + 		   macinfo_section_label);
> > > > + 
> > > > +   save_macinfo_strings ();
> > > > + 
> > > > +   /* Output all of the compilation units.  We put the main one last so that
> > > > +      the offsets are available to output_pubnames.  */
> > > > +   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
> > > > +     output_comp_unit (node->die, 0, NULL);
> > > > + 
> > > > +   hash_table<comdat_type_hasher> comdat_type_table (100);
> > > > +   for (comdat_type_node *ctnode = comdat_type_list;
> > > > +        ctnode != NULL; ctnode = ctnode->next)
> > > > +     {
> > > > +       comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT);
> > > > + 
> > > > +       /* Don't output duplicate types.  */
> > > > +       if (*slot != HTAB_EMPTY_ENTRY)
> > > > +         continue;
> > > > + 
> > > > +       /* Add a pointer to the line table for the main compilation unit
> > > > +          so that the debugger can make sense of DW_AT_decl_file
> > > > +          attributes.  */
> > > > +       if (debug_info_level >= DINFO_LEVEL_TERSE)
> > > > +         add_AT_lineptr (ctnode->root_die, DW_AT_stmt_list,
> > > > +                         (!dwarf_split_debug_info
> > > > +                          ? debug_line_section_label
> > > > +                          : debug_skeleton_line_section_label));
> > > > + 
> > > > +       output_comdat_type_unit (ctnode);
> > > > +       *slot = ctnode;
> > > > +     }
> > > > + 
> > > > +   /* The AT_pubnames attribute needs to go in all skeleton dies, including
> > > > +      both the main_cu and all skeleton TUs.  Making this call unconditional
> > > > +      would end up either adding a second copy of the AT_pubnames attribute, or
> > > > +      requiring a special case in add_top_level_skeleton_die_attrs.  */
> > > > +   if (!dwarf_split_debug_info)
> > > > +     add_AT_pubnames (comp_unit_die ());
> > > > + 
> > > > +   /* Stick a unique symbol to the main debuginfo section.  */
> > > > +   compute_section_prefix_1 (comp_unit_die (), false);
> > > > + 
> > > > +   /* Output the main compilation unit.  We always need it if only for
> > > > +      the CU symbol.  */
> > > > +   output_comp_unit (comp_unit_die (), true, NULL);
> > > > + 
> > > > +   /* Output the abbreviation table.  */
> > > > +   if (vec_safe_length (abbrev_die_table) != 1)
> > > > +     {
> > > > +       switch_to_section (debug_abbrev_section);
> > > > +       ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
> > > > +       output_abbrev_section ();
> > > > +     }
> > > > + 
> > > > +   /* Have to end the macro section.  */
> > > > +   if (have_macinfo)
> > > > +     {
> > > > +       /* We have to save macinfo state if we need to output it again
> > > > + 	 for the FAT part of the object.  */
> > > > +       vec<macinfo_entry, va_gc> *saved_macinfo_table = macinfo_table;
> > > > +       if (flag_fat_lto_objects)
> > > > + 	macinfo_table = macinfo_table->copy ();
> > > > + 
> > > > +       switch_to_section (debug_macinfo_section);
> > > > +       ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
> > > > +       output_macinfo (debug_skeleton_line_section_label, true);
> > > > +       dw2_asm_output_data (1, 0, "End compilation unit");
> > > > + 
> > > > +       /* Emit a skeleton debug_line section.  */
> > > > +       switch_to_section (debug_skeleton_line_section);
> > > > +       ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_line_section_label);
> > > > +       output_line_info (true);
> > > > + 
> > > > +       if (flag_fat_lto_objects)
> > > > + 	{
> > > > + 	  vec_free (macinfo_table);
> > > > + 	  macinfo_table = saved_macinfo_table;
> > > > + 	}
> > > > +     }
> > > > + 
> > > > + 
> > > > +   /* If we emitted any indirect strings, output the string table too.  */
> > > > +   if (debug_str_hash || skeleton_debug_str_hash)
> > > > +     output_indirect_strings ();
> > > > + 
> > > > +   /* Switch back to the text section.  */
> > > > +   switch_to_section (text_section);
> > > >   }
> > > >   
> > > >   /* Reset all state within dwarf2out.c so that we can rerun the compiler
> > > > Index: early-lto-debug/gcc/debug.h
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/debug.h	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/debug.h	2017-05-16 13:10:49.774239353 +0200
> > > > *************** struct gcc_debug_hooks
> > > > *** 147,152 ****
> > > > --- 147,160 ----
> > > >     void (* imported_module_or_decl) (tree decl, tree name,
> > > >   				    tree context, bool child);
> > > >   
> > > > +   /* Return true if a DIE for the tree is available and return a symbol
> > > > +      and offset that can be used to refer to it externally.  */
> > > > +   bool (* die_ref_for_decl) (tree, const char **, unsigned HOST_WIDE_INT *);
> > > > + 
> > > > +   /* Early debug information for the tree is available at symbol plus
> > > > +      offset externally.  */
> > > > +   void (* register_external_die) (tree, const char *, unsigned HOST_WIDE_INT);
> > > > + 
> > > >     /* DECL is an inline function, whose body is present, but which is
> > > >        not being output at this point.  */
> > > >     void (* deferred_inline_function) (tree decl);
> > > > *************** extern void debug_nothing_tree_tree_tree
> > > > *** 210,215 ****
> > > > --- 218,227 ----
> > > >   extern bool debug_true_const_tree (const_tree);
> > > >   extern void debug_nothing_rtx_insn (rtx_insn *);
> > > >   extern void debug_nothing_rtx_code_label (rtx_code_label *);
> > > > + extern bool debug_false_tree_charstarstar_uhwistar (tree, const char **,
> > > > + 						    unsigned HOST_WIDE_INT *);
> > > > + extern void debug_nothing_tree_charstar_uhwi (tree, const char *,
> > > > + 					      unsigned HOST_WIDE_INT);
> > > >   
> > > >   /* Hooks for various debug formats.  */
> > > >   extern const struct gcc_debug_hooks do_nothing_debug_hooks;
> > > > Index: early-lto-debug/gcc/debug.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/debug.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/debug.c	2017-05-16 13:10:49.774239353 +0200
> > > > *************** const struct gcc_debug_hooks do_nothing_
> > > > *** 48,53 ****
> > > > --- 48,55 ----
> > > >     debug_nothing_tree,	         	 /* late_global_decl */
> > > >     debug_nothing_tree_int,		 /* type_decl */
> > > >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > > > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> > > >     debug_nothing_tree,		         /* deferred_inline_function */
> > > >     debug_nothing_tree,		         /* outlining_inline_function */
> > > >     debug_nothing_rtx_code_label,	         /* label */
> > > > *************** debug_nothing_tree_int (tree decl ATTRIB
> > > > *** 146,148 ****
> > > > --- 148,163 ----
> > > >   			int local ATTRIBUTE_UNUSED)
> > > >   {
> > > >   }
> > > > + 
> > > > + bool
> > > > + debug_false_tree_charstarstar_uhwistar (tree, const char **,
> > > > + 					unsigned HOST_WIDE_INT *)
> > > > + {
> > > > +   return false;
> > > > + }
> > > > + 
> > > > + void
> > > > + debug_nothing_tree_charstar_uhwi (tree, const char *,
> > > > + 				  unsigned HOST_WIDE_INT)
> > > > + {
> > > > + }
> > > > Index: early-lto-debug/gcc/dbxout.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/dbxout.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/dbxout.c	2017-05-16 13:10:49.778239419 +0200
> > > > *************** const struct gcc_debug_hooks dbx_debug_h
> > > > *** 372,377 ****
> > > > --- 372,379 ----
> > > >     dbxout_late_global_decl,		 /* late_global_decl */
> > > >     dbxout_type_decl,			 /* type_decl */
> > > >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > > > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> > > >     debug_nothing_tree,		         /* deferred_inline_function */
> > > >     debug_nothing_tree,		         /* outlining_inline_function */
> > > >     debug_nothing_rtx_code_label,	         /* label */
> > > > *************** const struct gcc_debug_hooks xcoff_debug
> > > > *** 412,417 ****
> > > > --- 414,421 ----
> > > >     dbxout_late_global_decl,		 /* late_global_decl */
> > > >     dbxout_type_decl,			 /* type_decl */
> > > >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > > > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > > +   debug_nothing_tree_charstar_uhwi,      /* register_external_die */
> > > >     debug_nothing_tree,		         /* deferred_inline_function */
> > > >     debug_nothing_tree,		         /* outlining_inline_function */
> > > >     debug_nothing_rtx_code_label,	         /* label */
> > > > Index: early-lto-debug/gcc/sdbout.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/sdbout.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/sdbout.c	2017-05-16 13:10:49.778239419 +0200
> > > > *************** const struct gcc_debug_hooks sdb_debug_h
> > > > *** 302,307 ****
> > > > --- 302,309 ----
> > > >     sdbout_late_global_decl,		 /* late_global_decl */
> > > >     sdbout_symbol,			 /* type_decl */
> > > >     debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
> > > > +   debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > > +   debug_nothing_tree_charstar_uhwi,	 /* register_external_die */
> > > >     debug_nothing_tree,		         /* deferred_inline_function */
> > > >     debug_nothing_tree,		         /* outlining_inline_function */
> > > >     sdbout_label,			         /* label */
> > > > Index: early-lto-debug/gcc/lto/lto.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/lto/lto.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/lto/lto.c	2017-05-16 13:10:49.778239419 +0200
> > > > *************** unify_scc (struct data_in *data_in, unsi
> > > > *** 1632,1637 ****
> > > > --- 1632,1640 ----
> > > >   	      free_node (scc->entries[i]);
> > > >   	    }
> > > >   
> > > > + 	  /* Drop DIE references.  */
> > > > + 	  dref_queue.truncate (0);
> > > > + 
> > > >   	  break;
> > > >   	}
> > > >   
> > > > *************** lto_read_decls (struct lto_file_decl_dat
> > > > *** 1707,1714 ****
> > > >   						     from);
> > > >   	  if (len == 1
> > > >   	      && (TREE_CODE (first) == IDENTIFIER_NODE
> > > > ! 		  || TREE_CODE (first) == INTEGER_CST
> > > > ! 		  || TREE_CODE (first) == TRANSLATION_UNIT_DECL))
> > > >   	    continue;
> > > >   
> > > >   	  /* Try to unify the SCC with already existing ones.  */
> > > > --- 1710,1716 ----
> > > >   						     from);
> > > >   	  if (len == 1
> > > >   	      && (TREE_CODE (first) == IDENTIFIER_NODE
> > > > ! 		  || TREE_CODE (first) == INTEGER_CST))
> > > >   	    continue;
> > > >   
> > > >   	  /* Try to unify the SCC with already existing ones.  */
> > > > *************** lto_read_decls (struct lto_file_decl_dat
> > > > *** 1747,1762 ****
> > > >   	      if (TREE_CODE (t) == INTEGER_CST
> > > >   		  && !TREE_OVERFLOW (t))
> > > >   		cache_integer_cst (t);
> > > > - 	      /* Register TYPE_DECLs with the debuginfo machinery.  */
> > > > - 	      if (!flag_wpa
> > > > - 		  && TREE_CODE (t) == TYPE_DECL)
> > > > - 		{
> > > > - 		  /* Dwarf2out needs location information.
> > > > - 		     TODO: Moving this out of the streamer loop may noticealy
> > > > - 		     improve ltrans linemap memory use.  */
> > > > - 		  data_in->location_cache.apply_location_cache ();
> > > > - 		  debug_hooks->type_decl (t, !DECL_FILE_SCOPE_P (t));
> > > > - 		}
> > > >   	      if (!flag_ltrans)
> > > >   		{
> > > >   		  /* Register variables and functions with the
> > > > --- 1749,1754 ----
> > > > *************** lto_read_decls (struct lto_file_decl_dat
> > > > *** 1772,1777 ****
> > > > --- 1764,1777 ----
> > > >   		    vec_safe_push (tree_with_vars, t);
> > > >   		}
> > > >   	    }
> > > > + 
> > > > + 	  /* Register DECLs with the debuginfo machinery.  */
> > > > + 	  while (!dref_queue.is_empty ())
> > > > + 	    {
> > > > + 	      dref_entry e = dref_queue.pop ();
> > > > + 	      debug_hooks->register_external_die (e.decl, e.sym, e.off);
> > > > + 	    }
> > > > + 
> > > >   	  if (seen_type)
> > > >   	    num_type_scc_trees += len;
> > > >   	}
> > > > *************** lto_section_with_id (const char *name, u
> > > > *** 1951,1957 ****
> > > >     if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
> > > >       return 0;
> > > >     s = strrchr (name, '.');
> > > > !   return s && sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
> > > >   }
> > > >   
> > > >   /* Create file_data of each sub file id */
> > > > --- 1951,1962 ----
> > > >     if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
> > > >       return 0;
> > > >     s = strrchr (name, '.');
> > > > !   if (!s)
> > > > !     return 0;
> > > > !   /* If the section is not suffixed with an ID return.  */
> > > > !   if ((size_t)(s - name) == strlen (section_name_prefix))
> > > > !     return 0;
> > > > !   return sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
> > > >   }
> > > >   
> > > >   /* Create file_data of each sub file id */
> > > > Index: early-lto-debug/gcc/lto-streamer-in.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/lto-streamer-in.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/lto-streamer-in.c	2017-05-16 13:10:49.858240736 +0200
> > > > *************** along with GCC; see the file COPYING3.
> > > > *** 41,46 ****
> > > > --- 41,47 ----
> > > >   #include "except.h"
> > > >   #include "cgraph.h"
> > > >   #include "cfgloop.h"
> > > > + #include "debug.h"
> > > >   
> > > >   
> > > >   struct freeing_string_slot_hasher : string_slot_hasher
> > > > *************** input_function (tree fn_decl, struct dat
> > > > *** 1038,1043 ****
> > > > --- 1039,1054 ----
> > > >     DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in);
> > > >     DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in);
> > > >   
> > > > +   /* Read debug args if available.  */
> > > > +   unsigned n_debugargs = streamer_read_uhwi (ib);
> > > > +   if (n_debugargs)
> > > > +     {
> > > > +       vec<tree, va_gc> **debugargs = decl_debug_args_insert (fn_decl);
> > > > +       vec_safe_grow (*debugargs, n_debugargs);
> > > > +       for (unsigned i = 0; i < n_debugargs; ++i)
> > > > + 	(**debugargs)[i] = stream_read_tree (ib, data_in);
> > > > +     }
> > > > + 
> > > >     /* Read the tree of lexical scopes for the function.  */
> > > >     DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
> > > >     unsigned block_leaf_count = streamer_read_uhwi (ib);
> > > > *************** lto_input_variable_constructor (struct l
> > > > *** 1318,1323 ****
> > > > --- 1329,1338 ----
> > > >   }
> > > >   
> > > >   
> > > > + /* Queue of acummulated decl -> DIE mappings.  Similar to locations those
> > > > +    are only applied to prevailing tree nodes during tree merging.  */
> > > > + vec<dref_entry> dref_queue;
> > > > + 
> > > >   /* Read the physical representation of a tree node EXPR from
> > > >      input block IB using the per-file context in DATA_IN.  */
> > > >   
> > > > *************** lto_read_tree_1 (struct lto_input_block
> > > > *** 1337,1342 ****
> > > > --- 1352,1374 ----
> > > >         && TREE_CODE (expr) != FUNCTION_DECL
> > > >         && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
> > > >       DECL_INITIAL (expr) = stream_read_tree (ib, data_in);
> > > > + 
> > > > +   /* Stream references to early generated DIEs.  Keep in sync with the
> > > > +      trees handled in dwarf2out_register_external_die.  */
> > > > +   if ((DECL_P (expr)
> > > > +        && TREE_CODE (expr) != FIELD_DECL
> > > > +        && TREE_CODE (expr) != DEBUG_EXPR_DECL
> > > > +        && TREE_CODE (expr) != TYPE_DECL)
> > > > +       || TREE_CODE (expr) == BLOCK)
> > > > +     {
> > > > +       const char *str = streamer_read_string (data_in, ib);
> > > > +       if (str)
> > > > + 	{
> > > > + 	  unsigned HOST_WIDE_INT off = streamer_read_uhwi (ib);
> > > > + 	  dref_entry e = { expr, str, off };
> > > > + 	  dref_queue.safe_push (e);
> > > > + 	}
> > > > +     }
> > > >   }
> > > >   
> > > >   /* Read the physical representation of a tree node with tag TAG from
> > > > *************** lto_input_tree (struct lto_input_block *
> > > > *** 1482,1487 ****
> > > > --- 1514,1526 ----
> > > >       {
> > > >         unsigned len, entry_len;
> > > >         lto_input_scc (ib, data_in, &len, &entry_len);
> > > > + 
> > > > +       /* Register DECLs with the debuginfo machinery.  */
> > > > +       while (!dref_queue.is_empty ())
> > > > + 	{
> > > > + 	  dref_entry e = dref_queue.pop ();
> > > > + 	  debug_hooks->register_external_die (e.decl, e.sym, e.off);
> > > > + 	}
> > > >       }
> > > >     return lto_input_tree_1 (ib, data_in, tag, 0);
> > > >   }
> > > > Index: early-lto-debug/gcc/lto-streamer-out.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/lto-streamer-out.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/lto-streamer-out.c	2017-05-16 13:10:49.858240736 +0200
> > > > *************** along with GCC; see the file COPYING3.
> > > > *** 40,45 ****
> > > > --- 40,46 ----
> > > >   #include "cfgloop.h"
> > > >   #include "builtins.h"
> > > >   #include "gomp-constants.h"
> > > > + #include "debug.h"
> > > >   
> > > >   
> > > >   static void lto_write_tree (struct output_block*, tree, bool);
> > > > *************** lto_write_tree_1 (struct output_block *o
> > > > *** 406,411 ****
> > > > --- 407,432 ----
> > > >   			 (ob->decl_state->symtab_node_encoder, expr);
> > > >         stream_write_tree (ob, initial, ref_p);
> > > >       }
> > > > + 
> > > > +   /* Stream references to early generated DIEs.  Keep in sync with the
> > > > +      trees handled in dwarf2out_die_ref_for_decl.  */
> > > > +   if ((DECL_P (expr)
> > > > +        && TREE_CODE (expr) != FIELD_DECL
> > > > +        && TREE_CODE (expr) != DEBUG_EXPR_DECL
> > > > +        && TREE_CODE (expr) != TYPE_DECL)
> > > > +       || TREE_CODE (expr) == BLOCK)
> > > > +     {
> > > > +       const char *sym;
> > > > +       unsigned HOST_WIDE_INT off;
> > > > +       if (debug_info_level > DINFO_LEVEL_NONE
> > > > + 	  && debug_hooks->die_ref_for_decl (expr, &sym, &off))
> > > > + 	{
> > > > + 	  streamer_write_string (ob, ob->main_stream, sym, true);
> > > > + 	  streamer_write_uhwi (ob, off);
> > > > + 	}
> > > > +       else
> > > > + 	streamer_write_string (ob, ob->main_stream, NULL, true);
> > > > +     }
> > > >   }
> > > >   
> > > >   /* Write a physical representation of tree node EXPR to output block
> > > > *************** DFS::DFS_write_tree_body (struct output_
> > > > *** 745,751 ****
> > > >   	;
> > > >         else
> > > >   	DFS_follow_tree_edge (DECL_NAME (expr));
> > > > !       DFS_follow_tree_edge (DECL_CONTEXT (expr));
> > > >       }
> > > >   
> > > >     if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> > > > --- 766,776 ----
> > > >   	;
> > > >         else
> > > >   	DFS_follow_tree_edge (DECL_NAME (expr));
> > > > !       if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
> > > > ! 	  && ! DECL_CONTEXT (expr))
> > > > ! 	DFS_follow_tree_edge ((*all_translation_units)[0]);
> > > > !       else
> > > > ! 	DFS_follow_tree_edge (DECL_CONTEXT (expr));
> > > >       }
> > > >   
> > > >     if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> > > > *************** DFS::DFS_write_tree_body (struct output_
> > > > *** 765,770 ****
> > > > --- 790,796 ----
> > > >   	 declarations which should be eliminated by decl merging. Be sure none
> > > >   	 leaks to this point.  */
> > > >         gcc_assert (DECL_ABSTRACT_ORIGIN (expr) != error_mark_node);
> > > > +       DFS_follow_tree_edge (DECL_ABSTRACT_ORIGIN (expr));
> > > >   
> > > >         if ((VAR_P (expr)
> > > >   	   || TREE_CODE (expr) == PARM_DECL)
> > > > *************** output_function (struct cgraph_node *nod
> > > > *** 2061,2066 ****
> > > > --- 2087,2103 ----
> > > >     stream_write_tree (ob, DECL_RESULT (function), true);
> > > >     streamer_write_chain (ob, DECL_ARGUMENTS (function), true);
> > > >   
> > > > +   /* Output debug args if available. */
> > > > +   vec<tree, va_gc> **debugargs = decl_debug_args_lookup (function);
> > > > +   if (! debugargs)
> > > > +     streamer_write_uhwi (ob, 0);
> > > > +   else
> > > > +     {
> > > > +       streamer_write_uhwi (ob, (*debugargs)->length ());
> > > > +       for (unsigned i = 0; i < (*debugargs)->length (); ++i)
> > > > + 	stream_write_tree (ob, (**debugargs)[i], true);
> > > > +     }
> > > > + 
> > > >     /* Output DECL_INITIAL for the function, which contains the tree of
> > > >        lexical scopes.  */
> > > >     stream_write_tree (ob, DECL_INITIAL (function), true);
> > > > Index: early-lto-debug/gcc/lto-streamer.h
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/lto-streamer.h	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/lto-streamer.h	2017-05-16 13:10:49.858240736 +0200
> > > > *************** DEFINE_DECL_STREAM_FUNCS (TYPE_DECL, typ
> > > > *** 1212,1215 ****
> > > > --- 1212,1225 ----
> > > >   DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl)
> > > >   DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl)
> > > >   
> > > > + /* Entry for the delayed registering of decl -> DIE references.  */
> > > > + struct dref_entry {
> > > > +     tree decl;
> > > > +     const char *sym;
> > > > +     unsigned HOST_WIDE_INT off;
> > > > + };
> > > > + 
> > > > + extern vec<dref_entry> dref_queue;
> > > > + 
> > > > + 
> > > >   #endif /* GCC_LTO_STREAMER_H  */
> > > > Index: early-lto-debug/gcc/lto-wrapper.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/lto-wrapper.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/lto-wrapper.c	2017-05-16 13:10:49.858240736 +0200
> > > > *************** static char **output_names;
> > > > *** 70,75 ****
> > > > --- 70,76 ----
> > > >   static char **offload_names;
> > > >   static char *offload_objects_file_name;
> > > >   static char *makefile;
> > > > + static char *debug_obj;
> > > >   
> > > >   const char tool_name[] = "lto-wrapper";
> > > >   
> > > > *************** tool_cleanup (bool)
> > > > *** 88,93 ****
> > > > --- 89,96 ----
> > > >       maybe_unlink (offload_objects_file_name);
> > > >     if (makefile)
> > > >       maybe_unlink (makefile);
> > > > +   if (debug_obj)
> > > > +     maybe_unlink (debug_obj);
> > > >     for (i = 0; i < nr; ++i)
> > > >       {
> > > >         maybe_unlink (input_names[i]);
> > > > *************** find_and_merge_options (int fd, off_t fi
> > > > *** 938,943 ****
> > > > --- 941,1007 ----
> > > >     return true;
> > > >   }
> > > >   
> > > > + /* Copy early debug info sections from INFILE to a new file whose name
> > > > +    is returned.  Return NULL on error.  */
> > > > + 
> > > > + const char *
> > > > + debug_objcopy (const char *infile)
> > > > + {
> > > > +   const char *outfile;
> > > > +   const char *errmsg;
> > > > +   int err;
> > > > + 
> > > > +   const char *p;
> > > > +   off_t inoff = 0;
> > > > +   long loffset;
> > > > +   int consumed;
> > > > +   if ((p = strrchr (infile, '@'))
> > > > +       && p != infile
> > > > +       && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
> > > > +       && strlen (p) == (unsigned int) consumed)
> > > > +     {
> > > > +       char *fname = xstrdup (infile);
> > > > +       fname[p - infile] = '\0';
> > > > +       infile = fname;
> > > > +       inoff = (off_t) loffset;
> > > > +     }
> > > > +   int infd = open (infile, O_RDONLY);
> > > > +   if (infd == -1)
> > > > +     return NULL;
> > > > +   simple_object_read *inobj = simple_object_start_read (infd, inoff,
> > > > + 							"__GNU_LTO",
> > > > + 							&errmsg, &err);
> > > > +   if (!inobj)
> > > > +     return NULL;
> > > > + 
> > > > +   off_t off, len;
> > > > +   if (simple_object_find_section (inobj, ".gnu.debuglto_.debug_info",
> > > > + 				  &off, &len, &errmsg, &err) != 1)
> > > > +     {
> > > > +       if (errmsg)
> > > > + 	fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
> > > > + 
> > > > +       simple_object_release_read (inobj);
> > > > +       close (infd);
> > > > +       return NULL;
> > > > +     }
> > > > + 
> > > > +   outfile = make_temp_file ("debugobjtem");
> > > > +   errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err);
> > > > +   if (errmsg)
> > > > +     {
> > > > +       unlink_if_ordinary (outfile);
> > > > +       fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
> > > > +     }
> > > > + 
> > > > +   simple_object_release_read (inobj);
> > > > +   close (infd);
> > > > + 
> > > > +   return outfile;
> > > > + }
> > > > + 
> > > > + 
> > > > + 
> > > >   /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
> > > >   
> > > >   static void
> > > > *************** run_gcc (unsigned argc, char *argv[])
> > > > *** 962,969 ****
> > > >     int new_head_argc;
> > > >     bool have_lto = false;
> > > >     bool have_offload = false;
> > > > !   unsigned lto_argc = 0;
> > > > !   char **lto_argv;
> > > >   
> > > >     /* Get the driver and options.  */
> > > >     collect_gcc = getenv ("COLLECT_GCC");
> > > > --- 1026,1035 ----
> > > >     int new_head_argc;
> > > >     bool have_lto = false;
> > > >     bool have_offload = false;
> > > > !   unsigned lto_argc = 0, ltoobj_argc = 0;
> > > > !   char **lto_argv, **ltoobj_argv;
> > > > !   bool skip_debug = false;
> > > > !   unsigned n_debugobj;
> > > >   
> > > >     /* Get the driver and options.  */
> > > >     collect_gcc = getenv ("COLLECT_GCC");
> > > > *************** run_gcc (unsigned argc, char *argv[])
> > > > *** 982,987 ****
> > > > --- 1048,1054 ----
> > > >     /* Allocate array for input object files with LTO IL,
> > > >        and for possible preceding arguments.  */
> > > >     lto_argv = XNEWVEC (char *, argc);
> > > > +   ltoobj_argv = XNEWVEC (char *, argc);
> > > >   
> > > >     /* Look at saved options in the IL files.  */
> > > >     for (i = 1; i < argc; ++i)
> > > > *************** run_gcc (unsigned argc, char *argv[])
> > > > *** 1024,1030 ****
> > > >   				  collect_gcc))
> > > >   	{
> > > >   	  have_lto = true;
> > > > ! 	  lto_argv[lto_argc++] = argv[i];
> > > >   	}
> > > >         close (fd);
> > > >       }
> > > > --- 1091,1097 ----
> > > >   				  collect_gcc))
> > > >   	{
> > > >   	  have_lto = true;
> > > > ! 	  ltoobj_argv[ltoobj_argc++] = argv[i];
> > > >   	}
> > > >         close (fd);
> > > >       }
> > > > *************** run_gcc (unsigned argc, char *argv[])
> > > > *** 1085,1090 ****
> > > > --- 1152,1168 ----
> > > >   	}
> > > >       }
> > > >   
> > > > +   /* Output lto-wrapper invocation command.  */
> > > > +   if (verbose)
> > > > +     {
> > > > +       for (i = 0; i < argc; ++i)
> > > > + 	{
> > > > + 	  fputs (argv[i], stderr);
> > > > + 	  fputc (' ', stderr);
> > > > + 	}
> > > > +       fputc ('\n', stderr);
> > > > +     }
> > > > + 
> > > >     if (no_partition)
> > > >       {
> > > >         lto_mode = LTO_MODE_LTO;
> > > > *************** cont1:
> > > > *** 1274,1291 ****
> > > >           obstack_ptr_grow (&argv_obstack, "-fwpa");
> > > >       }
> > > >   
> > > > !   /* Append the input objects and possible preceding arguments.  */
> > > >     for (i = 0; i < lto_argc; ++i)
> > > >       obstack_ptr_grow (&argv_obstack, lto_argv[i]);
> > > >     obstack_ptr_grow (&argv_obstack, NULL);
> > > >   
> > > >     new_argv = XOBFINISH (&argv_obstack, const char **);
> > > >     argv_ptr = &new_argv[new_head_argc];
> > > >     fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
> > > >   
> > > >     if (lto_mode == LTO_MODE_LTO)
> > > >       {
> > > >         printf ("%s\n", flto_out);
> > > >         free (flto_out);
> > > >         flto_out = NULL;
> > > >       }
> > > > --- 1352,1456 ----
> > > >           obstack_ptr_grow (&argv_obstack, "-fwpa");
> > > >       }
> > > >   
> > > > !   /* Append input arguments.  */
> > > >     for (i = 0; i < lto_argc; ++i)
> > > >       obstack_ptr_grow (&argv_obstack, lto_argv[i]);
> > > > +   /* Append the input objects.  */
> > > > +   for (i = 0; i < ltoobj_argc; ++i)
> > > > +     obstack_ptr_grow (&argv_obstack, ltoobj_argv[i]);
> > > >     obstack_ptr_grow (&argv_obstack, NULL);
> > > >   
> > > >     new_argv = XOBFINISH (&argv_obstack, const char **);
> > > >     argv_ptr = &new_argv[new_head_argc];
> > > >     fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
> > > >   
> > > > +   /* Handle early generated debug information.  At compile-time
> > > > +      we output early DWARF debug info into .gnu.debuglto_ prefixed
> > > > +      sections.  LTRANS object DWARF debug info refers to that.
> > > > +      So we need to transfer the .gnu.debuglto_ sections to the final
> > > > +      link.  Ideally the linker plugin interface would allow us to
> > > > +      not claim those sections and instruct the linker to keep
> > > > +      them, renaming them in the process.  For now we extract and
> > > > +      rename those sections via a simple-object interface to produce
> > > > +      regular objects containing only the early debug info.  We
> > > > +      then partially link those to a single early debug info object
> > > > +      and pass that as additional output back to the linker plugin.  */
> > > > + 
> > > > +   /* Prepare the partial link to gather the compile-time generated
> > > > +      debug-info into a single input for the final link.  */
> > > > +   debug_obj = make_temp_file ("debugobj");
> > > > +   obstack_ptr_grow (&argv_obstack, collect_gcc);
> > > > +   for (i = 1; i < decoded_options_count; ++i)
> > > > +     {
> > > > +       /* Retain linker choice and -B.  */
> > > > +       if (decoded_options[i].opt_index == OPT_B
> > > > + 	  || decoded_options[i].opt_index == OPT_fuse_ld_bfd
> > > > + 	  || decoded_options[i].opt_index == OPT_fuse_ld_gold)
> > > > + 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
> > > > +       /* Retain all target options, this preserves -m32 for example.  */
> > > > +       if (cl_options[decoded_options[i].opt_index].flags & CL_TARGET)
> > > > + 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
> > > > +       /* Recognize -g0.  */
> > > > +       if (decoded_options[i].opt_index == OPT_g
> > > > + 	  && strcmp (decoded_options[i].arg, "0") == 0)
> > > > + 	skip_debug = true;
> > > > +     }
> > > > +   obstack_ptr_grow (&argv_obstack, "-r");
> > > > +   obstack_ptr_grow (&argv_obstack, "-nostdlib");
> > > > +   obstack_ptr_grow (&argv_obstack, "-o");
> > > > +   obstack_ptr_grow (&argv_obstack, debug_obj);
> > > > + 
> > > > +   /* Copy the early generated debug info from the objects to temporary
> > > > +      files and append those to the partial link commandline.  */
> > > > +   n_debugobj = 0;
> > > > +   if (! skip_debug)
> > > > +     for (i = 0; i < ltoobj_argc; ++i)
> > > > +       {
> > > > + 	const char *tem;
> > > > + 	if ((tem = debug_objcopy (ltoobj_argv[i])))
> > > > + 	  {
> > > > + 	    obstack_ptr_grow (&argv_obstack, tem);
> > > > + 	    n_debugobj++;
> > > > + 	  }
> > > > +       }
> > > > + 
> > > > +   /* Link them all into a single object.  Ideally this would reduce
> > > > +      disk space usage mainly due to .debug_str merging but unfortunately
> > > > +      GNU ld doesn't perform this with -r.  */
> > > > +   if (n_debugobj)
> > > > +     {
> > > > +       obstack_ptr_grow (&argv_obstack, NULL);
> > > > +       const char **debug_link_argv = XOBFINISH (&argv_obstack, const char **);
> > > > +       fork_execute (debug_link_argv[0],
> > > > + 		    CONST_CAST (char **, debug_link_argv), false);
> > > > + 
> > > > +       /* And dispose the temporaries.  */
> > > > +       for (i = 0; debug_link_argv[i]; ++i)
> > > > + 	;
> > > > +       for (--i; i > 0; --i)
> > > > + 	{
> > > > + 	  if (strcmp (debug_link_argv[i], debug_obj) == 0)
> > > > + 	    break;
> > > > + 	  maybe_unlink (debug_link_argv[i]);
> > > > + 	}
> > > > +     }
> > > > +   else
> > > > +     {
> > > > +       unlink_if_ordinary (debug_obj);
> > > > +       free (debug_obj);
> > > > +       debug_obj = NULL;
> > > > +       skip_debug = true;
> > > > +     }
> > > > + 
> > > >     if (lto_mode == LTO_MODE_LTO)
> > > >       {
> > > >         printf ("%s\n", flto_out);
> > > > +       if (!skip_debug)
> > > > + 	{
> > > > + 	  printf ("%s\n", debug_obj);
> > > > + 	  free (debug_obj);
> > > > + 	  debug_obj = NULL;
> > > > + 	}
> > > >         free (flto_out);
> > > >         flto_out = NULL;
> > > >       }
> > > > *************** cont:
> > > > *** 1434,1439 ****
> > > > --- 1599,1610 ----
> > > >   	  for (i = 0; i < nr; ++i)
> > > >   	    maybe_unlink (input_names[i]);
> > > >   	}
> > > > +       if (!skip_debug)
> > > > + 	{
> > > > + 	  printf ("%s\n", debug_obj);
> > > > + 	  free (debug_obj);
> > > > + 	  debug_obj = NULL;
> > > > + 	}
> > > >         for (i = 0; i < nr; ++i)
> > > >   	{
> > > >   	  fputs (output_names[i], stdout);
> > > > Index: early-lto-debug/gcc/tree-streamer-in.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/tree-streamer-in.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/tree-streamer-in.c	2017-05-16 13:10:49.862240801 +0200
> > > > *************** lto_input_ts_decl_common_tree_pointers (
> > > > *** 688,697 ****
> > > >     DECL_SIZE (expr) = stream_read_tree (ib, data_in);
> > > >     DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
> > > >     DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
> > > > ! 
> > > > !   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
> > > > !      for early inlining so drop it on the floor instead of ICEing in
> > > > !      dwarf2out.c.  */
> > > >   
> > > >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> > > >         && DECL_HAS_VALUE_EXPR_P (expr))
> > > > --- 688,694 ----
> > > >     DECL_SIZE (expr) = stream_read_tree (ib, data_in);
> > > >     DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
> > > >     DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
> > > > !   DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
> > > >   
> > > >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> > > >         && DECL_HAS_VALUE_EXPR_P (expr))
> > > > Index: early-lto-debug/gcc/tree-streamer-out.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/tree-streamer-out.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/tree-streamer-out.c	2017-05-16 13:10:49.862240801 +0200
> > > > *************** write_ts_decl_minimal_tree_pointers (str
> > > > *** 566,572 ****
> > > >       stream_write_tree (ob, NULL_TREE, ref_p);
> > > >     else
> > > >       stream_write_tree (ob, DECL_NAME (expr), ref_p);
> > > > !   stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
> > > >   }
> > > >   
> > > >   
> > > > --- 566,576 ----
> > > >       stream_write_tree (ob, NULL_TREE, ref_p);
> > > >     else
> > > >       stream_write_tree (ob, DECL_NAME (expr), ref_p);
> > > > !   if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
> > > > !       && ! DECL_CONTEXT (expr))
> > > > !     stream_write_tree (ob, (*all_translation_units)[0], ref_p);
> > > > !   else
> > > > !     stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
> > > >   }
> > > >   
> > > >   
> > > > *************** write_ts_decl_common_tree_pointers (stru
> > > > *** 585,594 ****
> > > >        special handling in LTO, it must be handled by streamer hooks.  */
> > > >   
> > > >     stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
> > > > ! 
> > > > !   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
> > > > !      for early inlining so drop it on the floor instead of ICEing in
> > > > !      dwarf2out.c.  */
> > > >   
> > > >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> > > >         && DECL_HAS_VALUE_EXPR_P (expr))
> > > > --- 589,595 ----
> > > >        special handling in LTO, it must be handled by streamer hooks.  */
> > > >   
> > > >     stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
> > > > !   stream_write_tree (ob, DECL_ABSTRACT_ORIGIN (expr), ref_p);
> > > >   
> > > >     if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
> > > >         && DECL_HAS_VALUE_EXPR_P (expr))
> > > > Index: early-lto-debug/gcc/config/darwin.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/config/darwin.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/config/darwin.c	2017-05-16 13:10:49.862240801 +0200
> > > > *************** darwin_asm_lto_end (void)
> > > > *** 1959,1965 ****
> > > >   }
> > > >   
> > > >   static void
> > > > ! darwin_asm_dwarf_section (const char *name, unsigned int flags, tree decl);
> > > >   
> > > >   /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
> > > >   
> > > > --- 1959,1966 ----
> > > >   }
> > > >   
> > > >   static void
> > > > ! darwin_asm_dwarf_section (const char *name, unsigned int flags,
> > > > ! 			  tree decl, bool is_for_lto);
> > > >   
> > > >   /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
> > > >   
> > > > *************** darwin_asm_named_section (const char *na
> > > > *** 2001,2007 ****
> > > >         vec_safe_push (lto_section_names, e);
> > > >      }
> > > >     else if (strncmp (name, "__DWARF,", 8) == 0)
> > > > !     darwin_asm_dwarf_section (name, flags, decl);
> > > >     else
> > > >       fprintf (asm_out_file, "\t.section %s\n", name);
> > > >   }
> > > > --- 2002,2010 ----
> > > >         vec_safe_push (lto_section_names, e);
> > > >      }
> > > >     else if (strncmp (name, "__DWARF,", 8) == 0)
> > > > !     darwin_asm_dwarf_section (name, flags, decl, false);
> > > > !   else if (strncmp (name, "__GNU_DWARF_LTO,", 16) == 0)
> > > > !     darwin_asm_dwarf_section (name, flags, decl, true);
> > > >     else
> > > >       fprintf (asm_out_file, "\t.section %s\n", name);
> > > >   }
> > > > *************** static GTY (()) vec<dwarf_sect_used_entr
> > > > *** 2783,2801 ****
> > > >   
> > > >   static void
> > > >   darwin_asm_dwarf_section (const char *name, unsigned int flags,
> > > > ! 			  tree ARG_UNUSED (decl))
> > > >   {
> > > >     unsigned i;
> > > > !   int namelen;
> > > > !   const char * sname;
> > > >     dwarf_sect_used_entry *ref;
> > > >     bool found = false;
> > > > !   gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
> > > > ! 		    == (SECTION_DEBUG | SECTION_NAMED));
> > > > !   /* We know that the name starts with __DWARF,  */
> > > > !   sname = name + 8;
> > > > !   namelen = strchr (sname, ',') - sname;
> > > > !   gcc_assert (namelen);
> > > >     if (dwarf_sect_names_table == NULL)
> > > >       vec_alloc (dwarf_sect_names_table, 16);
> > > >     else
> > > > --- 2786,2822 ----
> > > >   
> > > >   static void
> > > >   darwin_asm_dwarf_section (const char *name, unsigned int flags,
> > > > ! 			  tree ARG_UNUSED (decl), bool is_for_lto)
> > > >   {
> > > >     unsigned i;
> > > > !   int namelen, extra = 0;
> > > > !   const char *sect, *lto_add = "";
> > > > !   char sname[64];
> > > >     dwarf_sect_used_entry *ref;
> > > >     bool found = false;
> > > > ! 
> > > > !   gcc_checking_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
> > > > ! 			== (SECTION_DEBUG | SECTION_NAMED));
> > > > ! 
> > > > !   /* We know that the name starts with __DWARF, or __GNU_DAWRF_LTO  */
> > > > !   sect = strchr (name, ',') + 1;
> > > > !   namelen = strchr (sect, ',') - sect;
> > > > !   gcc_checking_assert (namelen);
> > > > ! 
> > > > !   /* The section switch is output as written...  */
> > > > !   fprintf (asm_out_file, "\t.section %s\n", name);
> > > > ! 
> > > > !   /* ... but the string we keep to make section start labels needs
> > > > !      adjustment for lto cases.  */
> > > > !   if (is_for_lto)
> > > > !     {
> > > > !       lto_add = "_lto";
> > > > !       extra = 4;
> > > > !     }
> > > > ! 
> > > > !   snprintf (sname, 64, "%.*s%.*s", namelen, sect, extra, lto_add);
> > > > !   namelen += extra;
> > > > ! 
> > > >     if (dwarf_sect_names_table == NULL)
> > > >       vec_alloc (dwarf_sect_names_table, 16);
> > > >     else
> > > > *************** darwin_asm_dwarf_section (const char *na
> > > > *** 2813,2819 ****
> > > >   	  }
> > > >         }
> > > >   
> > > > -   fprintf (asm_out_file, "\t.section %s\n", name);
> > > >     if (!found)
> > > >       {
> > > >         dwarf_sect_used_entry e;
> > > > --- 2834,2839 ----
> > > > *************** darwin_asm_output_dwarf_offset (FILE *fi
> > > > *** 2866,2879 ****
> > > >   				HOST_WIDE_INT offset, section *base)
> > > >   {
> > > >     char sname[64];
> > > > !   int namelen;
> > > >   
> > > > !   gcc_assert (base->common.flags & SECTION_NAMED);
> > > > !   gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
> > > > !   gcc_assert (strchr (base->named.name + 8, ','));
> > > > ! 
> > > > !   namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
> > > > !   sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
> > > >     darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
> > > >   }
> > > >   
> > > > --- 2886,2909 ----
> > > >   				HOST_WIDE_INT offset, section *base)
> > > >   {
> > > >     char sname[64];
> > > > !   int namelen, extra = 0;
> > > > !   bool is_for_lto;
> > > > !   const char *lto_add = "";
> > > > ! 
> > > > !   gcc_checking_assert (base->common.flags & SECTION_NAMED);
> > > > !   is_for_lto = strncmp (base->named.name, "__GNU_DWARF_LTO,", 16) == 0;
> > > > !   gcc_checking_assert (is_for_lto
> > > > ! 		       || strncmp (base->named.name, "__DWARF,", 8) == 0);
> > > > !   const char *name = strchr (base->named.name, ',') + 1;
> > > > !   gcc_checking_assert (name);
> > > >   
> > > > !   namelen = strchr (name, ',') - (name);
> > > > !   if (is_for_lto)
> > > > !     {
> > > > !       lto_add = "_lto";
> > > > !       extra = 4;
> > > > !     }
> > > > !   snprintf (sname, 64, "*Lsection%.*s%.*s", namelen, name, extra, lto_add);
> > > >     darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
> > > >   }
> > > >   
> > > > Index: early-lto-debug/gcc/config/darwin.h
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/config/darwin.h	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/config/darwin.h	2017-05-16 13:10:49.866240867 +0200
> > > > *************** extern GTY(()) int darwin_ms_struct;
> > > > *** 445,451 ****
> > > >   #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
> > > >   #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
> > > >   #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
> > > > ! #define DEBUG_MACRO_SECTION    "__DWARF,__debug_macro,regular,debug"
> > > >   
> > > >   #define TARGET_WANT_DEBUG_PUB_SECTIONS true
> > > >   
> > > > --- 445,458 ----
> > > >   #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
> > > >   #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
> > > >   #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
> > > > ! #define DEBUG_MACRO_SECTION     "__DWARF,__debug_macro,regular,debug"
> > > > ! 
> > > > ! #define DEBUG_LTO_INFO_SECTION	  "__GNU_DWARF_LTO,__debug_info,regular,debug"
> > > > ! #define DEBUG_LTO_ABBREV_SECTION  "__GNU_DWARF_LTO,__debug_abbrev,regular,debug"
> > > > ! #define DEBUG_LTO_MACINFO_SECTION "__GNU_DWARF_LTO,__debug_macinfo,regular,debug"
> > > > ! #define DEBUG_LTO_LINE_SECTION	  "__GNU_DWARF_LTO,__debug_line,regular,debug"
> > > > ! #define DEBUG_LTO_STR_SECTION	  "__GNU_DWARF_LTO,__debug_str,regular,debug"
> > > > ! #define DEBUG_LTO_MACRO_SECTION   "__GNU_DWARF_LTO,__debug_macro,regular,debug"
> > > >   
> > > >   #define TARGET_WANT_DEBUG_PUB_SECTIONS true
> > > >   
> > > > Index: early-lto-debug/gcc/vmsdbgout.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/vmsdbgout.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/vmsdbgout.c	2017-05-16 13:10:49.866240867 +0200
> > > > *************** const struct gcc_debug_hooks vmsdbg_debu
> > > > *** 198,203 ****
> > > > --- 198,205 ----
> > > >      vmsdbgout_late_global_decl,
> > > >      vmsdbgout_type_decl,		  /* type_decl */
> > > >      debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
> > > > +    debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
> > > > +    debug_nothing_tree_charstar_uhwi, /* register_external_die */
> > > >      debug_nothing_tree,		  /* deferred_inline_function */
> > > >      vmsdbgout_abstract_function,
> > > >      debug_nothing_rtx_code_label,  /* label */
> > > > Index: early-lto-debug/gcc/tree.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/tree.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/tree.c	2017-05-16 13:10:49.870240933 +0200
> > > > *************** free_lang_data (void)
> > > > *** 5974,5979 ****
> > > > --- 5974,5983 ----
> > > >         || (!flag_generate_lto && !flag_generate_offload))
> > > >       return 0;
> > > >   
> > > > +   /* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one.  */
> > > > +   if (vec_safe_is_empty (all_translation_units))
> > > > +     build_translation_unit_decl (NULL_TREE);
> > > > + 
> > > >     /* Allocate and assign alias sets to the standard integer types
> > > >        while the slots are still in the way the frontends generated them.  */
> > > >     for (i = 0; i < itk_none; ++i)
> > > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-05-16 13:10:49.870240933 +0200
> > > > *************** int main() {
> > > > *** 23,28 ****
> > > >   }
> > > >   
> > > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
> > > >   /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
> > > >   /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
> > > > --- 23,28 ----
> > > >   }
> > > >   
> > > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
> > > >   /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
> > > >   /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
> > > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-05-16 13:10:49.870240933 +0200
> > > > *************** int main(int argc, char **argv) {
> > > > *** 24,31 ****
> > > >   }
> > > >   
> > > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > --- 24,31 ----
> > > >   }
> > > >   
> > > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-05-16 13:10:49.870240933 +0200
> > > > *************** main ()
> > > > *** 39,43 ****
> > > >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> > > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > > > --- 39,43 ----
> > > >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> > > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-05-16 13:10:49.870240933 +0200
> > > > *************** main ()
> > > > *** 39,43 ****
> > > >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> > > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > > > --- 39,43 ----
> > > >   /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
> > > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-05-16 13:10:49.870240933 +0200
> > > > *************** int main()
> > > > *** 18,22 ****
> > > >   
> > > >   /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
> > > >   /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > --- 18,22 ----
> > > >   
> > > >   /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
> > > >   /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-05-16 13:10:49.874240999 +0200
> > > > *************** int main() {
> > > > *** 18,23 ****
> > > >   }
> > > >   
> > > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
> > > >   /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
> > > > --- 18,23 ----
> > > >   }
> > > >   
> > > >   /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
> > > >   /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
> > > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-05-16 13:10:49.874240999 +0200
> > > > *************** int main(int argc, char **argv) {
> > > > *** 14,21 ****
> > > >   
> > > >   /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > --- 14,21 ----
> > > >   
> > > >   /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-05-16 13:10:49.874240999 +0200
> > > > *************** int main() {
> > > > *** 12,22 ****
> > > >   /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
> > > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > --- 12,22 ----
> > > >   /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
> > > >   /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
> > > >   /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > ! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
> > > > Index: early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-05-16 13:10:49.874240999 +0200
> > > > *************** int main() {
> > > > *** 38,44 ****
> > > >   // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
> > > >   // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
> > > >   // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
> > > > ! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" }
> > > >   // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
> > > >   // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
> > > >   // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
> > > > --- 38,44 ----
> > > >   // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
> > > >   // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
> > > >   // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
> > > > ! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" }
> > > >   // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
> > > >   // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
> > > >   // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
> > > > Index: early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp
> > > > ===================================================================
> > > > *** early-lto-debug.orig/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-05-16 13:10:47.554202813 +0200
> > > > --- early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-05-16 13:10:49.874240999 +0200
> > > > ***************
> > > > *** 15,20 ****
> > > > --- 15,21 ----
> > > >   # <http://www.gnu.org/licenses/>.
> > > >   
> > > >   load_lib gdb-test.exp
> > > > + load_lib target-supports.exp
> > > >   
> > > >   dg-init
> > > >   v3-build_support
> > > > *************** global PCH_CXXFLAGS
> > > > *** 46,51 ****
> > > > --- 47,60 ----
> > > >   gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
> > > >     "" "$DEFAULT_CXXFLAGS $PCH_CXXFLAGS"
> > > >   
> > > > + if { [check_effective_target_lto] } {
> > > > +   append cxxflags " -flto"
> > > > +   # work around sourceware.org 20882
> > > > +   regsub {^(.*)-Wl,--gc-sections(.*)$} $cxxldflags {\1\2} cxxldflags
> > > > +   gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
> > > > +     "" "$DEFAULT_CXXFLAGS -flto $PCH_CXXFLAGS"
> > > > + }
> > > > + 
> > > >   if [info exists guality_gdb_name] {
> > > >       unsetenv GUALITY_GDB_NAME
> > > >   }
> > > > Index: early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90
> > > > ===================================================================
> > > > *** /dev/null	1970-01-01 00:00:00.000000000 +0000
> > > > --- early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90	2017-05-18 09:39:31.394914888 +0200
> > > > ***************
> > > > *** 0 ****
> > > > --- 1,54 ----
> > > > + ! { dg-do run }
> > > > + ! { dg-require-effective-target lto }
> > > > + ! { dg-options "-fno-automatic -flto -g" }
> > > > + !
> > > > + ! PR fortran/55733
> > > > + !
> > > > + ! Check that -fno-automatic makes the local variable SAVEd
> > > > + ! Check that -flto -g works
> > > > + !
> > > > + 
> > > > + ! Scalar allocatable
> > > > + subroutine foo(i)
> > > > +   integer :: i
> > > > +   integer, allocatable :: j
> > > > +   if (i == 1) j = 42
> > > > +   if (.not. allocated (j)) call abort ()
> > > > +   if (j /= 42) call abort ()
> > > > + end
> > > > + 
> > > > + ! Deferred-length string scalar
> > > > + subroutine bar()
> > > > +   logical, save :: first = .true.
> > > > +   character(len=:), allocatable :: str
> > > > +   if (first) then
> > > > +     first = .false.
> > > > +     if (allocated (str)) call abort ()
> > > > +     str = "ABCDEF"
> > > > +   end if
> > > > +   if (.not. allocated (str)) call abort ()
> > > > +   if (len (str) /= 6) call abort ()
> > > > +   if (str(1:6) /= "ABCDEF") call abort ()
> > > > + end subroutine bar
> > > > + 
> > > > + ! Deferred-length string array
> > > > + subroutine bar_array()
> > > > +   logical, save :: first = .true.
> > > > +   character(len=:), allocatable :: str
> > > > +   if (first) then
> > > > +     first = .false.
> > > > +     if (allocated (str)) call abort ()
> > > > +     str = "ABCDEF"
> > > > +   end if
> > > > +   if (.not. allocated (str)) call abort ()
> > > > +   if (len (str) /= 6) call abort ()
> > > > +   if (str(1:6) /= "ABCDEF") call abort ()
> > > > + end subroutine bar_array
> > > > + 
> > > > + call foo(1)
> > > > + call foo(2)
> > > > + call bar()
> > > > + call bar_array()
> > > > + call bar()
> > > > + call bar_array()
> > > > + end
> > > > Index: early-lto-debug/gcc/config/i386/i386.c
> > > > ===================================================================
> > > > *** early-lto-debug.orig/gcc/config/i386/i386.c	2017-05-15 10:57:19.923567540 +0200
> > > > --- early-lto-debug/gcc/config/i386/i386.c	2017-05-19 11:27:19.565373271 +0200
> > > > *************** make_resolver_func (const tree default_d
> > > > *** 33840,33846 ****
> > > >     DECL_NAME (decl) = decl_name;
> > > >     TREE_USED (decl) = 1;
> > > >     DECL_ARTIFICIAL (decl) = 1;
> > > > !   DECL_IGNORED_P (decl) = 0;
> > > >     /* IFUNC resolvers have to be externally visible.  */
> > > >     TREE_PUBLIC (decl) = 1;
> > > >     DECL_UNINLINABLE (decl) = 1;
> > > > --- 33840,33846 ----
> > > >     DECL_NAME (decl) = decl_name;
> > > >     TREE_USED (decl) = 1;
> > > >     DECL_ARTIFICIAL (decl) = 1;
> > > > !   DECL_IGNORED_P (decl) = 1;
> > > >     /* IFUNC resolvers have to be externally visible.  */
> > > >     TREE_PUBLIC (decl) = 1;
> > > >     DECL_UNINLINABLE (decl) = 1;
> > > > 
> > > 
> > > 
> > 
> > 
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-05-19 10:44 [PATCH][2/2] early LTO debug, main part Richard Biener
  2017-06-07  8:21 ` Richard Biener
@ 2017-08-02  4:30 ` Jason Merrill
  2017-08-02 10:35   ` Richard Biener
  1 sibling, 1 reply; 22+ messages in thread
From: Jason Merrill @ 2017-08-02  4:30 UTC (permalink / raw)
  To: Richard Biener, gcc-patches

On 05/19/2017 06:42 AM, Richard Biener wrote:
> +     /* ???  In some cases the C++ FE (at least) fails to
> +        set DECL_CONTEXT properly.  Simply globalize stuff
> +        in this case.  For example
> +        __dso_handle created via iostream line 74 col 25.  */
> +     parent = comp_unit_die ();

I've now fixed __dso_handle, so that can be removed from the comment, 
but it still makes sense to have this fall-back for the (permitted) case 
of null DECL_CONTEXT.

> +       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
> + 	 at the input language (if we have enough DECL_CONTEXT to follow)
> + 	 or use a bit in tree_decl_with_vis to record the distinction.  */

Sure, you should be able to look at TRANSLATION_UNIT_LANGUAGE.

> ! 		  /* ???  We cannot unconditionally output die_offset if
> ! 		     non-zero - at least -feliminate-dwarf2-dups will
> ! 		     create references to those DIEs via symbols.  And we
> ! 		     do not clear its DIE offset after outputting it
> ! 		     (and the label refers to the actual DIEs, not the
> ! 		     DWARF CU unit header which is when using label + offset
> ! 		     would be the correct thing to do).

As in our previous discussion, I think -feliminate-dwarf2-dups can go 
away now.  But this is a more general issue: die_offset has meant the 
offset from the beginning of the CU, but if with_offset is set it means 
an offset from die_symbol.  Since with_offset changes the meaning of 
die_symbol and die_offset, having different code here depending on that 
flag makes sense.

It seems likely that when -fEDD goes away, we will never again want to 
do direct symbolic references to DIEs, in which case we could drop the 
current meaning of die_symbol, and so we wouldn't need the with_offset flag.

> !   unit_die->comdat_type_p = comdat_p;
> ! }
> ! 
> ! static void
> ! compute_section_prefix (dw_die_ref unit_die)
> ! {
> !   compute_section_prefix_1 (unit_die, true);
> !   comdat_symbol_id = unit_die->die_id.die_symbol;
>     comdat_symbol_number = 0;
>   }

Let's set the comdat_type_p flag in this function rather than add a 
parameter to the existing function.  And when -fEDD goes away, we don't 
need this entry point at all.

Also, for LTO debug, it seems you aren't actually using the symbol as a 
section prefix, so the name becomes inaccurate.  Maybe 
compute_comp_unit_symbol rather than compute_section_prefix_1?

> +   /* For LTO cross unit DIE refs we want a symbol on the start of the
> +      debuginfo section, not on the CU DIE.
> +      ???  We could simply use the symbol as it would be output by output_die
> +      and account for the extra offset produced by the CU header which has fixed
> +      size.  OTOH it currently only supports linkonce globals which would
> +      be less than ideal?.  */

I think the way you're doing it now is better than this alternative, 
since die_offset is relative to the beginning of the CU header.

> !       /* Don't output the symbol twice.  For LTO we want the label
> !          on the section beginning, not on the actual DIE.  */
> !       && (!flag_generate_lto
> ! 	      || die->die_tag != DW_TAG_compile_unit))

I think this check should just be !with_offset; if that flag is set the 
DIE doesn't actually have its own symbol.

> !       if (old_die
> ! 	  && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
> ! 	  /* ???  In LTO all origin DIEs still refer to the early
> ! 	     debug copy.  Detect that.  */
> ! 	  && get_AT (c, DW_AT_inline))
...
> !       /* "Unwrap" the decls DIE which we put in the imported unit context.
> !           ???  If we finish dwarf2out_function_decl refactoring we can
> ! 	  do this in a better way from the start and only lazily emit
> ! 	  the early DIE references.  */

It seems like in gen_subprogram_die you deliberately avoid reusing the 
DIE from dwarf2out_register_external_die (since it doesn't have 
DW_AT_inline), and then in add_abstract_origin_attribute you need to 
look through that redundant die.  Why not reuse it?

> ! 	  /* ???  In LTO we do not see any of the location attributes.  */
> ! 	   && ((DECL_ARTIFICIAL (decl) || in_lto_p)

Perhaps get_AT_ref (old_die, DW_AT_abstract_origin) instead of in_lto_p?

And you don't need the added parentheses here.

>      if (parm_die && parm_die->die_parent != context_die)
>   	{
> ! 	  /* ???  The DIE parent is the "abstract" copy and the context_die
> ! 	     is the specification "copy".  */
> ! 	  if (!DECL_ABSTRACT_P (node) && !in_lto_p)

And a bit below in the current source,

>               /* 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.  */

Now that you've done away with the old dwarf2out_abstract_function, I 
think dwarf2out shouldn't need to consider DECL_ABSTRACT_P at all.

In the hunk above, it seems that you want to reuse the parm DIEs from 
d*_register_external_die if origin is NULL, which seems appropriate. 
So, are there any cases remaining where we actually want to clear 
parm_die there?  I suspect not, in which case we should be able to 
remove the entire "if (parm_die && parm_die->die_parent != context_die)" 
block.

> ! 	  /* Early created DIEs do not have a parent as the decls refer
> ! 	     to the function as DECL_CONTEXT rather than the BLOCK.  */
> ! 	  if (in_lto_p
> ! 	      && die && die->die_parent == NULL)
> ! 	    add_child_die (context_die, die);

Perhaps in_lto_p should be asserted rather than a condition?

> ! 	       /* Do not generate stray type DIEs in late LTO dumping.  */
> ! 	       && early_dwarf)
...
> !       /* Avoid generating stray type DIEs during late dwarf dumping.
> !          All types have been dumped early.  */
> !       if (! lookup_decl_die (decl_or_origin)
...
> !       /* Avoid generating stray type DIEs during late dwarf dumping.
> !          All types have been dumped early.  */
> !       if (! lookup_decl_die (decl_or_origin)

Should these use the same test (early_dwarf vs. lookup_decl_die)?

Jason

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-08-02  4:30 ` Jason Merrill
@ 2017-08-02 10:35   ` Richard Biener
  2017-08-02 19:01     ` Jason Merrill
  0 siblings, 1 reply; 22+ messages in thread
From: Richard Biener @ 2017-08-02 10:35 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

On Wed, 2 Aug 2017, Jason Merrill wrote:

> On 05/19/2017 06:42 AM, Richard Biener wrote:
> > +     /* ???  In some cases the C++ FE (at least) fails to
> > +        set DECL_CONTEXT properly.  Simply globalize stuff
> > +        in this case.  For example
> > +        __dso_handle created via iostream line 74 col 25.  */
> > +     parent = comp_unit_die ();
> 
> I've now fixed __dso_handle, so that can be removed from the comment, but it
> still makes sense to have this fall-back for the (permitted) case of null
> DECL_CONTEXT.

Adjusted the comment.

> > +       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
> > + 	 at the input language (if we have enough DECL_CONTEXT to follow)
> > + 	 or use a bit in tree_decl_with_vis to record the distinction.  */
> 
> Sure, you should be able to look at TRANSLATION_UNIT_LANGUAGE.

Yeah, the comment says we might be able to walk DECL_CONTEXT up to
a TRANSLATION_UNIT_DECL.  I've amended is_fortran similar to as I
amended is_cxx, providing an overload for a decl, factoring out common
code.  So this is now if (is_fortran (decl)) ... = new_die 
(DW_TAG_module,...).

> > ! 		  /* ???  We cannot unconditionally output die_offset if
> > ! 		     non-zero - at least -feliminate-dwarf2-dups will
> > ! 		     create references to those DIEs via symbols.  And we
> > ! 		     do not clear its DIE offset after outputting it
> > ! 		     (and the label refers to the actual DIEs, not the
> > ! 		     DWARF CU unit header which is when using label + offset
> > ! 		     would be the correct thing to do).
> 
> As in our previous discussion, I think -feliminate-dwarf2-dups can go away
> now.  But this is a more general issue: die_offset has meant the offset from
> the beginning of the CU, but if with_offset is set it means an offset from
> die_symbol.  Since with_offset changes the meaning of die_symbol and
> die_offset, having different code here depending on that flag makes sense.
> 
> It seems likely that when -fEDD goes away, we will never again want to do
> direct symbolic references to DIEs, in which case we could drop the current
> meaning of die_symbol, and so we wouldn't need the with_offset flag.

Yeah, I've been playing with a patch to remove -fEDD but it has conflicts
with the early LTO debug work and thus I wanted to postpone it until
after that goes in to avoid further churn.  I hope that's fine, it's
sth I'll tackle soon after this patch lands on trunk.

> > !   unit_die->comdat_type_p = comdat_p;
> > ! }
> > ! ! static void
> > ! compute_section_prefix (dw_die_ref unit_die)
> > ! {
> > !   compute_section_prefix_1 (unit_die, true);
> > !   comdat_symbol_id = unit_die->die_id.die_symbol;
> >     comdat_symbol_number = 0;
> >   }
> 
> Let's set the comdat_type_p flag in this function rather than add a parameter
> to the existing function.  And when -fEDD goes away, we don't need this entry
> point at all.
> 
> Also, for LTO debug, it seems you aren't actually using the symbol as a
> section prefix, so the name becomes inaccurate.  Maybe
> compute_comp_unit_symbol rather than compute_section_prefix_1?

Done.

> > +   /* For LTO cross unit DIE refs we want a symbol on the start of the
> > +      debuginfo section, not on the CU DIE.
> > +      ???  We could simply use the symbol as it would be output by
> > output_die
> > +      and account for the extra offset produced by the CU header which has
> > fixed
> > +      size.  OTOH it currently only supports linkonce globals which would
> > +      be less than ideal?.  */
> 
> I think the way you're doing it now is better than this alternative, since
> die_offset is relative to the beginning of the CU header.

Removed the ??? part of the comment.

> > !       /* Don't output the symbol twice.  For LTO we want the label
> > !          on the section beginning, not on the actual DIE.  */
> > !       && (!flag_generate_lto
> > ! 	      || die->die_tag != DW_TAG_compile_unit))
> 
> I think this check should just be !with_offset; if that flag is set the DIE
> doesn't actually have its own symbol.

with_offset is set only during LTRANS phase for the DIEs refering to
the early DIEs via the CU label.  But the above is guarding the
early phase when we do not want to output that CU label twice.

Can we revisit this check when -fEDD has gone away?

> > !       if (old_die
> > ! 	  && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
> > ! 	  /* ???  In LTO all origin DIEs still refer to the early
> > ! 	     debug copy.  Detect that.  */
> > ! 	  && get_AT (c, DW_AT_inline))
> ...
> > !       /* "Unwrap" the decls DIE which we put in the imported unit context.
> > !           ???  If we finish dwarf2out_function_decl refactoring we can
> > ! 	  do this in a better way from the start and only lazily emit
> > ! 	  the early DIE references.  */
> 
> It seems like in gen_subprogram_die you deliberately avoid reusing the DIE
> from dwarf2out_register_external_die (since it doesn't have DW_AT_inline), and
> then in add_abstract_origin_attribute you need to look through that redundant
> die.  Why not reuse it?

What we're doing here is dealing with the case of an inlined
instance which is adjusted to point back to the early debug copy
directly than to the wrapping DIE (supposed to eventually contain
the concrete instance).

That is the underlying issue is that when we register the external DIE
we really register abstract origins for the decls but the easiest way
to store those is to create an actual DIE for the decl just containing
that abstract origin link.  For function decls that will end up as
the DIE for the concrete instance so we have to jump through this hoop
to get the abstract origin for the inline instances correct.  The
check in gen_subprogram_die

  /* An inlined instance, tag a new DIE with DW_AT_abstract_origin.  */
  if (origin != NULL)
    {
...
      dw_die_ref c;
      if (old_die
          && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
          /* ???  In LTO all origin DIEs still refer to the early
             debug copy.  Detect that.  */
          && get_AT (c, DW_AT_inline))
        {
          /* If we have a DW_AT_abstract_origin we have a working
             cached version.  */
          subr_die = old_die;

makes sure we do _not_ re-use this concrete instance DIE (it's
not the cached variant).

Maybe we can move the add_abstract_origin_attribute check to
some of the callers if we provide a variant that gets a origin DIE
rather than a tree ...

Can we leave this for future enhancement?  (just making a list here)

> 
> > ! 	  /* ???  In LTO we do not see any of the location attributes.  */
> > ! 	   && ((DECL_ARTIFICIAL (decl) || in_lto_p)
> 
> Perhaps get_AT_ref (old_die, DW_AT_abstract_origin) instead of in_lto_p?

Good idea.  Any reason why not get_AT (...)?  Using that now.

> And you don't need the added parentheses here.

Fixed.

> >      if (parm_die && parm_die->die_parent != context_die)
> >   	{
> > ! 	  /* ???  The DIE parent is the "abstract" copy and the context_die
> > ! 	     is the specification "copy".  */
> > ! 	  if (!DECL_ABSTRACT_P (node) && !in_lto_p)
> 
> And a bit below in the current source,
> 
> >               /* 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.  */
> 
> Now that you've done away with the old dwarf2out_abstract_function, I think
> dwarf2out shouldn't need to consider DECL_ABSTRACT_P at all.
> 
> In the hunk above, it seems that you want to reuse the parm DIEs from
> d*_register_external_die if origin is NULL, which seems appropriate. So, are
> there any cases remaining where we actually want to clear parm_die there?  I
> suspect not, in which case we should be able to remove the entire "if
> (parm_die && parm_die->die_parent != context_die)" block.

I suspect not either.  But the dwarf2out_abstract_function change
should cause DECL_ABSTRACT_P to _not_ be set (unless we have any
"real" DECL_ABSTRACT params) and thus we always run into the
param_die = NULL case (if the guarding condition is true, that is,
which I think happens for in_lto_p -- thus the change should have
been to amend the if (param_die && param_die->die_parent != 
context_die) with && !in_lto_p.

I've moved the && !in_lto_p check and the comment and added an item
on my TODO (remove this whole block).  And I added gcc_unreachable
as suggested by the comment above.

Oh, and if the later check, param_die->die_parent == NULL then
we've always run into the earlier block and if ! DECL_ABSTRACT_P
cleared param_die.

This code is somewhat confusing as it exists right now.

> > ! 	  /* Early created DIEs do not have a parent as the decls refer
> > ! 	     to the function as DECL_CONTEXT rather than the BLOCK.  */
> > ! 	  if (in_lto_p
> > ! 	      && die && die->die_parent == NULL)
> > ! 	    add_child_die (context_die, die);
> 
> Perhaps in_lto_p should be asserted rather than a condition?

You mean

    if (die && die->die_parent == NULL)
      {
        gcc_assert (in_lto_p);
        add_child_die (context_die, die);
      }

?  Done.

> > ! 	       /* Do not generate stray type DIEs in late LTO dumping.  */
> > ! 	       && early_dwarf)
> ...
> > !       /* Avoid generating stray type DIEs during late dwarf dumping.
> > !          All types have been dumped early.  */
> > !       if (! lookup_decl_die (decl_or_origin)
> ...
> > !       /* Avoid generating stray type DIEs during late dwarf dumping.
> > !          All types have been dumped early.  */
> > !       if (! lookup_decl_die (decl_or_origin)
> 
> Should these use the same test (early_dwarf vs. lookup_decl_die)?

Yeah, fixed.

Below is an incremental patch with the changes you requested, minus
those I put on the TODO.

I'll put this version through my usual testing now and will post
the full updated patch once that succeeded.

Thanks,
Richard.

Index: early-lto-debug/gcc/dwarf2out.c
===================================================================
--- early-lto-debug.orig/gcc/dwarf2out.c	2017-08-02 12:33:27.392750835 +0200
+++ early-lto-debug/gcc/dwarf2out.c	2017-08-02 12:29:13.128290085 +0200
@@ -5087,6 +5087,21 @@ get_AT_file (dw_die_ref die, enum dwarf_
   return a ? AT_file (a) : NULL;
 }
 
+/* Returns the ultimate TRANSLATION_UNIT_DECL context of DECL or NULL.  */
+
+static const_tree
+get_ultimate_context (const_tree decl)
+{
+  while (decl && TREE_CODE (decl) != TRANSLATION_UNIT_DECL)
+    {
+      if (TREE_CODE (decl) == BLOCK)
+	decl = BLOCK_SUPERCONTEXT (decl);
+      else
+	decl = get_containing_scope (decl);
+    }
+  return decl;
+}
+
 /* Return TRUE if the language is C++.  */
 
 static inline bool
@@ -5105,14 +5120,7 @@ is_cxx (const_tree decl)
 {
   if (in_lto_p)
     {
-      const_tree context = decl;
-      while (context && TREE_CODE (context) != TRANSLATION_UNIT_DECL)
-	{
-	  if (TREE_CODE (context) == BLOCK)
-	    context = BLOCK_SUPERCONTEXT (context);
-	  else
-	    context = get_containing_scope (context);
-	}
+      const_tree context = get_ultimate_context (decl);
       if (context && TRANSLATION_UNIT_LANGUAGE (context))
 	return strncmp (TRANSLATION_UNIT_LANGUAGE (context), "GNU C++", 7) == 0;
     }
@@ -5133,6 +5141,21 @@ is_fortran (void)
 	  || lang == DW_LANG_Fortran08);
 }
 
+static inline bool
+is_fortran (const_tree decl)
+{
+  if (in_lto_p)
+    {
+      const_tree context = get_ultimate_context (decl);
+      if (context && TRANSLATION_UNIT_LANGUAGE (context))
+	return (strncmp (TRANSLATION_UNIT_LANGUAGE (context),
+			 "GNU Fortran", 11) == 0
+		|| strcmp (TRANSLATION_UNIT_LANGUAGE (context),
+			   "GNU F77") == 0);
+    }
+  return is_fortran ();
+}
+
 /* Return TRUE if the language is Ada.  */
 
 static inline bool
@@ -5597,10 +5620,8 @@ dwarf2out_register_external_die (tree de
 	parent = lookup_decl_die (ctx);
     }
   else
-    /* ???  In some cases the C++ FE (at least) fails to
-       set DECL_CONTEXT properly.  Simply globalize stuff
-       in this case.  For example
-       __dso_handle created via iostream line 74 col 25.  */
+    /* In some cases the FEs fail to set DECL_CONTEXT properly.
+       Handle this case gracefully by globalizing stuff.  */
     parent = comp_unit_die ();
   /* Create a DIE "stub".  */
   switch (TREE_CODE (decl))
@@ -5619,10 +5640,10 @@ dwarf2out_register_external_die (tree de
       die = new_die (DW_TAG_compile_unit, NULL, decl);
       break;
     case NAMESPACE_DECL:
-      /* ???  LANG issue - DW_TAG_module for fortran.  Either look
-	 at the input language (if we have enough DECL_CONTEXT to follow)
-	 or use a bit in tree_decl_with_vis to record the distinction.  */
-      die = new_die (DW_TAG_namespace, parent, decl);
+      if (is_fortran (decl))
+	die = new_die (DW_TAG_module, parent, decl);
+      else
+	die = new_die (DW_TAG_namespace, parent, decl);
       break;
     case FUNCTION_DECL:
       die = new_die (DW_TAG_subprogram, parent, decl);
@@ -7461,10 +7482,10 @@ static const char *comdat_symbol_id;
 static unsigned int comdat_symbol_number;
 
 /* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its
-   children, and set comdat_symbol_id accordingly.  */
+   children, and set die_symbol.  */
 
 static void
-compute_section_prefix_1 (dw_die_ref unit_die, bool comdat_p)
+compute_comp_unit_symbol (dw_die_ref unit_die)
 {
   const char *die_name = get_AT_string (unit_die, DW_AT_name);
   const char *base = die_name ? lbasename (die_name) : "anonymous";
@@ -7498,13 +7519,13 @@ compute_section_prefix_1 (dw_die_ref uni
     }
 
   unit_die->die_id.die_symbol = xstrdup (name);
-  unit_die->comdat_type_p = comdat_p;
 }
 
 static void
 compute_section_prefix (dw_die_ref unit_die)
 {
-  compute_section_prefix_1 (unit_die, true);
+  compute_comp_unit_symbol (unit_die);
+  unit_die->comdat_type_p = true;
   comdat_symbol_id = unit_die->die_id.die_symbol;
   comdat_symbol_number = 0;
 }
@@ -10684,11 +10705,7 @@ output_comp_unit (dw_die_ref die, int ou
     }
 
   /* For LTO cross unit DIE refs we want a symbol on the start of the
-     debuginfo section, not on the CU DIE.
-     ???  We could simply use the symbol as it would be output by output_die
-     and account for the extra offset produced by the CU header which has fixed
-     size.  OTOH it currently only supports linkonce globals which would
-     be less than ideal?.  */
+     debuginfo section, not on the CU DIE.  */
   if (flag_generate_lto && oldsym)
     {
       /* ???  No way to get visibility assembled without a decl.  */
@@ -21505,12 +21522,13 @@ gen_formal_parameter_die (tree node, tre
       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)
+	 thing.
+	 ???  When in LTO the DIE parent is the "abstract" copy and the
+	 context_die is the specification "copy".  But this whole block
+	 should eventually be no longer needed.  */
+      if (parm_die && parm_die->die_parent != context_die && !in_lto_p)
 	{
-	  /* ???  The DIE parent is the "abstract" copy and the context_die
-	     is the specification "copy".  */
-	  if (!DECL_ABSTRACT_P (node) && !in_lto_p)
+	  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
@@ -21518,18 +21536,7 @@ gen_formal_parameter_die (tree node, tre
 	      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.  */
-	    }
+	    gcc_unreachable ();
 	}
 
       if (parm_die && parm_die->die_parent == NULL)
@@ -22189,8 +22196,11 @@ gen_subprogram_die (tree decl, dw_die_re
 	   || (old_die->die_parent
 	       && old_die->die_parent->die_tag == DW_TAG_module)
 	   || context_die == NULL)
-	  /* ???  In LTO we do not see any of the location attributes.  */
-	   && ((DECL_ARTIFICIAL (decl) || in_lto_p)
+	   && (DECL_ARTIFICIAL (decl)
+	       /* The location attributes may be in the abstract origin
+		  which in the case of LTO might be not available to
+		  look at.  */
+	       || get_AT (old_die, DW_AT_abstract_origin)
 	       || (get_AT_file (old_die, DW_AT_decl_file) == file_index
 		   && (get_AT_unsigned (old_die, DW_AT_decl_line)
 		       == (unsigned) s.line)
@@ -25067,9 +25077,11 @@ process_scope_var (tree stmt, tree decl,
 
 	  /* Early created DIEs do not have a parent as the decls refer
 	     to the function as DECL_CONTEXT rather than the BLOCK.  */
-	  if (in_lto_p
-	      && die && die->die_parent == NULL)
-	    add_child_die (context_die, die);
+	  if (die && die->die_parent == NULL)
+	    {
+	      gcc_assert (in_lto_p);
+	      add_child_die (context_die, die);
+	    }
 	}
 
       gen_decl_die (decl, origin, NULL, context_die);
@@ -25576,7 +25588,7 @@ gen_decl_die (tree decl, tree origin, st
 
       /* Avoid generating stray type DIEs during late dwarf dumping.
          All types have been dumped early.  */
-      if (! lookup_decl_die (decl_or_origin)
+      if (early_dwarf
 	  /* ???  But in LTRANS we cannot annotate early created variably
 	     modified type DIEs without copying them and adjusting all
 	     references to them.  Dump them again as happens for inlining
@@ -25635,7 +25647,7 @@ gen_decl_die (tree decl, tree origin, st
     case PARM_DECL:
       /* Avoid generating stray type DIEs during late dwarf dumping.
          All types have been dumped early.  */
-      if (! lookup_decl_die (decl_or_origin)
+      if (early_dwarf
 	  /* ???  But in LTRANS we cannot annotate early created variably
 	     modified type DIEs without copying them and adjusting all
 	     references to them.  Dump them again as happens for inlining
@@ -30863,7 +30875,7 @@ dwarf2out_early_finish (const char *file
     add_AT_pubnames (comp_unit_die ());
 
   /* Stick a unique symbol to the main debuginfo section.  */
-  compute_section_prefix_1 (comp_unit_die (), false);
+  compute_comp_unit_symbol (comp_unit_die ());
 
   /* Output the main compilation unit.  We always need it if only for
      the CU symbol.  */

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-08-02 10:35   ` Richard Biener
@ 2017-08-02 19:01     ` Jason Merrill
  2017-08-03 10:51       ` Richard Biener
  0 siblings, 1 reply; 22+ messages in thread
From: Jason Merrill @ 2017-08-02 19:01 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches List

On Wed, Aug 2, 2017 at 6:35 AM, Richard Biener <rguenther@suse.de> wrote:
> On Wed, 2 Aug 2017, Jason Merrill wrote:
>
>> On 05/19/2017 06:42 AM, Richard Biener wrote:
>> > +     /* ???  In some cases the C++ FE (at least) fails to
>> > +        set DECL_CONTEXT properly.  Simply globalize stuff
>> > +        in this case.  For example
>> > +        __dso_handle created via iostream line 74 col 25.  */
>> > +     parent = comp_unit_die ();
>>
>> I've now fixed __dso_handle, so that can be removed from the comment, but it
>> still makes sense to have this fall-back for the (permitted) case of null
>> DECL_CONTEXT.
>
> Adjusted the comment.
>
>> > +       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
>> > +    at the input language (if we have enough DECL_CONTEXT to follow)
>> > +    or use a bit in tree_decl_with_vis to record the distinction.  */
>>
>> Sure, you should be able to look at TRANSLATION_UNIT_LANGUAGE.
>
> Yeah, the comment says we might be able to walk DECL_CONTEXT up to
> a TRANSLATION_UNIT_DECL.  I've amended is_fortran similar to as I
> amended is_cxx, providing an overload for a decl, factoring out common
> code.  So this is now if (is_fortran (decl)) ... = new_die
> (DW_TAG_module,...).
>
>> > !             /* ???  We cannot unconditionally output die_offset if
>> > !                non-zero - at least -feliminate-dwarf2-dups will
>> > !                create references to those DIEs via symbols.  And we
>> > !                do not clear its DIE offset after outputting it
>> > !                (and the label refers to the actual DIEs, not the
>> > !                DWARF CU unit header which is when using label + offset
>> > !                would be the correct thing to do).
>>
>> As in our previous discussion, I think -feliminate-dwarf2-dups can go away
>> now.  But this is a more general issue: die_offset has meant the offset from
>> the beginning of the CU, but if with_offset is set it means an offset from
>> die_symbol.  Since with_offset changes the meaning of die_symbol and
>> die_offset, having different code here depending on that flag makes sense.
>>
>> It seems likely that when -fEDD goes away, we will never again want to do
>> direct symbolic references to DIEs, in which case we could drop the current
>> meaning of die_symbol, and so we wouldn't need the with_offset flag.
>
> Yeah, I've been playing with a patch to remove -fEDD but it has conflicts
> with the early LTO debug work and thus I wanted to postpone it until
> after that goes in to avoid further churn.  I hope that's fine, it's
> sth I'll tackle soon after this patch lands on trunk.

Sure.

>> > !       /* Don't output the symbol twice.  For LTO we want the label
>> > !          on the section beginning, not on the actual DIE.  */
>> > !       && (!flag_generate_lto
>> > !         || die->die_tag != DW_TAG_compile_unit))
>>
>> I think this check should just be !with_offset; if that flag is set the DIE
>> doesn't actually have its own symbol.
>
> with_offset is set only during LTRANS phase for the DIEs refering to
> the early DIEs via the CU label.  But the above is guarding the
> early phase when we do not want to output that CU label twice.
>
> Can we revisit this check when -fEDD has gone away?

Yes.

>> > !       if (old_die
>> > !     && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
>> > !     /* ???  In LTO all origin DIEs still refer to the early
>> > !        debug copy.  Detect that.  */
>> > !     && get_AT (c, DW_AT_inline))
>> ...
>> > !       /* "Unwrap" the decls DIE which we put in the imported unit context.
>> > !           ???  If we finish dwarf2out_function_decl refactoring we can
>> > !     do this in a better way from the start and only lazily emit
>> > !     the early DIE references.  */
>>
>> It seems like in gen_subprogram_die you deliberately avoid reusing the DIE
>> from dwarf2out_register_external_die (since it doesn't have DW_AT_inline), and
>> then in add_abstract_origin_attribute you need to look through that redundant
>> die.  Why not reuse it?
>
> What we're doing here is dealing with the case of an inlined
> instance which is adjusted to point back to the early debug copy
> directly than to the wrapping DIE (supposed to eventually contain
> the concrete instance).

But we enter this block when we're emitting the concrete out-of-line
instance, and the DW_AT_inline check prevents us from using the
wrapping DIE for the out-of-line instance.

The comment should really change "inlined instance" to "concrete
instance"; inlined instances are handled in
gen_inlined_subroutine_die.

Jason

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-08-02 19:01     ` Jason Merrill
@ 2017-08-03 10:51       ` Richard Biener
  2017-08-03 17:04         ` Jason Merrill
  0 siblings, 1 reply; 22+ messages in thread
From: Richard Biener @ 2017-08-03 10:51 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On Wed, 2 Aug 2017, Jason Merrill wrote:

> On Wed, Aug 2, 2017 at 6:35 AM, Richard Biener <rguenther@suse.de> wrote:
> > On Wed, 2 Aug 2017, Jason Merrill wrote:
> >
> >> On 05/19/2017 06:42 AM, Richard Biener wrote:
> >> > +     /* ???  In some cases the C++ FE (at least) fails to
> >> > +        set DECL_CONTEXT properly.  Simply globalize stuff
> >> > +        in this case.  For example
> >> > +        __dso_handle created via iostream line 74 col 25.  */
> >> > +     parent = comp_unit_die ();
> >>
> >> I've now fixed __dso_handle, so that can be removed from the comment, but it
> >> still makes sense to have this fall-back for the (permitted) case of null
> >> DECL_CONTEXT.
> >
> > Adjusted the comment.
> >
> >> > +       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
> >> > +    at the input language (if we have enough DECL_CONTEXT to follow)
> >> > +    or use a bit in tree_decl_with_vis to record the distinction.  */
> >>
> >> Sure, you should be able to look at TRANSLATION_UNIT_LANGUAGE.
> >
> > Yeah, the comment says we might be able to walk DECL_CONTEXT up to
> > a TRANSLATION_UNIT_DECL.  I've amended is_fortran similar to as I
> > amended is_cxx, providing an overload for a decl, factoring out common
> > code.  So this is now if (is_fortran (decl)) ... = new_die
> > (DW_TAG_module,...).
> >
> >> > !             /* ???  We cannot unconditionally output die_offset if
> >> > !                non-zero - at least -feliminate-dwarf2-dups will
> >> > !                create references to those DIEs via symbols.  And we
> >> > !                do not clear its DIE offset after outputting it
> >> > !                (and the label refers to the actual DIEs, not the
> >> > !                DWARF CU unit header which is when using label + offset
> >> > !                would be the correct thing to do).
> >>
> >> As in our previous discussion, I think -feliminate-dwarf2-dups can go away
> >> now.  But this is a more general issue: die_offset has meant the offset from
> >> the beginning of the CU, but if with_offset is set it means an offset from
> >> die_symbol.  Since with_offset changes the meaning of die_symbol and
> >> die_offset, having different code here depending on that flag makes sense.
> >>
> >> It seems likely that when -fEDD goes away, we will never again want to do
> >> direct symbolic references to DIEs, in which case we could drop the current
> >> meaning of die_symbol, and so we wouldn't need the with_offset flag.
> >
> > Yeah, I've been playing with a patch to remove -fEDD but it has conflicts
> > with the early LTO debug work and thus I wanted to postpone it until
> > after that goes in to avoid further churn.  I hope that's fine, it's
> > sth I'll tackle soon after this patch lands on trunk.
> 
> Sure.
> 
> >> > !       /* Don't output the symbol twice.  For LTO we want the label
> >> > !          on the section beginning, not on the actual DIE.  */
> >> > !       && (!flag_generate_lto
> >> > !         || die->die_tag != DW_TAG_compile_unit))
> >>
> >> I think this check should just be !with_offset; if that flag is set the DIE
> >> doesn't actually have its own symbol.
> >
> > with_offset is set only during LTRANS phase for the DIEs refering to
> > the early DIEs via the CU label.  But the above is guarding the
> > early phase when we do not want to output that CU label twice.
> >
> > Can we revisit this check when -fEDD has gone away?
> 
> Yes.
> 
> >> > !       if (old_die
> >> > !     && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
> >> > !     /* ???  In LTO all origin DIEs still refer to the early
> >> > !        debug copy.  Detect that.  */
> >> > !     && get_AT (c, DW_AT_inline))
> >> ...
> >> > !       /* "Unwrap" the decls DIE which we put in the imported unit context.
> >> > !           ???  If we finish dwarf2out_function_decl refactoring we can
> >> > !     do this in a better way from the start and only lazily emit
> >> > !     the early DIE references.  */
> >>
> >> It seems like in gen_subprogram_die you deliberately avoid reusing the DIE
> >> from dwarf2out_register_external_die (since it doesn't have DW_AT_inline), and
> >> then in add_abstract_origin_attribute you need to look through that redundant
> >> die.  Why not reuse it?
> >
> > What we're doing here is dealing with the case of an inlined
> > instance which is adjusted to point back to the early debug copy
> > directly than to the wrapping DIE (supposed to eventually contain
> > the concrete instance).
> 
> But we enter this block when we're emitting the concrete out-of-line
> instance, and the DW_AT_inline check prevents us from using the
> wrapping DIE for the out-of-line instance.
> 
> The comment should really change "inlined instance" to "concrete
> instance"; inlined instances are handled in
> gen_inlined_subroutine_die.

You are right.  I suspect I got confused by the comment when looking
for a way to paper over the check_die ICE removing the check causes.
We end up adding DW_AT_inline to the DIE which means check_die isn't
happy with us using it for the concrete instance.

That happens in two places, first add_abstract_origin_attribute
calling dwarf2out_abstract_function for origin != FUNCTION_DECL/BLOCK
and second from RTL expansion calling the same function via the
debug hook.  Both of this should be obsoleted by the early debug
work on trunk.  Then we do the same from gen_decl_die.  I'm not sure
that those cases are obsolete by now - the clone case should
eventually be, but we can probably guard them with early_dwarf -- this
exposes the issue that gen_subprogram_die happily re-uses the old_die
even if DW_AT_inline is set, so the set_decl_origin_self must
matter here.  During early dwarf cgraph_function_possibly_inlined_p
returns false.  Not sure what is best here - either guarding
gen_subprogram_die or doing set_decl_origin_self in
dwarf2out_abstract_function?  Doing the latter now with the idea
this origin might be important elsewhere.  For in_lto_p we also need to
avoid dwarf2out_abstract_function, easiest by adding a
|| get_AT (old_die, DW_AT_abstract_origin) to the existing check
for DW_AT_inline (that might have fixed all of the issues above,
just in case you are hot happy with them).

I've changed the comment in add_abstract_origin_attribute as the
unwrapping is really because of the inlined subroutine case.  It
also ends up applying to the case of clones where I'm less sure
if the abstract origin should point to the concrete instance or
the abstract copy (without LTO it points at the abstract copy
and thus matches what the patch ends up doing).

So with the following I see the DIEs used for the concrete instance
as intented and the abstract copy in the early object refered to
by inline instances (and the concrete instance of course).

Re-doing testing...

Thanks,
Richard.

Index: early-lto-debug/gcc/dwarf2out.c
===================================================================
--- early-lto-debug.orig/gcc/dwarf2out.c	2017-08-03 12:48:59.854268649 +0200
+++ early-lto-debug/gcc/dwarf2out.c	2017-08-03 12:44:13.545059174 +0200
@@ -20517,33 +20517,12 @@ add_abstract_origin_attribute (dw_die_re
 {
   dw_die_ref origin_die = NULL;
 
-  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
-	 sure that the abstract function has been written out.
-
-	 Doing this for nested functions is wrong, however; functions are
-	 distinct units, and our context might not even be inline.  */
-      tree fn = origin;
-
-      if (TYPE_P (fn))
-	fn = TYPE_STUB_DECL (fn);
-
-      fn = decl_function_context (fn);
-      if (fn)
-	dwarf2out_abstract_function (fn);
-    }
-
   if (DECL_P (origin))
     {
       dw_die_ref c;
       origin_die = lookup_decl_die (origin);
       /* "Unwrap" the decls DIE which we put in the imported unit context.
-          ???  If we finish dwarf2out_function_decl refactoring we can
-	  do this in a better way from the start and only lazily emit
-	  the early DIE references.  */
+         We are looking for the abstract copy here.  */
       if (in_lto_p
 	  && origin_die
 	  && (c = get_AT_ref (origin_die, DW_AT_abstract_origin))
@@ -21879,7 +21858,8 @@ dwarf2out_abstract_function (tree decl)
   old_die = lookup_decl_die (decl);
   /* With early debug we always have an old DIE.  */
   gcc_assert (old_die != NULL);
-  if (get_AT (old_die, DW_AT_inline))
+  if (get_AT (old_die, DW_AT_inline)
+      || get_AT (old_die, DW_AT_abstract_origin))
     /* We've already generated the abstract instance.  */
     return;
 
@@ -21902,6 +21882,8 @@ dwarf2out_abstract_function (tree decl)
   if (DECL_DECLARED_INLINE_P (decl)
       && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
     add_AT_flag (old_die, DW_AT_artificial, 1);
+
+  set_decl_origin_self (decl);
 }
 
 /* Helper function of premark_used_types() which gets called through
@@ -22113,7 +22095,7 @@ gen_subprogram_die (tree decl, dw_die_re
       && debug_info_level > DINFO_LEVEL_TERSE)
     old_die = force_decl_die (decl);
 
-  /* An inlined instance, tag a new DIE with DW_AT_abstract_origin.  */
+  /* A concrete instance, tag a new DIE with DW_AT_abstract_origin.  */
   if (origin != NULL)
     {
       gcc_assert (!declaration || local_scope_p (context_die));
@@ -22123,12 +22105,7 @@ gen_subprogram_die (tree decl, dw_die_re
       if (old_die && old_die->die_parent == NULL)
 	add_child_die (context_die, old_die);
 
-      dw_die_ref c;
-      if (old_die
-	  && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
-	  /* ???  In LTO all origin DIEs still refer to the early
-	     debug copy.  Detect that.  */
-	  && get_AT (c, DW_AT_inline))
+      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.  */
@@ -25496,8 +25473,13 @@ gen_decl_die (tree decl, tree origin, st
 	/* This is only a declaration.  */;
 #endif
 
+      /* We should have abstract copies already and should not generate
+	 stray type DIEs in late LTO dumping.  */
+      if (! early_dwarf)
+	;
+
       /* If we're emitting a clone, emit info for the abstract instance.  */
-      if (origin || DECL_ORIGIN (decl) != decl)
+      else if (origin || DECL_ORIGIN (decl) != decl)
 	dwarf2out_abstract_function (origin
 				     ? DECL_ORIGIN (origin)
 				     : DECL_ABSTRACT_ORIGIN (decl));
@@ -25511,15 +25493,10 @@ gen_decl_die (tree decl, tree origin, st
 		  a declaration.  We must avoid setting DECL_ABSTRACT_ORIGIN in
 		  that case, because that works only if we have a die.  */
 	       && DECL_INITIAL (decl) != NULL_TREE)
-	{
-	  dwarf2out_abstract_function (decl);
-	  set_decl_origin_self (decl);
-	}
+	dwarf2out_abstract_function (decl);
 
       /* Otherwise we're emitting the primary DIE for this decl.  */
-      else if (debug_info_level > DINFO_LEVEL_TERSE
-	       /* Do not generate stray type DIEs in late LTO dumping.  */
-	       && early_dwarf)
+      else if (debug_info_level > DINFO_LEVEL_TERSE)
 	{
 	  /* Before we describe the FUNCTION_DECL itself, make sure that we
 	     have its containing type.  */
Index: early-lto-debug/gcc/cfgexpand.c
===================================================================
--- early-lto-debug.orig/gcc/cfgexpand.c	2017-08-02 10:20:44.093608890 +0200
+++ early-lto-debug/gcc/cfgexpand.c	2017-08-03 12:21:08.348962776 +0200
@@ -6527,12 +6527,6 @@ pass_expand::execute (function *fun)
 	  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1;
     }
 
-  /* We are now committed to emitting code for this function.  Do any
-     preparation, such as emitting abstract debug info for the inline
-     before it gets mangled by optimization.  */
-  if (cgraph_function_possibly_inlined_p (current_function_decl))
-    (*debug_hooks->outlining_inline_function) (current_function_decl);
-
   TREE_ASM_WRITTEN (current_function_decl) = 1;
 
   /* After expanding, the return labels are no longer needed. */

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-08-03 10:51       ` Richard Biener
@ 2017-08-03 17:04         ` Jason Merrill
  2017-08-04 12:21           ` Richard Biener
  0 siblings, 1 reply; 22+ messages in thread
From: Jason Merrill @ 2017-08-03 17:04 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches List

On Thu, Aug 3, 2017 at 6:51 AM, Richard Biener <rguenther@suse.de> wrote:
> On Wed, 2 Aug 2017, Jason Merrill wrote:
>
>> On Wed, Aug 2, 2017 at 6:35 AM, Richard Biener <rguenther@suse.de> wrote:
>> > On Wed, 2 Aug 2017, Jason Merrill wrote:
>> >
>> >> On 05/19/2017 06:42 AM, Richard Biener wrote:
>> >> > +     /* ???  In some cases the C++ FE (at least) fails to
>> >> > +        set DECL_CONTEXT properly.  Simply globalize stuff
>> >> > +        in this case.  For example
>> >> > +        __dso_handle created via iostream line 74 col 25.  */
>> >> > +     parent = comp_unit_die ();
>> >>
>> >> I've now fixed __dso_handle, so that can be removed from the comment, but it
>> >> still makes sense to have this fall-back for the (permitted) case of null
>> >> DECL_CONTEXT.
>> >
>> > Adjusted the comment.
>> >
>> >> > +       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
>> >> > +    at the input language (if we have enough DECL_CONTEXT to follow)
>> >> > +    or use a bit in tree_decl_with_vis to record the distinction.  */
>> >>
>> >> Sure, you should be able to look at TRANSLATION_UNIT_LANGUAGE.
>> >
>> > Yeah, the comment says we might be able to walk DECL_CONTEXT up to
>> > a TRANSLATION_UNIT_DECL.  I've amended is_fortran similar to as I
>> > amended is_cxx, providing an overload for a decl, factoring out common
>> > code.  So this is now if (is_fortran (decl)) ... = new_die
>> > (DW_TAG_module,...).
>> >
>> >> > !             /* ???  We cannot unconditionally output die_offset if
>> >> > !                non-zero - at least -feliminate-dwarf2-dups will
>> >> > !                create references to those DIEs via symbols.  And we
>> >> > !                do not clear its DIE offset after outputting it
>> >> > !                (and the label refers to the actual DIEs, not the
>> >> > !                DWARF CU unit header which is when using label + offset
>> >> > !                would be the correct thing to do).
>> >>
>> >> As in our previous discussion, I think -feliminate-dwarf2-dups can go away
>> >> now.  But this is a more general issue: die_offset has meant the offset from
>> >> the beginning of the CU, but if with_offset is set it means an offset from
>> >> die_symbol.  Since with_offset changes the meaning of die_symbol and
>> >> die_offset, having different code here depending on that flag makes sense.
>> >>
>> >> It seems likely that when -fEDD goes away, we will never again want to do
>> >> direct symbolic references to DIEs, in which case we could drop the current
>> >> meaning of die_symbol, and so we wouldn't need the with_offset flag.
>> >
>> > Yeah, I've been playing with a patch to remove -fEDD but it has conflicts
>> > with the early LTO debug work and thus I wanted to postpone it until
>> > after that goes in to avoid further churn.  I hope that's fine, it's
>> > sth I'll tackle soon after this patch lands on trunk.
>>
>> Sure.
>>
>> >> > !       /* Don't output the symbol twice.  For LTO we want the label
>> >> > !          on the section beginning, not on the actual DIE.  */
>> >> > !       && (!flag_generate_lto
>> >> > !         || die->die_tag != DW_TAG_compile_unit))
>> >>
>> >> I think this check should just be !with_offset; if that flag is set the DIE
>> >> doesn't actually have its own symbol.
>> >
>> > with_offset is set only during LTRANS phase for the DIEs refering to
>> > the early DIEs via the CU label.  But the above is guarding the
>> > early phase when we do not want to output that CU label twice.
>> >
>> > Can we revisit this check when -fEDD has gone away?
>>
>> Yes.
>>
>> >> > !       if (old_die
>> >> > !     && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
>> >> > !     /* ???  In LTO all origin DIEs still refer to the early
>> >> > !        debug copy.  Detect that.  */
>> >> > !     && get_AT (c, DW_AT_inline))
>> >> ...
>> >> > !       /* "Unwrap" the decls DIE which we put in the imported unit context.
>> >> > !           ???  If we finish dwarf2out_function_decl refactoring we can
>> >> > !     do this in a better way from the start and only lazily emit
>> >> > !     the early DIE references.  */
>> >>
>> >> It seems like in gen_subprogram_die you deliberately avoid reusing the DIE
>> >> from dwarf2out_register_external_die (since it doesn't have DW_AT_inline), and
>> >> then in add_abstract_origin_attribute you need to look through that redundant
>> >> die.  Why not reuse it?
>> >
>> > What we're doing here is dealing with the case of an inlined
>> > instance which is adjusted to point back to the early debug copy
>> > directly than to the wrapping DIE (supposed to eventually contain
>> > the concrete instance).
>>
>> But we enter this block when we're emitting the concrete out-of-line
>> instance, and the DW_AT_inline check prevents us from using the
>> wrapping DIE for the out-of-line instance.
>>
>> The comment should really change "inlined instance" to "concrete
>> instance"; inlined instances are handled in
>> gen_inlined_subroutine_die.
>
> You are right.  I suspect I got confused by the comment when looking
> for a way to paper over the check_die ICE removing the check causes.
> We end up adding DW_AT_inline to the DIE which means check_die isn't
> happy with us using it for the concrete instance.
>
> That happens in two places, first add_abstract_origin_attribute
> calling dwarf2out_abstract_function for origin != FUNCTION_DECL/BLOCK
> and second from RTL expansion calling the same function via the
> debug hook.  Both of this should be obsoleted by the early debug
> work on trunk.  Then we do the same from gen_decl_die.  I'm not sure
> that those cases are obsolete by now - the clone case should
> eventually be, but we can probably guard them with early_dwarf -- this
> exposes the issue that gen_subprogram_die happily re-uses the old_die
> even if DW_AT_inline is set, so the set_decl_origin_self must
> matter here.  During early dwarf cgraph_function_possibly_inlined_p
> returns false.  Not sure what is best here - either guarding
> gen_subprogram_die or doing set_decl_origin_self in
> dwarf2out_abstract_function?  Doing the latter now with the idea
> this origin might be important elsewhere.  For in_lto_p we also need to
> avoid dwarf2out_abstract_function, easiest by adding a
> || get_AT (old_die, DW_AT_abstract_origin) to the existing check
> for DW_AT_inline (that might have fixed all of the issues above,
> just in case you are hot happy with them).
>
> I've changed the comment in add_abstract_origin_attribute as the
> unwrapping is really because of the inlined subroutine case.  It
> also ends up applying to the case of clones where I'm less sure
> if the abstract origin should point to the concrete instance or
> the abstract copy (without LTO it points at the abstract copy
> and thus matches what the patch ends up doing).
>
> So with the following I see the DIEs used for the concrete instance
> as intented and the abstract copy in the early object refered to
> by inline instances (and the concrete instance of course).
>
> Re-doing testing...

OK if testing passes.

Jason

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-08-03 17:04         ` Jason Merrill
@ 2017-08-04 12:21           ` Richard Biener
  2017-08-22 10:49             ` Szabolcs Nagy
  2017-09-19 15:24             ` Jakub Jelinek
  0 siblings, 2 replies; 22+ messages in thread
From: Richard Biener @ 2017-08-04 12:21 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On Thu, 3 Aug 2017, Jason Merrill wrote:

> On Thu, Aug 3, 2017 at 6:51 AM, Richard Biener <rguenther@suse.de> wrote:
> > On Wed, 2 Aug 2017, Jason Merrill wrote:
> >
> >> On Wed, Aug 2, 2017 at 6:35 AM, Richard Biener <rguenther@suse.de> wrote:
> >> > On Wed, 2 Aug 2017, Jason Merrill wrote:
> >> >
> >> >> On 05/19/2017 06:42 AM, Richard Biener wrote:
> >> >> > +     /* ???  In some cases the C++ FE (at least) fails to
> >> >> > +        set DECL_CONTEXT properly.  Simply globalize stuff
> >> >> > +        in this case.  For example
> >> >> > +        __dso_handle created via iostream line 74 col 25.  */
> >> >> > +     parent = comp_unit_die ();
> >> >>
> >> >> I've now fixed __dso_handle, so that can be removed from the comment, but it
> >> >> still makes sense to have this fall-back for the (permitted) case of null
> >> >> DECL_CONTEXT.
> >> >
> >> > Adjusted the comment.
> >> >
> >> >> > +       /* ???  LANG issue - DW_TAG_module for fortran.  Either look
> >> >> > +    at the input language (if we have enough DECL_CONTEXT to follow)
> >> >> > +    or use a bit in tree_decl_with_vis to record the distinction.  */
> >> >>
> >> >> Sure, you should be able to look at TRANSLATION_UNIT_LANGUAGE.
> >> >
> >> > Yeah, the comment says we might be able to walk DECL_CONTEXT up to
> >> > a TRANSLATION_UNIT_DECL.  I've amended is_fortran similar to as I
> >> > amended is_cxx, providing an overload for a decl, factoring out common
> >> > code.  So this is now if (is_fortran (decl)) ... = new_die
> >> > (DW_TAG_module,...).
> >> >
> >> >> > !             /* ???  We cannot unconditionally output die_offset if
> >> >> > !                non-zero - at least -feliminate-dwarf2-dups will
> >> >> > !                create references to those DIEs via symbols.  And we
> >> >> > !                do not clear its DIE offset after outputting it
> >> >> > !                (and the label refers to the actual DIEs, not the
> >> >> > !                DWARF CU unit header which is when using label + offset
> >> >> > !                would be the correct thing to do).
> >> >>
> >> >> As in our previous discussion, I think -feliminate-dwarf2-dups can go away
> >> >> now.  But this is a more general issue: die_offset has meant the offset from
> >> >> the beginning of the CU, but if with_offset is set it means an offset from
> >> >> die_symbol.  Since with_offset changes the meaning of die_symbol and
> >> >> die_offset, having different code here depending on that flag makes sense.
> >> >>
> >> >> It seems likely that when -fEDD goes away, we will never again want to do
> >> >> direct symbolic references to DIEs, in which case we could drop the current
> >> >> meaning of die_symbol, and so we wouldn't need the with_offset flag.
> >> >
> >> > Yeah, I've been playing with a patch to remove -fEDD but it has conflicts
> >> > with the early LTO debug work and thus I wanted to postpone it until
> >> > after that goes in to avoid further churn.  I hope that's fine, it's
> >> > sth I'll tackle soon after this patch lands on trunk.
> >>
> >> Sure.
> >>
> >> >> > !       /* Don't output the symbol twice.  For LTO we want the label
> >> >> > !          on the section beginning, not on the actual DIE.  */
> >> >> > !       && (!flag_generate_lto
> >> >> > !         || die->die_tag != DW_TAG_compile_unit))
> >> >>
> >> >> I think this check should just be !with_offset; if that flag is set the DIE
> >> >> doesn't actually have its own symbol.
> >> >
> >> > with_offset is set only during LTRANS phase for the DIEs refering to
> >> > the early DIEs via the CU label.  But the above is guarding the
> >> > early phase when we do not want to output that CU label twice.
> >> >
> >> > Can we revisit this check when -fEDD has gone away?
> >>
> >> Yes.
> >>
> >> >> > !       if (old_die
> >> >> > !     && (c = get_AT_ref (old_die, DW_AT_abstract_origin))
> >> >> > !     /* ???  In LTO all origin DIEs still refer to the early
> >> >> > !        debug copy.  Detect that.  */
> >> >> > !     && get_AT (c, DW_AT_inline))
> >> >> ...
> >> >> > !       /* "Unwrap" the decls DIE which we put in the imported unit context.
> >> >> > !           ???  If we finish dwarf2out_function_decl refactoring we can
> >> >> > !     do this in a better way from the start and only lazily emit
> >> >> > !     the early DIE references.  */
> >> >>
> >> >> It seems like in gen_subprogram_die you deliberately avoid reusing the DIE
> >> >> from dwarf2out_register_external_die (since it doesn't have DW_AT_inline), and
> >> >> then in add_abstract_origin_attribute you need to look through that redundant
> >> >> die.  Why not reuse it?
> >> >
> >> > What we're doing here is dealing with the case of an inlined
> >> > instance which is adjusted to point back to the early debug copy
> >> > directly than to the wrapping DIE (supposed to eventually contain
> >> > the concrete instance).
> >>
> >> But we enter this block when we're emitting the concrete out-of-line
> >> instance, and the DW_AT_inline check prevents us from using the
> >> wrapping DIE for the out-of-line instance.
> >>
> >> The comment should really change "inlined instance" to "concrete
> >> instance"; inlined instances are handled in
> >> gen_inlined_subroutine_die.
> >
> > You are right.  I suspect I got confused by the comment when looking
> > for a way to paper over the check_die ICE removing the check causes.
> > We end up adding DW_AT_inline to the DIE which means check_die isn't
> > happy with us using it for the concrete instance.
> >
> > That happens in two places, first add_abstract_origin_attribute
> > calling dwarf2out_abstract_function for origin != FUNCTION_DECL/BLOCK
> > and second from RTL expansion calling the same function via the
> > debug hook.  Both of this should be obsoleted by the early debug
> > work on trunk.  Then we do the same from gen_decl_die.  I'm not sure
> > that those cases are obsolete by now - the clone case should
> > eventually be, but we can probably guard them with early_dwarf -- this
> > exposes the issue that gen_subprogram_die happily re-uses the old_die
> > even if DW_AT_inline is set, so the set_decl_origin_self must
> > matter here.  During early dwarf cgraph_function_possibly_inlined_p
> > returns false.  Not sure what is best here - either guarding
> > gen_subprogram_die or doing set_decl_origin_self in
> > dwarf2out_abstract_function?  Doing the latter now with the idea
> > this origin might be important elsewhere.  For in_lto_p we also need to
> > avoid dwarf2out_abstract_function, easiest by adding a
> > || get_AT (old_die, DW_AT_abstract_origin) to the existing check
> > for DW_AT_inline (that might have fixed all of the issues above,
> > just in case you are hot happy with them).
> >
> > I've changed the comment in add_abstract_origin_attribute as the
> > unwrapping is really because of the inlined subroutine case.  It
> > also ends up applying to the case of clones where I'm less sure
> > if the abstract origin should point to the concrete instance or
> > the abstract copy (without LTO it points at the abstract copy
> > and thus matches what the patch ends up doing).
> >
> > So with the following I see the DIEs used for the concrete instance
> > as intented and the abstract copy in the early object refered to
> > by inline instances (and the concrete instance of course).
> >
> > Re-doing testing...
> 
> OK if testing passes.

Thanks.  Meanwhile testing passed.

Bootstrapped and tested on x86_64-unknown-linux-gnu, LTO bootstrapped
on x86_64-unknown-linux-gnu (both all languages).  I've successfully
built SPEC CPU 2006 with -flto -g (provides reasonable Fortran coverage).
I've successfully ran the GCC testsuite with -flto -g which shows lots
of FAILs but doesn't regress in any unexpected ways compared to before
the patches.

I'll ping Ian about the simple-object part again and will apply
earliest at Aug 14th.

Richard.

2017-08-04  Richard Biener  <rguenther@suse.de>

        * debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and
        register_external_die hooks.
        (debug_false_tree_charstarstar_uhwistar): Declare.
        (debug_nothing_tree_charstar_uhwi): Likewise.
        * debug.c (do_nothing_debug_hooks): Adjust.
        (debug_false_tree_charstarstar_uhwistar): New do nothing.
        (debug_nothing_tree_charstar_uhwi): Likewise.
        * dbxout.c (dbx_debug_hooks): Adjust.
        (xcoff_debug_hooks): Likewise.
        * sdbout.c (sdb_debug_hooks): Likewise.
        * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.

        * dwarf2out.c (macinfo_label_base): New global.
	(dwarf2out_register_external_die): New function for the
	register_external_die hook.
        (dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl.
        (dwarf2_debug_hooks): Use them.
        (dwarf2_lineno_debug_hooks): Adjust.
        (struct die_struct): Add with_offset flag.
        (DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION,
        DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION,
        DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION,
        DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION,
        DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
        DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros
        defining section names for the early LTO debug variants.
	(reset_indirect_string): New helper.
        (add_AT_external_die_ref): Helper for dwarf2out_register_external_die.
        (print_dw_val): Add support for offsetted symbol references.
	(get_ultimate_context): Split out from is_cxx.
	(is_cxx): Use get_ultimate_context.
	(is_fortran): Add decl overload.
        (compute_comp_unit_symbol): Split out worker from
	compute_section_prefix.
        (compute_section_prefix): Call compute_comp_unit_symbol and
	set comdat_type_p here.
        (output_die): Skip DIE symbol output for the LTO added one.
        Handle DIE symbol references with offset.
        (output_comp_unit): Guard section name mangling properly.
        For LTO debug sections emit a symbol at the section beginning
        which we use to refer to its DIEs.
        (add_abstract_origin_attribute): For DIEs registered via
        dwarf2out_register_external_die directly refer to the early
        DIE rather than indirectly through the shadow one we created.
	Remove obsolete call to dwarf2out_abstract_function for
	non-function/block origins.
        (gen_array_type_die): When generating early LTO debug do
        not emit DW_AT_string_length.
        (gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs
        late when in LTO.  As suggested place a gcc_unreachable for
	the DECL_ABSTRACT_P case.
        (gen_subprogram_die): Avoid another specification DIE
        for early built declarations/definitions for the late LTO case.
        (gen_variable_die): Add type references for late duplicated VLA dies
        when in late LTO.
        (gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function,
        we have the abstract instance already.
        (process_scope_var): Adjust decl DIE contexts in LTO which
        first puts them in limbo.
        (gen_decl_die): Do not generate type DIEs late apart from
        types for VLAs or for decls we do not yet have a DIE.  Do not
	call dwarf2out_abstract_function late.
        (dwarf2out_early_global_decl): Make sure to create DIEs
        for abstract instances of a decl first.
        (dwarf2out_late_global_decl): Adjust comment.
        (output_macinfo_op): With multiple macro sections use
	macinfo_label_base to distinguish labels.
        (output_macinfo): Likewise.  Update macinfo_label_base.
	Pass in the line info label.
	(note_variable_value_in_expr): When generating LTO resolve
	all variable values here by generating DIEs as needed.
        (init_sections_and_labels): Add early LTO debug flag parameter
        and generate different sections and names if set.  Add generation
        counter for the labels so we can have multiple of them.
        (reset_dies): Helper to allow DIEs to be output multiple times.
        (dwarf2out_finish): When outputting DIEs to the fat part of an
	LTO object first reset DIEs.
        (dwarf2out_early_finish): Output early DIEs when generating LTO.

Cleanups we can do (and need) when removing the "old" LTO path and add
the early LTO path.

        (set_decl_abstract_flags): Remove.
        (set_block_abstract_flags): Likewise.
        (dwarf2out_abstract_function): Treat the early generated DIEs
        as the abstract copy and only add DW_AT_inline and
        DW_AT_artificial here and call set_decl_origin_self.
	If the DIE has an abstract origin don't do anything.

	* tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL
	if we have none yet (Go fails to build one, PR78628).
        * lto-streamer-in.c: Include debug.h.
        (dref_queue): New global.
        (lto_read_tree_1): Stream in DIE references.
        (lto_input_tree): Register DIE references.
	(input_function): Stream DECL_DEBUG_ARGS.
        * lto-streamer-out.c: Include debug.h.
        (lto_write_tree_1): Output DIE references.
        (DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN.
	Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls.
	(output_function): Stream DECL_DEBUG_ARGS.
        * tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers):
        Stream DECL_ABSTRACT_ORIGIN.
        * tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise.
	(write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL
	DECL_CONTEXT for file-scope decls.
        * lto-streamer.h (struct dref_entry): Declare.
        (dref_queue): Likewise.
	* cfgexpand.c (pass_expand::execute): Do not call the
	outlining_inline_function hook here.

        * lto-wrapper.c (debug_obj): New global.
        (tool_cleanup): Unlink it if required.
        (debug_objcopy): New function.
        (run_gcc): Handle early debug sections in the IL files by
        extracting them to separate files, partially linkin them and
        feeding the result back as result to the linker.

        * config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION,
        DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION,
        DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug
        sections into a separate segment.
        * config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO
        segments.
        (darwin_asm_dwarf_section): Likewise.
        (darwin_asm_output_dwarf_offset): Likewise.

	* config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P.

        lto/
        * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
        (lto_read_decls): Process TRANSLATION_UNIT_DECLs.  Remove
        TYPE_DECL debug processing, register DIE references from
        prevailing SCCs with the debug machinery.
        (lto_section_with_id): Handle LTO debug sections.

	libstdc++/
	* testsuite/libstdc++-prettyprinters/prettyprinters.exp: Run all
	tests with -flto as well if supported.

	* c-c++-common/asan/global-overflow-1.c: Adjust diagnostic location
	regex to handle the LTO case.
	* c-c++-common/asan/heap-overflow-1.c: Likewise.
	* c-c++-common/asan/misalign-1.c: Likewise.
	* c-c++-common/asan/misalign-2.c: Likewise.
	* c-c++-common/asan/null-deref-1.c: Likewise.
	* c-c++-common/asan/stack-overflow-1.c: Likewise.
	* c-c++-common/asan/strncpy-overflow-1.c: Likewise.
	* c-c++-common/asan/use-after-free-1.c: Likewise.
	* c-c++-common/asan/alloca_big_alignment.c: Likewise.
	* c-c++-common/asan/alloca_detect_custom_size.c: Likewise.
	* c-c++-common/asan/alloca_overflow_partial.c: Likewise.
	* c-c++-common/asan/alloca_overflow_right.c: Likewise.
	* c-c++-common/asan/alloca_underflow_left.c: Likewise.
	* g++.dg/asan/large-func-test-1.C: Likewise.
	* gfortran.dg/save_6.f90: Add -flto -g variant of save_5.f90.

Index: early-lto-debug/gcc/dwarf2out.c
===================================================================
*** early-lto-debug.orig/gcc/dwarf2out.c	2017-08-02 10:20:42.693584645 +0200
--- early-lto-debug/gcc/dwarf2out.c	2017-08-03 12:44:13.545059174 +0200
*************** static GTY(()) section *debug_aranges_se
*** 162,167 ****
--- 162,168 ----
  static GTY(()) section *debug_addr_section;
  static GTY(()) section *debug_macinfo_section;
  static const char *debug_macinfo_section_name;
+ static unsigned macinfo_label_base = 1;
  static GTY(()) section *debug_line_section;
  static GTY(()) section *debug_skeleton_line_section;
  static GTY(()) section *debug_loc_section;
*************** static void dwarf2out_begin_function (tr
*** 2690,2695 ****
--- 2691,2700 ----
  static void dwarf2out_end_function (unsigned int);
  static void dwarf2out_register_main_translation_unit (tree unit);
  static void dwarf2out_set_name (tree, tree);
+ static void dwarf2out_register_external_die (tree decl, const char *sym,
+ 					     unsigned HOST_WIDE_INT off);
+ static bool dwarf2out_die_ref_for_decl (tree decl, const char **sym,
+ 					unsigned HOST_WIDE_INT *off);
  
  /* The debug hooks structure.  */
  
*************** const struct gcc_debug_hooks dwarf2_debu
*** 2724,2729 ****
--- 2729,2736 ----
    dwarf2out_late_global_decl,
    dwarf2out_type_decl,		/* type_decl */
    dwarf2out_imported_module_or_decl,
+   dwarf2out_die_ref_for_decl,
+   dwarf2out_register_external_die,
    debug_nothing_tree,		/* deferred_inline_function */
    /* The DWARF 2 backend tries to reduce debugging bloat by not
       emitting the abstract description of inline functions until
*************** const struct gcc_debug_hooks dwarf2_line
*** 2765,2770 ****
--- 2772,2779 ----
    debug_nothing_tree,		         /* late_global_decl */
    debug_nothing_tree_int,		 /* type_decl */
    debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+   debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+   debug_nothing_tree_charstar_uhwi,      /* register_external_die */
    debug_nothing_tree,		         /* deferred_inline_function */
    debug_nothing_tree,		         /* outlining_inline_function */
    debug_nothing_rtx_code_label,	         /* label */
*************** typedef struct GTY((chain_circular ("%h.
*** 2893,2898 ****
--- 2902,2910 ----
    /* Die is used and must not be pruned as unused.  */
    BOOL_BITFIELD die_perennial_p : 1;
    BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
+   /* For an external ref to die_symbol if die_offset contains an extra
+      offset to that symbol.  */
+   BOOL_BITFIELD with_offset : 1;
    /* Whether this DIE was removed from the DIE tree, for example via
       prune_unused_types.  We don't consider those present from the
       DIE lookup routines.  */
*************** new_addr_loc_descr (rtx addr, enum dtpre
*** 3696,3707 ****
--- 3708,3731 ----
  #ifndef DEBUG_DWO_INFO_SECTION
  #define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
  #endif
+ #ifndef DEBUG_LTO_DWO_INFO_SECTION
+ #define DEBUG_LTO_DWO_INFO_SECTION ".gnu.debuglto_.debug_info.dwo"
+ #endif
+ #ifndef DEBUG_LTO_INFO_SECTION
+ #define DEBUG_LTO_INFO_SECTION	".gnu.debuglto_.debug_info"
+ #endif
  #ifndef DEBUG_ABBREV_SECTION
  #define DEBUG_ABBREV_SECTION	".debug_abbrev"
  #endif
  #ifndef DEBUG_DWO_ABBREV_SECTION
  #define DEBUG_DWO_ABBREV_SECTION ".debug_abbrev.dwo"
  #endif
+ #ifndef DEBUG_LTO_DWO_ABBREV_SECTION
+ #define DEBUG_LTO_DWO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev.dwo"
+ #endif
+ #ifndef DEBUG_LTO_ABBREV_SECTION
+ #define DEBUG_LTO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev"
+ #endif
  #ifndef DEBUG_ARANGES_SECTION
  #define DEBUG_ARANGES_SECTION	".debug_aranges"
  #endif
*************** new_addr_loc_descr (rtx addr, enum dtpre
*** 3714,3731 ****
--- 3738,3770 ----
  #ifndef DEBUG_DWO_MACINFO_SECTION
  #define DEBUG_DWO_MACINFO_SECTION      ".debug_macinfo.dwo"
  #endif
+ #ifndef DEBUG_LTO_DWO_MACINFO_SECTION
+ #define DEBUG_LTO_DWO_MACINFO_SECTION  ".gnu.debuglto_.debug_macinfo.dwo"
+ #endif
+ #ifndef DEBUG_LTO_MACINFO_SECTION
+ #define DEBUG_LTO_MACINFO_SECTION      ".gnu.debuglto_.debug_macinfo"
+ #endif
  #ifndef DEBUG_DWO_MACRO_SECTION
  #define DEBUG_DWO_MACRO_SECTION        ".debug_macro.dwo"
  #endif
  #ifndef DEBUG_MACRO_SECTION
  #define DEBUG_MACRO_SECTION	".debug_macro"
  #endif
+ #ifndef DEBUG_LTO_DWO_MACRO_SECTION
+ #define DEBUG_LTO_DWO_MACRO_SECTION    ".gnu.debuglto_.debug_macro.dwo"
+ #endif
+ #ifndef DEBUG_LTO_MACRO_SECTION
+ #define DEBUG_LTO_MACRO_SECTION ".gnu.debuglto_.debug_macro"
+ #endif
  #ifndef DEBUG_LINE_SECTION
  #define DEBUG_LINE_SECTION	".debug_line"
  #endif
  #ifndef DEBUG_DWO_LINE_SECTION
  #define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
  #endif
+ #ifndef DEBUG_LTO_LINE_SECTION
+ #define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
+ #endif
  #ifndef DEBUG_LOC_SECTION
  #define DEBUG_LOC_SECTION	".debug_loc"
  #endif
*************** new_addr_loc_descr (rtx addr, enum dtpre
*** 3754,3765 ****
--- 3793,3813 ----
  #ifndef DEBUG_DWO_STR_OFFSETS_SECTION
  #define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo"
  #endif
+ #ifndef DEBUG_LTO_DWO_STR_OFFSETS_SECTION
+ #define DEBUG_LTO_DWO_STR_OFFSETS_SECTION ".gnu.debuglto_.debug_str_offsets.dwo"
+ #endif
  #ifndef DEBUG_STR_DWO_SECTION
  #define DEBUG_STR_DWO_SECTION   ".debug_str.dwo"
  #endif
+ #ifndef DEBUG_LTO_STR_DWO_SECTION
+ #define DEBUG_LTO_STR_DWO_SECTION ".gnu.debuglto_.debug_str.dwo"
+ #endif
  #ifndef DEBUG_STR_SECTION
  #define DEBUG_STR_SECTION  ".debug_str"
  #endif
+ #ifndef DEBUG_LTO_STR_SECTION
+ #define DEBUG_LTO_STR_SECTION ".gnu.debuglto_.debug_str"
+ #endif
  #ifndef DEBUG_RANGES_SECTION
  #define DEBUG_RANGES_SECTION	".debug_ranges"
  #endif
*************** new_addr_loc_descr (rtx addr, enum dtpre
*** 3784,3789 ****
--- 3832,3841 ----
  /* Section flags for .debug_str.dwo section.  */
  #define DEBUG_STR_DWO_SECTION_FLAGS (SECTION_DEBUG | SECTION_EXCLUDE)
  
+ /* Attribute used to refer to the macro section.  */
+ #define DEBUG_MACRO_ATTRIBUTE (dwarf_version >= 5 ? DW_AT_macros \
+ 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros)
+ 
  /* Labels we insert at beginning sections we can reference instead of
     the section names themselves.  */
  
*************** set_indirect_string (struct indirect_str
*** 4372,4377 ****
--- 4424,4447 ----
      }
  }
  
+ /* A helper function for dwarf2out_finish, called to reset indirect
+    string decisions done for early LTO dwarf output before fat object
+    dwarf output.  */
+ 
+ int
+ reset_indirect_string (indirect_string_node **h, void *)
+ {
+   struct indirect_string_node *node = *h;
+   if (node->form == DW_FORM_strp || node->form == DW_FORM_GNU_str_index)
+     {
+       free (node->label);
+       node->label = NULL;
+       node->form = (dwarf_form) 0;
+       node->index = 0;
+     }
+   return 1;
+ }
+ 
  /* Find out whether a string should be output inline in DIE
     or out-of-line in .debug_str section.  */
  
*************** get_AT_file (dw_die_ref die, enum dwarf_
*** 5017,5022 ****
--- 5087,5107 ----
    return a ? AT_file (a) : NULL;
  }
  
+ /* Returns the ultimate TRANSLATION_UNIT_DECL context of DECL or NULL.  */
+ 
+ static const_tree
+ get_ultimate_context (const_tree decl)
+ {
+   while (decl && TREE_CODE (decl) != TRANSLATION_UNIT_DECL)
+     {
+       if (TREE_CODE (decl) == BLOCK)
+ 	decl = BLOCK_SUPERCONTEXT (decl);
+       else
+ 	decl = get_containing_scope (decl);
+     }
+   return decl;
+ }
+ 
  /* Return TRUE if the language is C++.  */
  
  static inline bool
*************** is_cxx (const_tree decl)
*** 5035,5048 ****
  {
    if (in_lto_p)
      {
!       const_tree context = decl;
!       while (context && TREE_CODE (context) != TRANSLATION_UNIT_DECL)
! 	{
! 	  if (TREE_CODE (context) == BLOCK)
! 	    context = BLOCK_SUPERCONTEXT (context);
! 	  else
! 	    context = get_containing_scope (context);
! 	}
        if (context && TRANSLATION_UNIT_LANGUAGE (context))
  	return strncmp (TRANSLATION_UNIT_LANGUAGE (context), "GNU C++", 7) == 0;
      }
--- 5120,5126 ----
  {
    if (in_lto_p)
      {
!       const_tree context = get_ultimate_context (decl);
        if (context && TRANSLATION_UNIT_LANGUAGE (context))
  	return strncmp (TRANSLATION_UNIT_LANGUAGE (context), "GNU C++", 7) == 0;
      }
*************** is_fortran (void)
*** 5063,5068 ****
--- 5141,5161 ----
  	  || lang == DW_LANG_Fortran08);
  }
  
+ static inline bool
+ is_fortran (const_tree decl)
+ {
+   if (in_lto_p)
+     {
+       const_tree context = get_ultimate_context (decl);
+       if (context && TRANSLATION_UNIT_LANGUAGE (context))
+ 	return (strncmp (TRANSLATION_UNIT_LANGUAGE (context),
+ 			 "GNU Fortran", 11) == 0
+ 		|| strcmp (TRANSLATION_UNIT_LANGUAGE (context),
+ 			   "GNU F77") == 0);
+     }
+   return is_fortran ();
+ }
+ 
  /* Return TRUE if the language is Ada.  */
  
  static inline bool
*************** lookup_decl_die (tree decl)
*** 5407,5412 ****
--- 5500,5683 ----
    return *die;
  }
  
+ 
+ /* For DECL which might have early dwarf output query a SYMBOL + OFFSET
+    style reference.  Return true if we found one refering to a DIE for
+    DECL, otherwise return false.  */
+ 
+ static bool
+ dwarf2out_die_ref_for_decl (tree decl, const char **sym,
+ 			    unsigned HOST_WIDE_INT *off)
+ {
+   dw_die_ref die;
+ 
+   if (flag_wpa && !decl_die_table)
+     return false;
+ 
+   if (TREE_CODE (decl) == BLOCK)
+     die = BLOCK_DIE (decl);
+   else
+     die = lookup_decl_die (decl);
+   if (!die)
+     return false;
+ 
+   /* During WPA stage we currently use DIEs to store the
+      decl <-> label + offset map.  That's quite inefficient but it
+      works for now.  */
+   if (flag_wpa)
+     {
+       dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
+       if (!ref)
+ 	{
+ 	  gcc_assert (die == comp_unit_die ());
+ 	  return false;
+ 	}
+       *off = ref->die_offset;
+       *sym = ref->die_id.die_symbol;
+       return true;
+     }
+ 
+   /* Similar to get_ref_die_offset_label, but using the "correct"
+      label.  */
+   *off = die->die_offset;
+   while (die->die_parent)
+     die = die->die_parent;
+   /* For the containing CU DIE we compute a die_symbol in
+      compute_section_prefix.  */
+   gcc_assert (die->die_tag == DW_TAG_compile_unit
+ 	      && die->die_id.die_symbol != NULL);
+   *sym = die->die_id.die_symbol;
+   return true;
+ }
+ 
+ /* Add a reference of kind ATTR_KIND to a DIE at SYMBOL + OFFSET to DIE.  */
+ 
+ static void
+ add_AT_external_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind,
+ 			 const char *symbol, HOST_WIDE_INT offset)
+ {
+   /* Create a fake DIE that contains the reference.  Don't use
+      new_die because we don't want to end up in the limbo list.  */
+   dw_die_ref ref = ggc_cleared_alloc<die_node> ();
+   ref->die_tag = die->die_tag;
+   ref->die_id.die_symbol = IDENTIFIER_POINTER (get_identifier (symbol));
+   ref->die_offset = offset;
+   ref->with_offset = 1;
+   add_AT_die_ref (die, attr_kind, ref);
+ }
+ 
+ /* Create a DIE for DECL if required and add a reference to a DIE
+    at SYMBOL + OFFSET which contains attributes dumped early.  */
+ 
+ static void
+ dwarf2out_register_external_die (tree decl, const char *sym,
+ 				 unsigned HOST_WIDE_INT off)
+ {
+   if (debug_info_level == DINFO_LEVEL_NONE)
+     return;
+ 
+   if (flag_wpa && !decl_die_table)
+     decl_die_table = hash_table<decl_die_hasher>::create_ggc (1000);
+ 
+   dw_die_ref die
+     = TREE_CODE (decl) == BLOCK ? BLOCK_DIE (decl) : lookup_decl_die (decl);
+   gcc_assert (!die);
+ 
+   tree ctx;
+   dw_die_ref parent = NULL;
+   /* Need to lookup a DIE for the decls context - the containing
+      function or translation unit.  */
+   if (TREE_CODE (decl) == BLOCK)
+     {
+       ctx = BLOCK_SUPERCONTEXT (decl);
+       /* ???  We do not output DIEs for all scopes thus skip as
+ 	 many DIEs as needed.  */
+       while (TREE_CODE (ctx) == BLOCK
+ 	     && !BLOCK_DIE (ctx))
+ 	ctx = BLOCK_SUPERCONTEXT (ctx);
+     }
+   else
+     ctx = DECL_CONTEXT (decl);
+   while (ctx && TYPE_P (ctx))
+     ctx = TYPE_CONTEXT (ctx);
+   if (ctx)
+     {
+       if (TREE_CODE (ctx) == BLOCK)
+ 	parent = BLOCK_DIE (ctx);
+       else if (TREE_CODE (ctx) == TRANSLATION_UNIT_DECL
+ 	       /* Keep the 1:1 association during WPA.  */
+ 	       && !flag_wpa)
+ 	/* Otherwise all late annotations go to the main CU which
+ 	   imports the original CUs.  */
+ 	parent = comp_unit_die ();
+       else if (TREE_CODE (ctx) == FUNCTION_DECL
+ 	       && TREE_CODE (decl) != PARM_DECL
+ 	       && TREE_CODE (decl) != BLOCK)
+ 	/* Leave function local entities parent determination to when
+ 	   we process scope vars.  */
+ 	;
+       else
+ 	parent = lookup_decl_die (ctx);
+     }
+   else
+     /* In some cases the FEs fail to set DECL_CONTEXT properly.
+        Handle this case gracefully by globalizing stuff.  */
+     parent = comp_unit_die ();
+   /* Create a DIE "stub".  */
+   switch (TREE_CODE (decl))
+     {
+     case TRANSLATION_UNIT_DECL:
+       if (! flag_wpa)
+ 	{
+ 	  die = comp_unit_die ();
+ 	  dw_die_ref import = new_die (DW_TAG_imported_unit, die, NULL_TREE);
+ 	  add_AT_external_die_ref (import, DW_AT_import, sym, off);
+ 	  /* We re-target all CU decls to the LTRANS CU DIE, so no need
+ 	     to create a DIE for the original CUs.  */
+ 	  return;
+ 	}
+       /* Keep the 1:1 association during WPA.  */
+       die = new_die (DW_TAG_compile_unit, NULL, decl);
+       break;
+     case NAMESPACE_DECL:
+       if (is_fortran (decl))
+ 	die = new_die (DW_TAG_module, parent, decl);
+       else
+ 	die = new_die (DW_TAG_namespace, parent, decl);
+       break;
+     case FUNCTION_DECL:
+       die = new_die (DW_TAG_subprogram, parent, decl);
+       break;
+     case VAR_DECL:
+       die = new_die (DW_TAG_variable, parent, decl);
+       break;
+     case RESULT_DECL:
+       die = new_die (DW_TAG_variable, parent, decl);
+       break;
+     case PARM_DECL:
+       die = new_die (DW_TAG_formal_parameter, parent, decl);
+       break;
+     case CONST_DECL:
+       die = new_die (DW_TAG_constant, parent, decl);
+       break;
+     case LABEL_DECL:
+       die = new_die (DW_TAG_label, parent, decl);
+       break;
+     case BLOCK:
+       die = new_die (DW_TAG_lexical_block, parent, decl);
+       break;
+     default:
+       gcc_unreachable ();
+     }
+   if (TREE_CODE (decl) == BLOCK)
+     BLOCK_DIE (decl) = die;
+   else
+     equate_decl_number_to_die (decl, die);
+ 
+   /* Add a reference to the DIE providing early debug at $sym + off.  */
+   add_AT_external_die_ref (die, DW_AT_abstract_origin, sym, off);
+ }
+ 
  /* Returns a hash value for X (which really is a var_loc_list).  */
  
  inline hashval_t
*************** print_dw_val (dw_val_node *val, bool rec
*** 5894,5900 ****
  			       die->die_id.die_type_node->signature);
  	    }
  	  else if (die->die_id.die_symbol)
! 	    fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
  	  else
  	    fprintf (outfile, "die -> %ld", die->die_offset);
  	  fprintf (outfile, " (%p)", (void *) die);
--- 6165,6175 ----
  			       die->die_id.die_type_node->signature);
  	    }
  	  else if (die->die_id.die_symbol)
! 	    {
! 	      fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
! 	      if (die->with_offset)
! 		fprintf (outfile, " + %ld", die->die_offset);
! 	    }
  	  else
  	    fprintf (outfile, "die -> %ld", die->die_offset);
  	  fprintf (outfile, " (%p)", (void *) die);
*************** static const char *comdat_symbol_id;
*** 7207,7216 ****
  static unsigned int comdat_symbol_number;
  
  /* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its
!    children, and set comdat_symbol_id accordingly.  */
  
  static void
! compute_section_prefix (dw_die_ref unit_die)
  {
    const char *die_name = get_AT_string (unit_die, DW_AT_name);
    const char *base = die_name ? lbasename (die_name) : "anonymous";
--- 7482,7491 ----
  static unsigned int comdat_symbol_number;
  
  /* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its
!    children, and set die_symbol.  */
  
  static void
! compute_comp_unit_symbol (dw_die_ref unit_die)
  {
    const char *die_name = get_AT_string (unit_die, DW_AT_name);
    const char *base = die_name ? lbasename (die_name) : "anonymous";
*************** compute_section_prefix (dw_die_ref unit_
*** 7229,7235 ****
    unmark_all_dies (unit_die);
    md5_finish_ctx (&ctx, checksum);
  
!   sprintf (name, "%s.", base);
    clean_symbol_name (name);
  
    p = name + strlen (name);
--- 7504,7514 ----
    unmark_all_dies (unit_die);
    md5_finish_ctx (&ctx, checksum);
  
!   /* When we this for comp_unit_die () we have a DW_AT_name that might
!      not start with a letter but with anything valid for filenames and
!      clean_symbol_name doesn't fix that up.  Prepend 'g' if the first
!      character is not a letter.  */
!   sprintf (name, "%s%s.", ISALPHA (*base) ? "" : "g", base);
    clean_symbol_name (name);
  
    p = name + strlen (name);
*************** compute_section_prefix (dw_die_ref unit_
*** 7239,7245 ****
        p += 2;
      }
  
!   comdat_symbol_id = unit_die->die_id.die_symbol = xstrdup (name);
    comdat_symbol_number = 0;
  }
  
--- 7518,7532 ----
        p += 2;
      }
  
!   unit_die->die_id.die_symbol = xstrdup (name);
! }
! 
! static void
! compute_section_prefix (dw_die_ref unit_die)
! {
!   compute_comp_unit_symbol (unit_die);
!   unit_die->comdat_type_p = true;
!   comdat_symbol_id = unit_die->die_id.die_symbol;
    comdat_symbol_number = 0;
  }
  
*************** output_die (dw_die_ref die)
*** 9965,9971 ****
  
    /* If someone in another CU might refer to us, set up a symbol for
       them to point to.  */
!   if (! die->comdat_type_p && die->die_id.die_symbol)
      output_die_symbol (die);
  
    dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
--- 10252,10262 ----
  
    /* If someone in another CU might refer to us, set up a symbol for
       them to point to.  */
!   if (! die->comdat_type_p && die->die_id.die_symbol
!       /* Don't output the symbol twice.  For LTO we want the label
!          on the section beginning, not on the actual DIE.  */
!       && (!flag_generate_lto
! 	  || die->die_tag != DW_TAG_compile_unit))
      output_die_symbol (die);
  
    dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
*************** output_die (dw_die_ref die)
*** 10158,10165 ****
  		    size = DWARF2_ADDR_SIZE;
  		  else
  		    size = DWARF_OFFSET_SIZE;
! 		  dw2_asm_output_offset (size, sym, debug_info_section, "%s",
! 					 name);
  		}
  	    }
  	  else
--- 10449,10468 ----
  		    size = DWARF2_ADDR_SIZE;
  		  else
  		    size = DWARF_OFFSET_SIZE;
! 		  /* ???  We cannot unconditionally output die_offset if
! 		     non-zero - at least -feliminate-dwarf2-dups will
! 		     create references to those DIEs via symbols.  And we
! 		     do not clear its DIE offset after outputting it
! 		     (and the label refers to the actual DIEs, not the
! 		     DWARF CU unit header which is when using label + offset
! 		     would be the correct thing to do).
! 		     ???  This is the reason for the with_offset flag.  */
! 		  if (AT_ref (a)->with_offset)
! 		    dw2_asm_output_offset (size, sym, AT_ref (a)->die_offset,
! 					   debug_info_section, "%s", name);
! 		  else
! 		    dw2_asm_output_offset (size, sym, debug_info_section, "%s",
! 					   name);
  		}
  	    }
  	  else
*************** output_comp_unit (dw_die_ref die, int ou
*** 10385,10391 ****
    calc_die_sizes (die);
  
    oldsym = die->die_id.die_symbol;
!   if (oldsym)
      {
        tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
  
--- 10688,10694 ----
    calc_die_sizes (die);
  
    oldsym = die->die_id.die_symbol;
!   if (oldsym && die->comdat_type_p)
      {
        tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
  
*************** output_comp_unit (dw_die_ref die, int ou
*** 10401,10406 ****
--- 10704,10732 ----
        info_section_emitted = true;
      }
  
+   /* For LTO cross unit DIE refs we want a symbol on the start of the
+      debuginfo section, not on the CU DIE.  */
+   if (flag_generate_lto && oldsym)
+     {
+       /* ???  No way to get visibility assembled without a decl.  */
+       tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ 			      get_identifier (oldsym), char_type_node);
+       TREE_PUBLIC (decl) = true;
+       TREE_STATIC (decl) = true;
+       DECL_ARTIFICIAL (decl) = true;
+       DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+       DECL_VISIBILITY_SPECIFIED (decl) = true;
+       targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
+ #ifdef ASM_WEAKEN_LABEL
+       /* We prefer a .weak because that handles duplicates from duplicate
+          archive members in a graceful way.  */
+       ASM_WEAKEN_LABEL (asm_out_file, oldsym);
+ #else
+       targetm.asm_out.globalize_label (asm_out_file, oldsym);
+ #endif
+       ASM_OUTPUT_LABEL (asm_out_file, oldsym);
+     }
+ 
    /* Output debugging information.  */
    output_compilation_unit_header (dwo_id
  				  ? DW_UT_split_compile : DW_UT_compile);
*************** parameter_ref_descriptor (rtx rtl)
*** 14517,14522 ****
--- 14843,14851 ----
    if (dwarf_strict)
      return NULL;
    gcc_assert (TREE_CODE (DEBUG_PARAMETER_REF_DECL (rtl)) == PARM_DECL);
+   /* With LTO during LTRANS we get the late DIE that refers to the early
+      DIE, thus we add another indirection here.  This seems to confuse
+      gdb enough to make gcc.dg/guality/pr68860-1.c FAIL with LTO.  */
    ref = lookup_decl_die (DEBUG_PARAMETER_REF_DECL (rtl));
    ret = new_loc_descr (DW_OP_GNU_parameter_ref, 0, 0);
    if (ref)
*************** add_abstract_origin_attribute (dw_die_re
*** 20188,20214 ****
  {
    dw_die_ref origin_die = NULL;
  
!   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
! 	 sure that the abstract function has been written out.
! 
! 	 Doing this for nested functions is wrong, however; functions are
! 	 distinct units, and our context might not even be inline.  */
!       tree fn = origin;
! 
!       if (TYPE_P (fn))
! 	fn = TYPE_STUB_DECL (fn);
! 
!       fn = decl_function_context (fn);
!       if (fn)
! 	dwarf2out_abstract_function (fn);
      }
- 
-   if (DECL_P (origin))
-     origin_die = lookup_decl_die (origin);
    else if (TYPE_P (origin))
      origin_die = lookup_type_die (origin);
    else if (TREE_CODE (origin) == BLOCK)
--- 20517,20535 ----
  {
    dw_die_ref origin_die = NULL;
  
!   if (DECL_P (origin))
      {
!       dw_die_ref c;
!       origin_die = lookup_decl_die (origin);
!       /* "Unwrap" the decls DIE which we put in the imported unit context.
!          We are looking for the abstract copy here.  */
!       if (in_lto_p
! 	  && origin_die
! 	  && (c = get_AT_ref (origin_die, DW_AT_abstract_origin))
! 	  /* ???  Identify this better.  */
! 	  && c->with_offset)
! 	origin_die = c;
      }
    else if (TYPE_P (origin))
      origin_die = lookup_type_die (origin);
    else if (TREE_CODE (origin) == BLOCK)
*************** gen_array_type_die (tree type, dw_die_re
*** 20767,20773 ****
        size = int_size_in_bytes (type);
        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)
  	{
  	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
--- 21088,21097 ----
        size = int_size_in_bytes (type);
        if (size >= 0)
  	add_AT_unsigned (array_die, DW_AT_byte_size, size);
!       /* ???  We can't annotate types late, but for LTO we may not
! 	 generate a location early either (gfortran.dg/save_6.f90).  */
!       else if (! (early_dwarf && flag_generate_lto)
! 	       && TYPE_DOMAIN (type) != NULL_TREE
  	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE)
  	{
  	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
*************** gen_formal_parameter_die (tree node, tre
*** 21177,21184 ****
        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))
  	    {
--- 21501,21511 ----
        parm_die = lookup_decl_die (node);
  
        /* If the contexts differ, we may not be talking about the same
! 	 thing.
! 	 ???  When in LTO the DIE parent is the "abstract" copy and the
! 	 context_die is the specification "copy".  But this whole block
! 	 should eventually be no longer needed.  */
!       if (parm_die && parm_die->die_parent != context_die && !in_lto_p)
  	{
  	  if (!DECL_ABSTRACT_P (node))
  	    {
*************** gen_formal_parameter_die (tree node, tre
*** 21188,21205 ****
  	      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)
--- 21515,21521 ----
  	      parm_die = NULL;
  	    }
  	  else
! 	    gcc_unreachable ();
  	}
  
        if (parm_die && parm_die->die_parent == NULL)
*************** gen_type_die_for_member (tree type, tree
*** 21454,21460 ****
  /* 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, 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
--- 21770,21775 ----
*************** set_decl_origin_self (tree decl)
*** 21527,21677 ****
      }
  }
  \f
! /* 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, vec<tree> &abstract_vec)
! {
!   tree local_decl;
!   tree subblock;
!   unsigned int i;
! 
!   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, abstract_vec);
! 
!   for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
!     {
!       local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i);
!       if ((VAR_P (local_decl) && !TREE_STATIC (local_decl))
! 	  || TREE_CODE (local_decl) == PARM_DECL)
! 	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, abstract_vec);
! }
! 
! /* 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, vec<tree> &abstract_vec)
! {
!   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))
! 	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), 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.
! 
!    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)
  {
    dw_die_ref old_die;
-   tree save_fn;
-   tree context;
-   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;
-   struct call_arg_loc_node *old_call_arg_locations;
  
    /* Make sure we have the actual abstract inline, not a clone.  */
    decl = DECL_ORIGIN (decl);
  
    old_die = lookup_decl_die (decl);
!   if (old_die && get_AT (old_die, DW_AT_inline))
      /* We've already generated the abstract instance.  */
      return;
  
!   /* We can be called while recursively when seeing block defining inlined subroutine
!      DIE.  Be sure to not clobber the outer location table nor use it or we would
!      get locations in abstract instantces.  */
!   old_decl_loc_table = decl_loc_table;
!   decl_loc_table = NULL;
!   old_cached_dw_loc_list_table = cached_dw_loc_list_table;
!   cached_dw_loc_list_table = NULL;
!   old_call_arg_locations = call_arg_locations;
!   call_arg_locations = NULL;
!   old_call_site_count = call_site_count;
!   call_site_count = -1;
!   old_tail_call_site_count = tail_call_site_count;
!   tail_call_site_count = -1;
! 
!   /* Be sure we've emitted the in-class declaration DIE (if any) first, so
!      we don't get confused by DECL_ABSTRACT_P.  */
!   if (debug_info_level > DINFO_LEVEL_TERSE)
      {
!       context = decl_class_context (decl);
!       if (context)
! 	gen_type_die_for_member
! 	  (context, decl, decl_function_context (decl) ? NULL : comp_unit_die ());
      }
  
!   /* Pretend we've just finished compiling this function.  */
!   save_fn = current_function_decl;
!   current_function_decl = decl;
! 
!   auto_vec<tree, 64> abstract_vec;
!   set_decl_abstract_flags (decl, abstract_vec);
!   dwarf2out_decl (decl);
!   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;
!   cached_dw_loc_list_table = old_cached_dw_loc_list_table;
!   call_arg_locations = old_call_arg_locations;
!   call_site_count = old_call_site_count;
!   tail_call_site_count = old_tail_call_site_count;
  }
  
  /* Helper function of premark_used_types() which gets called through
--- 21842,21889 ----
      }
  }
  \f
! /* Mark the early DIE for DECL as the abstract instance.  */
  
  static void
  dwarf2out_abstract_function (tree decl)
  {
    dw_die_ref old_die;
  
    /* Make sure we have the actual abstract inline, not a clone.  */
    decl = DECL_ORIGIN (decl);
  
+   if (DECL_IGNORED_P (decl))
+     return;
+ 
    old_die = lookup_decl_die (decl);
!   /* With early debug we always have an old DIE.  */
!   gcc_assert (old_die != NULL);
!   if (get_AT (old_die, DW_AT_inline)
!       || get_AT (old_die, DW_AT_abstract_origin))
      /* We've already generated the abstract instance.  */
      return;
  
!   /* Go ahead and put DW_AT_inline on the DIE.  */
!   if (DECL_DECLARED_INLINE_P (decl))
      {
!       if (cgraph_function_possibly_inlined_p (decl))
! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_inlined);
!       else
! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_declared_not_inlined);
!     }
!   else
!     {
!       if (cgraph_function_possibly_inlined_p (decl))
! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_inlined);
!       else
! 	add_AT_unsigned (old_die, DW_AT_inline, DW_INL_not_inlined);
      }
  
!   if (DECL_DECLARED_INLINE_P (decl)
!       && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
!     add_AT_flag (old_die, DW_AT_artificial, 1);
  
!   set_decl_origin_self (decl);
  }
  
  /* Helper function of premark_used_types() which gets called through
*************** gen_subprogram_die (tree decl, dw_die_re
*** 21883,21889 ****
        && 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));
--- 22095,22101 ----
        && debug_info_level > DINFO_LEVEL_TERSE)
      old_die = force_decl_die (decl);
  
!   /* A concrete instance, tag a new DIE with DW_AT_abstract_origin.  */
    if (origin != NULL)
      {
        gcc_assert (!declaration || local_scope_p (context_die));
*************** gen_subprogram_die (tree decl, dw_die_re
*** 21962,21967 ****
--- 22174,22183 ----
  	       && old_die->die_parent->die_tag == DW_TAG_module)
  	   || context_die == NULL)
  	   && (DECL_ARTIFICIAL (decl)
+ 	       /* The location attributes may be in the abstract origin
+ 		  which in the case of LTO might be not available to
+ 		  look at.  */
+ 	       || get_AT (old_die, DW_AT_abstract_origin)
  	       || (get_AT_file (old_die, DW_AT_decl_file) == file_index
  		   && (get_AT_unsigned (old_die, DW_AT_decl_line)
  		       == (unsigned) s.line)
*************** gen_variable_die (tree decl, tree origin
*** 22828,22833 ****
--- 23044,23067 ----
  	  /* If a DIE was dumped early, it still needs location info.
  	     Skip to where we fill the location bits.  */
  	  var_die = old_die;
+ 
+ 	  /* ???  In LTRANS we cannot annotate early created variably
+ 	     modified type DIEs without copying them and adjusting all
+ 	     references to them.  Thus we dumped them again, also add a
+ 	     reference to them.  */
+ 	  tree type = TREE_TYPE (decl_or_origin);
+ 	  if (in_lto_p
+ 	      && variably_modified_type_p
+ 		   (type, decl_function_context (decl_or_origin)))
+ 	    {
+ 	      if (decl_by_reference_p (decl_or_origin))
+ 		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),
+ 				    false, context_die);
+ 	    }
+ 
  	  goto gen_variable_die_location;
  	}
      }
*************** gen_inlined_subroutine_die (tree stmt, d
*** 23228,23239 ****
    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
-      a die whose origin die hasn't been emitted, and crashing.  */
-   dwarf2out_abstract_function (decl);
- 
    if (! BLOCK_ABSTRACT (stmt))
      {
        dw_die_ref subr_die
--- 23462,23467 ----
*************** process_scope_var (tree stmt, tree decl,
*** 24819,24825 ****
  					     stmt, context_die);
      }
    else
!     gen_decl_die (decl, origin, NULL, context_die);
  }
  
  /* Generate all of the decls declared within a given scope and (recursively)
--- 25047,25068 ----
  					     stmt, context_die);
      }
    else
!     {
!       if (decl && DECL_P (decl))
! 	{
! 	  die = lookup_decl_die (decl);
! 
! 	  /* Early created DIEs do not have a parent as the decls refer
! 	     to the function as DECL_CONTEXT rather than the BLOCK.  */
! 	  if (die && die->die_parent == NULL)
! 	    {
! 	      gcc_assert (in_lto_p);
! 	      add_child_die (context_die, die);
! 	    }
! 	}
! 
!       gen_decl_die (decl, origin, NULL, context_die);
!     }
  }
  
  /* Generate all of the decls declared within a given scope and (recursively)
*************** gen_decl_die (tree decl, tree origin, st
*** 25230,25243 ****
  	/* This is only a declaration.  */;
  #endif
  
        /* If we're emitting a clone, emit info for the abstract instance.  */
!       if (origin || DECL_ORIGIN (decl) != decl)
  	dwarf2out_abstract_function (origin
  				     ? DECL_ORIGIN (origin)
  				     : DECL_ABSTRACT_ORIGIN (decl));
  
!       /* If we're emitting an out-of-line copy of an inline function,
! 	 emit info for the abstract instance and set up to refer to it.  */
        else if (cgraph_function_possibly_inlined_p (decl)
  	       && ! DECL_ABSTRACT_P (decl)
  	       && ! class_or_namespace_scope_p (context_die)
--- 25473,25491 ----
  	/* This is only a declaration.  */;
  #endif
  
+       /* We should have abstract copies already and should not generate
+ 	 stray type DIEs in late LTO dumping.  */
+       if (! early_dwarf)
+ 	;
+ 
        /* If we're emitting a clone, emit info for the abstract instance.  */
!       else if (origin || DECL_ORIGIN (decl) != decl)
  	dwarf2out_abstract_function (origin
  				     ? DECL_ORIGIN (origin)
  				     : DECL_ABSTRACT_ORIGIN (decl));
  
!       /* If we're emitting a possibly inlined function emit it as
!          abstract instance.  */
        else if (cgraph_function_possibly_inlined_p (decl)
  	       && ! DECL_ABSTRACT_P (decl)
  	       && ! class_or_namespace_scope_p (context_die)
*************** gen_decl_die (tree decl, tree origin, st
*** 25245,25254 ****
  		  a declaration.  We must avoid setting DECL_ABSTRACT_ORIGIN in
  		  that case, because that works only if we have a die.  */
  	       && DECL_INITIAL (decl) != NULL_TREE)
! 	{
! 	  dwarf2out_abstract_function (decl);
! 	  set_decl_origin_self (decl);
! 	}
  
        /* Otherwise we're emitting the primary DIE for this decl.  */
        else if (debug_info_level > DINFO_LEVEL_TERSE)
--- 25493,25499 ----
  		  a declaration.  We must avoid setting DECL_ABSTRACT_ORIGIN in
  		  that case, because that works only if we have a die.  */
  	       && DECL_INITIAL (decl) != NULL_TREE)
! 	dwarf2out_abstract_function (decl);
  
        /* Otherwise we're emitting the primary DIE for this decl.  */
        else if (debug_info_level > DINFO_LEVEL_TERSE)
*************** gen_decl_die (tree decl, tree origin, st
*** 25318,25337 ****
        if (debug_info_level <= DINFO_LEVEL_TERSE)
  	break;
  
!       /* Output any DIEs that are needed to specify the type of this data
! 	 object.  */
!       if (decl_by_reference_p (decl_or_origin))
! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
!       else
! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
  
!       /* And its containing type.  */
!       class_origin = decl_class_context (decl_or_origin);
!       if (class_origin != NULL_TREE)
! 	gen_type_die_for_member (class_origin, decl_or_origin, context_die);
  
!       /* And its containing namespace.  */
!       context_die = declare_in_namespace (decl_or_origin, context_die);
  
        /* Now output the DIE to represent the data object itself.  This gets
  	 complicated because of the possibility that the VAR_DECL really
--- 25563,25598 ----
        if (debug_info_level <= DINFO_LEVEL_TERSE)
  	break;
  
!       /* Avoid generating stray type DIEs during late dwarf dumping.
!          All types have been dumped early.  */
!       if (early_dwarf
! 	  /* ???  But in LTRANS we cannot annotate early created variably
! 	     modified type DIEs without copying them and adjusting all
! 	     references to them.  Dump them again as happens for inlining
! 	     which copies both the decl and the types.  */
! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
! 	     in VLA bound information for example.  */
! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
! 						current_function_decl)))
! 	{
! 	  /* Output any DIEs that are needed to specify the type of this data
! 	     object.  */
! 	  if (decl_by_reference_p (decl_or_origin))
! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
! 	  else
! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
! 	}
  
!       if (early_dwarf)
! 	{
! 	  /* And its containing type.  */
! 	  class_origin = decl_class_context (decl_or_origin);
! 	  if (class_origin != NULL_TREE)
! 	    gen_type_die_for_member (class_origin, decl_or_origin, context_die);
  
! 	  /* And its containing namespace.  */
! 	  context_die = declare_in_namespace (decl_or_origin, context_die);
! 	}
  
        /* Now output the DIE to represent the data object itself.  This gets
  	 complicated because of the possibility that the VAR_DECL really
*************** gen_decl_die (tree decl, tree origin, st
*** 25361,25370 ****
        break;
  
      case PARM_DECL:
!       if (DECL_BY_REFERENCE (decl_or_origin))
! 	gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
!       else
! 	gen_type_die (TREE_TYPE (decl_or_origin), context_die);
        return gen_formal_parameter_die (decl, origin,
  				       true /* Emit name attribute.  */,
  				       context_die);
--- 25622,25644 ----
        break;
  
      case PARM_DECL:
!       /* Avoid generating stray type DIEs during late dwarf dumping.
!          All types have been dumped early.  */
!       if (early_dwarf
! 	  /* ???  But in LTRANS we cannot annotate early created variably
! 	     modified type DIEs without copying them and adjusting all
! 	     references to them.  Dump them again as happens for inlining
! 	     which copies both the decl and the types.  */
! 	  /* ???  And even non-LTO needs to re-visit type DIEs to fill
! 	     in VLA bound information for example.  */
! 	  || (decl && variably_modified_type_p (TREE_TYPE (decl),
! 						current_function_decl)))
! 	{
! 	  if (DECL_BY_REFERENCE (decl_or_origin))
! 	    gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
! 	  else
! 	    gen_type_die (TREE_TYPE (decl_or_origin), context_die);
! 	}
        return gen_formal_parameter_die (decl, origin,
  				       true /* Emit name attribute.  */,
  				       context_die);
*************** dwarf2out_early_global_decl (tree decl)
*** 25436,25441 ****
--- 25710,25725 ----
  	      dwarf2out_decl (context);
  	    }
  
+ 	  /* Emit an abstract origin of a function first.  This happens
+ 	     with C++ constructor clones for example and makes
+ 	     dwarf2out_abstract_function happy which requires the early
+ 	     DIE of the abstract instance to be present.  */
+ 	  if (DECL_ABSTRACT_ORIGIN (decl))
+ 	    {
+ 	      current_function_decl = DECL_ABSTRACT_ORIGIN (decl);
+ 	      dwarf2out_decl (DECL_ABSTRACT_ORIGIN (decl));
+ 	    }
+ 
  	  current_function_decl = decl;
  	}
        dwarf2out_decl (decl);
*************** dwarf2out_late_global_decl (tree decl)
*** 25457,25463 ****
      {
        dw_die_ref die = lookup_decl_die (decl);
  
!       /* We have to generate early debug late for LTO.  */
        if (! die && in_lto_p)
  	{
  	  dwarf2out_decl (decl);
--- 25741,25749 ----
      {
        dw_die_ref die = lookup_decl_die (decl);
  
!       /* We may have to generate early debug late for LTO in case debug
!          was not enabled at compile-time or the target doesn't support
! 	 the LTO early debug scheme.  */
        if (! die && in_lto_p)
  	{
  	  dwarf2out_decl (decl);
*************** output_macinfo_op (macinfo_entry *ref)
*** 26811,26817 ****
      case DW_MACRO_import:
        dw2_asm_output_data (1, ref->code, "Import");
        ASM_GENERATE_INTERNAL_LABEL (label,
! 				   DEBUG_MACRO_SECTION_LABEL, ref->lineno);
        dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
        break;
      default:
--- 27097,27104 ----
      case DW_MACRO_import:
        dw2_asm_output_data (1, ref->code, "Import");
        ASM_GENERATE_INTERNAL_LABEL (label,
! 				   DEBUG_MACRO_SECTION_LABEL,
! 				   ref->lineno + macinfo_label_base);
        dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
        break;
      default:
*************** save_macinfo_strings (void)
*** 26985,26991 ****
  /* Output macinfo section(s).  */
  
  static void
! output_macinfo (void)
  {
    unsigned i;
    unsigned long length = vec_safe_length (macinfo_table);
--- 27272,27278 ----
  /* Output macinfo section(s).  */
  
  static void
! output_macinfo (const char *debug_line_label, bool early_lto_debug)
  {
    unsigned i;
    unsigned long length = vec_safe_length (macinfo_table);
*************** output_macinfo (void)
*** 27005,27011 ****
  
    /* AIX Assembler inserts the length, so adjust the reference to match the
       offset expected by debuggers.  */
!   strcpy (dl_section_ref, debug_line_section_label);
    if (XCOFF_DEBUGGING_INFO)
      strcat (dl_section_ref, DWARF_INITIAL_LENGTH_SIZE_STR);
  
--- 27292,27298 ----
  
    /* AIX Assembler inserts the length, so adjust the reference to match the
       offset expected by debuggers.  */
!   strcpy (dl_section_ref, debug_line_label);
    if (XCOFF_DEBUGGING_INFO)
      strcat (dl_section_ref, DWARF_INITIAL_LENGTH_SIZE_STR);
  
*************** output_macinfo (void)
*** 27018,27026 ****
  	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
        else
  	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
!       dw2_asm_output_offset (DWARF_OFFSET_SIZE,
!                              (!dwarf_split_debug_info ? dl_section_ref
!                               : debug_skeleton_line_section_label),
                               debug_line_section, NULL);
      }
  
--- 27305,27311 ----
  	dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
        else
  	dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present");
!       dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_line_label,
                               debug_line_section, NULL);
      }
  
*************** output_macinfo (void)
*** 27074,27079 ****
--- 27359,27368 ----
    if (!macinfo_htab)
      return;
  
+   /* Save the number of transparent includes so we can adjust the
+      label number for the fat LTO object DWARF.  */
+   unsigned macinfo_label_base_adj = macinfo_htab->elements ();
+ 
    delete macinfo_htab;
    macinfo_htab = NULL;
  
*************** output_macinfo (void)
*** 27093,27103 ****
  	  dw2_asm_output_data (1, 0, "End compilation unit");
  	  targetm.asm_out.named_section (debug_macinfo_section_name,
  					 SECTION_DEBUG
! 					 | SECTION_LINKONCE,
  					 comdat_key);
  	  ASM_GENERATE_INTERNAL_LABEL (label,
  				       DEBUG_MACRO_SECTION_LABEL,
! 				       ref->lineno);
  	  ASM_OUTPUT_LABEL (asm_out_file, label);
  	  ref->code = 0;
  	  ref->info = NULL;
--- 27382,27394 ----
  	  dw2_asm_output_data (1, 0, "End compilation unit");
  	  targetm.asm_out.named_section (debug_macinfo_section_name,
  					 SECTION_DEBUG
! 					 | SECTION_LINKONCE
! 					 | (early_lto_debug
! 					    ? SECTION_EXCLUDE : 0),
  					 comdat_key);
  	  ASM_GENERATE_INTERNAL_LABEL (label,
  				       DEBUG_MACRO_SECTION_LABEL,
! 				       ref->lineno + macinfo_label_base);
  	  ASM_OUTPUT_LABEL (asm_out_file, label);
  	  ref->code = 0;
  	  ref->info = NULL;
*************** output_macinfo (void)
*** 27118,27226 ****
        default:
  	gcc_unreachable ();
        }
  }
  
! /* Initialize the various sections and labels for dwarf output.  */
  
  static void
! init_sections_and_labels (void)
  {
!   if (!dwarf_split_debug_info)
      {
!       debug_info_section = get_section (DEBUG_INFO_SECTION,
!                                         SECTION_DEBUG, NULL);
!       debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
!                                           SECTION_DEBUG, NULL);
!       debug_loc_section = get_section (dwarf_version >= 5
! 				       ? DEBUG_LOCLISTS_SECTION
! 				       : DEBUG_LOC_SECTION,
!                                        SECTION_DEBUG, NULL);
!       debug_macinfo_section_name
! 	= (dwarf_strict && dwarf_version < 5)
! 	  ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
!       debug_macinfo_section = get_section (debug_macinfo_section_name,
! 					   SECTION_DEBUG, NULL);
      }
    else
      {
!       debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
!                                         SECTION_DEBUG | SECTION_EXCLUDE, NULL);
!       debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
!                                           SECTION_DEBUG | SECTION_EXCLUDE,
!                                           NULL);
!       debug_addr_section = get_section (DEBUG_ADDR_SECTION,
!                                         SECTION_DEBUG, NULL);
!       debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
!                                                  SECTION_DEBUG, NULL);
!       debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
!                                                    SECTION_DEBUG, NULL);
!       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
!                                   DEBUG_SKELETON_ABBREV_SECTION_LABEL, 0);
! 
!       /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
!          the main .o, but the skeleton_line goes into the split off dwo.  */
!       debug_skeleton_line_section
!         = get_section (DEBUG_DWO_LINE_SECTION,
! 		       SECTION_DEBUG | SECTION_EXCLUDE, NULL);
!       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
!                                    DEBUG_SKELETON_LINE_SECTION_LABEL, 0);
!       debug_str_offsets_section = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
!                                                SECTION_DEBUG | SECTION_EXCLUDE,
!                                                NULL);
!       ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
!                                    DEBUG_SKELETON_INFO_SECTION_LABEL, 0);
!       debug_loc_section = get_section (dwarf_version >= 5
! 				       ? DEBUG_DWO_LOCLISTS_SECTION
! 				       : DEBUG_DWO_LOC_SECTION,
!                                        SECTION_DEBUG | SECTION_EXCLUDE, NULL);
!       debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
!                                            DEBUG_STR_DWO_SECTION_FLAGS, NULL);
!       debug_macinfo_section_name
! 	= (dwarf_strict && dwarf_version < 5)
! 	  ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
!       debug_macinfo_section = get_section (debug_macinfo_section_name,
  					   SECTION_DEBUG | SECTION_EXCLUDE,
  					   NULL);
!     }
!   debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
! 				       SECTION_DEBUG, NULL);
!   debug_line_section = get_section (DEBUG_LINE_SECTION,
! 				    SECTION_DEBUG, NULL);
!   debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
! 					SECTION_DEBUG, NULL);
!   debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
  					SECTION_DEBUG, NULL);
!   debug_str_section = get_section (DEBUG_STR_SECTION,
! 				   DEBUG_STR_SECTION_FLAGS, NULL);
!   if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
!     debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
! 					  DEBUG_STR_SECTION_FLAGS, NULL);
! 
!   debug_ranges_section = get_section (dwarf_version >= 5
! 				      ? DEBUG_RNGLISTS_SECTION
! 				      : DEBUG_RANGES_SECTION,
! 				      SECTION_DEBUG, NULL);
!   debug_frame_section = get_section (DEBUG_FRAME_SECTION,
! 				     SECTION_DEBUG, NULL);
  
    ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
! 			       DEBUG_ABBREV_SECTION_LABEL, 0);
    ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
! 			       DEBUG_INFO_SECTION_LABEL, 0);
    ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
! 			       DEBUG_LINE_SECTION_LABEL, 0);
    ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
! 			       DEBUG_RANGES_SECTION_LABEL, 0);
    if (dwarf_version >= 5 && dwarf_split_debug_info)
      ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
! 				 DEBUG_RANGES_SECTION_LABEL, 1);
    ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
!                                DEBUG_ADDR_SECTION_LABEL, 0);
    ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
  			       (dwarf_strict && dwarf_version < 5)
  			       ? DEBUG_MACINFO_SECTION_LABEL
! 			       : DEBUG_MACRO_SECTION_LABEL, 0);
!   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0);
  }
  
  /* Set up for Dwarf output at the start of compilation.  */
--- 27409,27600 ----
        default:
  	gcc_unreachable ();
        }
+ 
+   macinfo_label_base += macinfo_label_base_adj;
  }
  
! /* Initialize the various sections and labels for dwarf output and prefix
!    them with PREFIX if non-NULL.  */
  
  static void
! init_sections_and_labels (bool early_lto_debug)
  {
!   /* As we may get called multiple times have a generation count for labels.  */
!   static unsigned generation = 0;
! 
!   if (early_lto_debug)
      {
!       if (!dwarf_split_debug_info)
! 	{
! 	  debug_info_section = get_section (DEBUG_LTO_INFO_SECTION,
! 					    SECTION_DEBUG | SECTION_EXCLUDE,
! 					    NULL);
! 	  debug_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
! 					      SECTION_DEBUG | SECTION_EXCLUDE,
! 					      NULL);
! 	  debug_macinfo_section_name = ((dwarf_strict && dwarf_version < 5)
! 					? DEBUG_LTO_MACINFO_SECTION
! 					: DEBUG_LTO_MACRO_SECTION);
! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
! 					       SECTION_DEBUG
! 					       | SECTION_EXCLUDE, NULL);
! 	  /* For macro info we have to refer to a debug_line section, so similar
! 	     to split-dwarf emit a skeleton one for early debug.  */
! 	  debug_skeleton_line_section
! 	    = get_section (DEBUG_LTO_LINE_SECTION,
! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
! 				       generation);
! 	}
!       else
! 	{
! 	  /* ???  Which of the following do we need early?  */
! 	  debug_info_section = get_section (DEBUG_LTO_DWO_INFO_SECTION,
! 					    SECTION_DEBUG | SECTION_EXCLUDE,
! 					    NULL);
! 	  debug_abbrev_section = get_section (DEBUG_LTO_DWO_ABBREV_SECTION,
! 					      SECTION_DEBUG | SECTION_EXCLUDE,
! 					      NULL);
! 	  debug_skeleton_info_section = get_section (DEBUG_LTO_INFO_SECTION,
! 						     SECTION_DEBUG
! 						     | SECTION_EXCLUDE, NULL);
! 	  debug_skeleton_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
! 						       SECTION_DEBUG
! 						       | SECTION_EXCLUDE, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
! 				       generation);
! 
! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
! 	     the main .o, but the skeleton_line goes into the split off dwo.  */
! 	  debug_skeleton_line_section
! 	    = get_section (DEBUG_LTO_LINE_SECTION,
! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
! 				       generation);
! 	  debug_str_offsets_section
! 	    = get_section (DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
! 			   SECTION_DEBUG | SECTION_EXCLUDE,
! 			   NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
! 				       generation);
! 	  debug_str_dwo_section = get_section (DEBUG_LTO_STR_DWO_SECTION,
! 					       DEBUG_STR_DWO_SECTION_FLAGS, NULL);
! 	  debug_macinfo_section_name
! 	    = (dwarf_strict
! 	       ? DEBUG_LTO_DWO_MACINFO_SECTION : DEBUG_LTO_DWO_MACRO_SECTION);
! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
! 					       SECTION_DEBUG | SECTION_EXCLUDE,
! 					       NULL);
! 	}
!       debug_str_section = get_section (DEBUG_LTO_STR_SECTION,
! 				       DEBUG_STR_SECTION_FLAGS
! 				       | SECTION_EXCLUDE, NULL);
      }
    else
      {
!       if (!dwarf_split_debug_info)
! 	{
! 	  debug_info_section = get_section (DEBUG_INFO_SECTION,
! 					    SECTION_DEBUG, NULL);
! 	  debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
! 					      SECTION_DEBUG, NULL);
! 	  debug_loc_section = get_section (DEBUG_LOC_SECTION,
! 					   SECTION_DEBUG, NULL);
! 	  debug_macinfo_section_name
! 	      = dwarf_strict ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
! 					       SECTION_DEBUG, NULL);
! 	}
!       else
! 	{
! 	  debug_info_section = get_section (DEBUG_DWO_INFO_SECTION,
! 					    SECTION_DEBUG | SECTION_EXCLUDE,
! 					    NULL);
! 	  debug_abbrev_section = get_section (DEBUG_DWO_ABBREV_SECTION,
! 					      SECTION_DEBUG | SECTION_EXCLUDE,
! 					      NULL);
! 	  debug_addr_section = get_section (DEBUG_ADDR_SECTION,
! 					    SECTION_DEBUG, NULL);
! 	  debug_skeleton_info_section = get_section (DEBUG_INFO_SECTION,
! 						     SECTION_DEBUG, NULL);
! 	  debug_skeleton_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
! 						       SECTION_DEBUG, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
! 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
! 				       generation);
! 
! 	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections
! 	     stay in the main .o, but the skeleton_line goes into the
! 	     split off dwo.  */
! 	  debug_skeleton_line_section
! 	      = get_section (DEBUG_DWO_LINE_SECTION,
! 			     SECTION_DEBUG | SECTION_EXCLUDE, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_line_section_label,
! 				       DEBUG_SKELETON_LINE_SECTION_LABEL,
! 				       generation);
! 	  debug_str_offsets_section
! 	    = get_section (DEBUG_DWO_STR_OFFSETS_SECTION,
! 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
! 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
! 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
! 				       generation);
! 	  debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION,
  					   SECTION_DEBUG | SECTION_EXCLUDE,
  					   NULL);
! 	  debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
! 					       DEBUG_STR_DWO_SECTION_FLAGS,
! 					       NULL);
! 	  debug_macinfo_section_name
! 	    = (dwarf_strict && dwarf_version < 5)
! 	      ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
! 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
! 					       SECTION_DEBUG | SECTION_EXCLUDE,
! 					       NULL);
! 	}
!       debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
! 					   SECTION_DEBUG, NULL);
!       debug_line_section = get_section (DEBUG_LINE_SECTION,
  					SECTION_DEBUG, NULL);
!       debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
! 					    SECTION_DEBUG, NULL);
!       debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
! 					    SECTION_DEBUG, NULL);
!       debug_str_section = get_section (DEBUG_STR_SECTION,
! 				       DEBUG_STR_SECTION_FLAGS, NULL);
!       debug_ranges_section = get_section (dwarf_version >= 5
! 					  ? DEBUG_RNGLISTS_SECTION
! 					  : DEBUG_RANGES_SECTION,
! 					  SECTION_DEBUG, NULL);
!       debug_frame_section = get_section (DEBUG_FRAME_SECTION,
! 					 SECTION_DEBUG, NULL);
!     }
  
    ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
! 			       DEBUG_ABBREV_SECTION_LABEL, generation);
    ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
! 			       DEBUG_INFO_SECTION_LABEL, generation);
!   info_section_emitted = false;
    ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
! 			       DEBUG_LINE_SECTION_LABEL, generation);
    ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
! 			       DEBUG_RANGES_SECTION_LABEL, generation);
    if (dwarf_version >= 5 && dwarf_split_debug_info)
      ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
! 				 DEBUG_RANGES_SECTION_LABEL, 2 + generation);
    ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
!                                DEBUG_ADDR_SECTION_LABEL, generation);
    ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
  			       (dwarf_strict && dwarf_version < 5)
  			       ? DEBUG_MACINFO_SECTION_LABEL
! 			       : DEBUG_MACRO_SECTION_LABEL, generation);
!   ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL,
! 			       generation);
! 
!   ++generation;
  }
  
  /* Set up for Dwarf output at the start of compilation.  */
*************** flush_limbo_die_list (void)
*** 29567,29572 ****
--- 29941,29962 ----
      }
  }
  
+ /* Reset DIEs so we can output them again.  */
+ 
+ static void
+ reset_dies (dw_die_ref die)
+ {
+   dw_die_ref c;
+ 
+   /* Remove stuff we re-generate.  */
+   die->die_mark = 0;
+   die->die_offset = 0;
+   die->die_abbrev = 0;
+   remove_AT (die, DW_AT_sibling);
+ 
+   FOR_EACH_CHILD (die, c, reset_dies (c));
+ }
+ 
  /* Output stuff that dwarf requires at the end of every file,
     and generate the DWARF-2 debugging info.  */
  
*************** dwarf2out_finish (const char *)
*** 29594,29599 ****
--- 29984,30029 ----
  
    gen_remaining_tmpl_value_param_die_attribute ();
  
+   if (flag_generate_lto)
+     {
+       gcc_assert (flag_fat_lto_objects);
+ 
+       /* Prune stuff so that dwarf2out_finish runs successfully
+ 	 for the fat part of the object.  */
+       reset_dies (comp_unit_die ());
+       for (limbo_die_node *node = cu_die_list; node; node = node->next)
+ 	reset_dies (node->die);
+ 
+       hash_table<comdat_type_hasher> comdat_type_table (100);
+       for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
+ 	{
+ 	  comdat_type_node **slot
+ 	      = comdat_type_table.find_slot (ctnode, INSERT);
+ 
+ 	  /* Don't reset types twice.  */
+ 	  if (*slot != HTAB_EMPTY_ENTRY)
+ 	    continue;
+ 
+ 	  /* Add a pointer to the line table for the main compilation unit
+ 	     so that the debugger can make sense of DW_AT_decl_file
+ 	     attributes.  */
+ 	  if (debug_info_level >= DINFO_LEVEL_TERSE)
+ 	    reset_dies (ctnode->root_die);
+ 
+ 	  *slot = ctnode;
+ 	}
+ 
+       /* Reset die CU symbol so we don't output it twice.  */
+       comp_unit_die ()->die_id.die_symbol = NULL;
+ 
+       /* Remove DW_AT_macro from the early output.  */
+       if (have_macinfo)
+ 	remove_AT (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE);
+ 
+       /* Remove indirect string decisions.  */
+       debug_str_hash->traverse<void *, reset_indirect_string> (NULL);
+     }
+ 
  #if ENABLE_ASSERT_CHECKING
    {
      dw_die_ref die = comp_unit_die (), c;
*************** dwarf2out_finish (const char *)
*** 29604,29610 ****
    move_marked_base_types ();
  
    /* Initialize sections and labels used for actual assembler output.  */
!   init_sections_and_labels ();
  
    /* Traverse the DIE's and add sibling attributes to those DIE's that
       have children.  */
--- 30034,30040 ----
    move_marked_base_types ();
  
    /* Initialize sections and labels used for actual assembler output.  */
!   init_sections_and_labels (false);
  
    /* Traverse the DIE's and add sibling attributes to those DIE's that
       have children.  */
*************** dwarf2out_finish (const char *)
*** 29705,29713 ****
  		    dl_section_ref);
  
    if (have_macinfo)
!     add_AT_macptr (comp_unit_die (),
! 		   dwarf_version >= 5 ? DW_AT_macros
! 		   : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
  		   macinfo_section_label);
  
    if (dwarf_split_debug_info)
--- 30135,30141 ----
  		    dl_section_ref);
  
    if (have_macinfo)
!     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
  		   macinfo_section_label);
  
    if (dwarf_split_debug_info)
*************** dwarf2out_finish (const char *)
*** 29912,29918 ****
      {
        switch_to_section (debug_macinfo_section);
        ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
!       output_macinfo ();
        dw2_asm_output_data (1, 0, "End compilation unit");
      }
  
--- 30340,30347 ----
      {
        switch_to_section (debug_macinfo_section);
        ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
!       output_macinfo (!dwarf_split_debug_info ? debug_line_section_label
! 		      : debug_skeleton_line_section_label, false);
        dw2_asm_output_data (1, 0, "End compilation unit");
      }
  
*************** note_variable_value_in_expr (dw_die_ref
*** 30133,30138 ****
--- 30562,30581 ----
        {
  	tree decl = loc->dw_loc_oprnd1.v.val_decl_ref;
  	dw_die_ref ref = lookup_decl_die (decl);
+ 	if (! ref && flag_generate_lto)
+ 	  {
+ 	    /* ???  This is somewhat a hack because we do not create DIEs
+ 	       for variables not in BLOCK trees early but when generating
+ 	       early LTO output we need the dw_val_class_decl_ref to be
+ 	       fully resolved.  For fat LTO objects we'd also like to
+ 	       undo this after LTO dwarf output.  */
+ 	    gcc_assert (DECL_CONTEXT (decl));
+ 	    dw_die_ref ctx = lookup_decl_die (DECL_CONTEXT (decl));
+ 	    gcc_assert (ctx != NULL);
+ 	    gen_decl_die (decl, NULL_TREE, NULL, ctx);
+ 	    ref = lookup_decl_die (decl);
+ 	    gcc_assert (ref != NULL);
+ 	  }
  	if (ref)
  	  {
  	    loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
*************** dwarf2out_early_finish (const char *file
*** 30343,30348 ****
--- 30786,30904 ----
  
    /* The early debug phase is now finished.  */
    early_dwarf_finished = true;
+ 
+   /* Do not generate DWARF assembler now when not producing LTO bytecode.  */
+   if (!flag_generate_lto)
+     return;
+ 
+   /* Now as we are going to output for LTO initialize sections and labels
+      to the LTO variants.  We don't need a random-seed postfix as other
+      LTO sections as linking the LTO debug sections into one in a partial
+      link is fine.  */
+   init_sections_and_labels (true);
+ 
+   /* The output below is modeled after dwarf2out_finish with all
+      location related output removed and some LTO specific changes.
+      Some refactoring might make both smaller and easier to match up.  */
+ 
+   /* Traverse the DIE's and add add sibling attributes to those DIE's
+      that have children.  */
+   add_sibling_attributes (comp_unit_die ());
+   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
+     add_sibling_attributes (node->die);
+   for (comdat_type_node *ctnode = comdat_type_list;
+        ctnode != NULL; ctnode = ctnode->next)
+     add_sibling_attributes (ctnode->root_die);
+ 
+   if (have_macinfo)
+     add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE,
+ 		   macinfo_section_label);
+ 
+   save_macinfo_strings ();
+ 
+   /* Output all of the compilation units.  We put the main one last so that
+      the offsets are available to output_pubnames.  */
+   for (limbo_die_node *node = limbo_die_list; node; node = node->next)
+     output_comp_unit (node->die, 0, NULL);
+ 
+   hash_table<comdat_type_hasher> comdat_type_table (100);
+   for (comdat_type_node *ctnode = comdat_type_list;
+        ctnode != NULL; ctnode = ctnode->next)
+     {
+       comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT);
+ 
+       /* Don't output duplicate types.  */
+       if (*slot != HTAB_EMPTY_ENTRY)
+         continue;
+ 
+       /* Add a pointer to the line table for the main compilation unit
+          so that the debugger can make sense of DW_AT_decl_file
+          attributes.  */
+       if (debug_info_level >= DINFO_LEVEL_TERSE)
+         add_AT_lineptr (ctnode->root_die, DW_AT_stmt_list,
+                         (!dwarf_split_debug_info
+                          ? debug_line_section_label
+                          : debug_skeleton_line_section_label));
+ 
+       output_comdat_type_unit (ctnode);
+       *slot = ctnode;
+     }
+ 
+   /* The AT_pubnames attribute needs to go in all skeleton dies, including
+      both the main_cu and all skeleton TUs.  Making this call unconditional
+      would end up either adding a second copy of the AT_pubnames attribute, or
+      requiring a special case in add_top_level_skeleton_die_attrs.  */
+   if (!dwarf_split_debug_info)
+     add_AT_pubnames (comp_unit_die ());
+ 
+   /* Stick a unique symbol to the main debuginfo section.  */
+   compute_comp_unit_symbol (comp_unit_die ());
+ 
+   /* Output the main compilation unit.  We always need it if only for
+      the CU symbol.  */
+   output_comp_unit (comp_unit_die (), true, NULL);
+ 
+   /* Output the abbreviation table.  */
+   if (vec_safe_length (abbrev_die_table) != 1)
+     {
+       switch_to_section (debug_abbrev_section);
+       ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
+       output_abbrev_section ();
+     }
+ 
+   /* Have to end the macro section.  */
+   if (have_macinfo)
+     {
+       /* We have to save macinfo state if we need to output it again
+ 	 for the FAT part of the object.  */
+       vec<macinfo_entry, va_gc> *saved_macinfo_table = macinfo_table;
+       if (flag_fat_lto_objects)
+ 	macinfo_table = macinfo_table->copy ();
+ 
+       switch_to_section (debug_macinfo_section);
+       ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
+       output_macinfo (debug_skeleton_line_section_label, true);
+       dw2_asm_output_data (1, 0, "End compilation unit");
+ 
+       /* Emit a skeleton debug_line section.  */
+       switch_to_section (debug_skeleton_line_section);
+       ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_line_section_label);
+       output_line_info (true);
+ 
+       if (flag_fat_lto_objects)
+ 	{
+ 	  vec_free (macinfo_table);
+ 	  macinfo_table = saved_macinfo_table;
+ 	}
+     }
+ 
+ 
+   /* If we emitted any indirect strings, output the string table too.  */
+   if (debug_str_hash || skeleton_debug_str_hash)
+     output_indirect_strings ();
+ 
+   /* Switch back to the text section.  */
+   switch_to_section (text_section);
  }
  
  /* Reset all state within dwarf2out.c so that we can rerun the compiler
Index: early-lto-debug/gcc/debug.h
===================================================================
*** early-lto-debug.orig/gcc/debug.h	2017-08-02 10:21:25.118319347 +0200
--- early-lto-debug/gcc/debug.h	2017-08-02 10:21:39.142562230 +0200
*************** struct gcc_debug_hooks
*** 148,153 ****
--- 148,161 ----
  				    tree context, bool child,
  				    bool implicit);
  
+   /* Return true if a DIE for the tree is available and return a symbol
+      and offset that can be used to refer to it externally.  */
+   bool (* die_ref_for_decl) (tree, const char **, unsigned HOST_WIDE_INT *);
+ 
+   /* Early debug information for the tree is available at symbol plus
+      offset externally.  */
+   void (* register_external_die) (tree, const char *, unsigned HOST_WIDE_INT);
+ 
    /* DECL is an inline function, whose body is present, but which is
       not being output at this point.  */
    void (* deferred_inline_function) (tree decl);
*************** extern void debug_nothing_tree_tree_tree
*** 212,217 ****
--- 220,229 ----
  extern bool debug_true_const_tree (const_tree);
  extern void debug_nothing_rtx_insn (rtx_insn *);
  extern void debug_nothing_rtx_code_label (rtx_code_label *);
+ extern bool debug_false_tree_charstarstar_uhwistar (tree, const char **,
+ 						    unsigned HOST_WIDE_INT *);
+ extern void debug_nothing_tree_charstar_uhwi (tree, const char *,
+ 					      unsigned HOST_WIDE_INT);
  
  /* Hooks for various debug formats.  */
  extern const struct gcc_debug_hooks do_nothing_debug_hooks;
Index: early-lto-debug/gcc/debug.c
===================================================================
*** early-lto-debug.orig/gcc/debug.c	2017-08-02 10:21:25.118319347 +0200
--- early-lto-debug/gcc/debug.c	2017-08-02 10:25:56.415019203 +0200
*************** const struct gcc_debug_hooks do_nothing_
*** 48,53 ****
--- 48,55 ----
    debug_nothing_tree,	         	 /* late_global_decl */
    debug_nothing_tree_int,		 /* type_decl */
    debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+   debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+   debug_nothing_tree_charstar_uhwi,      /* register_external_die */
    debug_nothing_tree,		         /* deferred_inline_function */
    debug_nothing_tree,		         /* outlining_inline_function */
    debug_nothing_rtx_code_label,	         /* label */
*************** debug_nothing_tree_int (tree decl ATTRIB
*** 147,149 ****
--- 149,164 ----
  			int local ATTRIBUTE_UNUSED)
  {
  }
+ 
+ bool
+ debug_false_tree_charstarstar_uhwistar (tree, const char **,
+ 					unsigned HOST_WIDE_INT *)
+ {
+   return false;
+ }
+ 
+ void
+ debug_nothing_tree_charstar_uhwi (tree, const char *,
+ 				  unsigned HOST_WIDE_INT)
+ {
+ }
Index: early-lto-debug/gcc/dbxout.c
===================================================================
*** early-lto-debug.orig/gcc/dbxout.c	2017-08-02 10:21:39.142562230 +0200
--- early-lto-debug/gcc/dbxout.c	2017-08-02 10:26:54.536026603 +0200
*************** const struct gcc_debug_hooks dbx_debug_h
*** 372,377 ****
--- 372,379 ----
    dbxout_late_global_decl,		 /* late_global_decl */
    dbxout_type_decl,			 /* type_decl */
    debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+   debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+   debug_nothing_tree_charstar_uhwi,      /* register_external_die */
    debug_nothing_tree,		         /* deferred_inline_function */
    debug_nothing_tree,		         /* outlining_inline_function */
    debug_nothing_rtx_code_label,	         /* label */
*************** const struct gcc_debug_hooks xcoff_debug
*** 412,417 ****
--- 414,421 ----
    dbxout_late_global_decl,		 /* late_global_decl */
    dbxout_type_decl,			 /* type_decl */
    debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+   debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+   debug_nothing_tree_charstar_uhwi,      /* register_external_die */
    debug_nothing_tree,		         /* deferred_inline_function */
    debug_nothing_tree,		         /* outlining_inline_function */
    debug_nothing_rtx_code_label,	         /* label */
Index: early-lto-debug/gcc/sdbout.c
===================================================================
*** early-lto-debug.orig/gcc/sdbout.c	2017-08-02 10:21:39.146562299 +0200
--- early-lto-debug/gcc/sdbout.c	2017-08-02 10:27:32.172679470 +0200
*************** const struct gcc_debug_hooks sdb_debug_h
*** 302,307 ****
--- 302,309 ----
    sdbout_late_global_decl,		 /* late_global_decl */
    sdbout_symbol,			 /* type_decl */
    debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+   debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+   debug_nothing_tree_charstar_uhwi,      /* register_external_die */
    debug_nothing_tree,		         /* deferred_inline_function */
    debug_nothing_tree,		         /* outlining_inline_function */
    sdbout_label,			         /* label */
Index: early-lto-debug/gcc/lto/lto.c
===================================================================
*** early-lto-debug.orig/gcc/lto/lto.c	2017-08-02 10:21:25.146319831 +0200
--- early-lto-debug/gcc/lto/lto.c	2017-08-02 10:21:39.146562299 +0200
*************** unify_scc (struct data_in *data_in, unsi
*** 1633,1638 ****
--- 1633,1641 ----
  	      free_node (scc->entries[i]);
  	    }
  
+ 	  /* Drop DIE references.  */
+ 	  dref_queue.truncate (0);
+ 
  	  break;
  	}
  
*************** lto_read_decls (struct lto_file_decl_dat
*** 1708,1715 ****
  						     from);
  	  if (len == 1
  	      && (TREE_CODE (first) == IDENTIFIER_NODE
! 		  || TREE_CODE (first) == INTEGER_CST
! 		  || TREE_CODE (first) == TRANSLATION_UNIT_DECL))
  	    continue;
  
  	  /* Try to unify the SCC with already existing ones.  */
--- 1711,1717 ----
  						     from);
  	  if (len == 1
  	      && (TREE_CODE (first) == IDENTIFIER_NODE
! 		  || TREE_CODE (first) == INTEGER_CST))
  	    continue;
  
  	  /* Try to unify the SCC with already existing ones.  */
*************** lto_read_decls (struct lto_file_decl_dat
*** 1748,1763 ****
  	      if (TREE_CODE (t) == INTEGER_CST
  		  && !TREE_OVERFLOW (t))
  		cache_integer_cst (t);
- 	      /* Register TYPE_DECLs with the debuginfo machinery.  */
- 	      if (!flag_wpa
- 		  && TREE_CODE (t) == TYPE_DECL)
- 		{
- 		  /* Dwarf2out needs location information.
- 		     TODO: Moving this out of the streamer loop may noticealy
- 		     improve ltrans linemap memory use.  */
- 		  data_in->location_cache.apply_location_cache ();
- 		  debug_hooks->type_decl (t, !DECL_FILE_SCOPE_P (t));
- 		}
  	      if (!flag_ltrans)
  		{
  		  /* Register variables and functions with the
--- 1750,1755 ----
*************** lto_read_decls (struct lto_file_decl_dat
*** 1773,1778 ****
--- 1765,1778 ----
  		    vec_safe_push (tree_with_vars, t);
  		}
  	    }
+ 
+ 	  /* Register DECLs with the debuginfo machinery.  */
+ 	  while (!dref_queue.is_empty ())
+ 	    {
+ 	      dref_entry e = dref_queue.pop ();
+ 	      debug_hooks->register_external_die (e.decl, e.sym, e.off);
+ 	    }
+ 
  	  if (seen_type)
  	    num_type_scc_trees += len;
  	}
*************** lto_section_with_id (const char *name, u
*** 1952,1958 ****
    if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
      return 0;
    s = strrchr (name, '.');
!   return s && sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
  }
  
  /* Create file_data of each sub file id */
--- 1952,1963 ----
    if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
      return 0;
    s = strrchr (name, '.');
!   if (!s)
!     return 0;
!   /* If the section is not suffixed with an ID return.  */
!   if ((size_t)(s - name) == strlen (section_name_prefix))
!     return 0;
!   return sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
  }
  
  /* Create file_data of each sub file id */
Index: early-lto-debug/gcc/lto-streamer-in.c
===================================================================
*** early-lto-debug.orig/gcc/lto-streamer-in.c	2017-08-02 10:21:25.146319831 +0200
--- early-lto-debug/gcc/lto-streamer-in.c	2017-08-02 10:21:39.178562854 +0200
*************** along with GCC; see the file COPYING3.
*** 41,46 ****
--- 41,47 ----
  #include "except.h"
  #include "cgraph.h"
  #include "cfgloop.h"
+ #include "debug.h"
  
  
  struct freeing_string_slot_hasher : string_slot_hasher
*************** input_function (tree fn_decl, struct dat
*** 1038,1043 ****
--- 1039,1054 ----
    DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in);
    DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in);
  
+   /* Read debug args if available.  */
+   unsigned n_debugargs = streamer_read_uhwi (ib);
+   if (n_debugargs)
+     {
+       vec<tree, va_gc> **debugargs = decl_debug_args_insert (fn_decl);
+       vec_safe_grow (*debugargs, n_debugargs);
+       for (unsigned i = 0; i < n_debugargs; ++i)
+ 	(**debugargs)[i] = stream_read_tree (ib, data_in);
+     }
+ 
    /* Read the tree of lexical scopes for the function.  */
    DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
    unsigned block_leaf_count = streamer_read_uhwi (ib);
*************** lto_input_variable_constructor (struct l
*** 1322,1327 ****
--- 1333,1342 ----
  }
  
  
+ /* Queue of acummulated decl -> DIE mappings.  Similar to locations those
+    are only applied to prevailing tree nodes during tree merging.  */
+ vec<dref_entry> dref_queue;
+ 
  /* Read the physical representation of a tree node EXPR from
     input block IB using the per-file context in DATA_IN.  */
  
*************** lto_read_tree_1 (struct lto_input_block
*** 1341,1346 ****
--- 1356,1378 ----
        && TREE_CODE (expr) != FUNCTION_DECL
        && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
      DECL_INITIAL (expr) = stream_read_tree (ib, data_in);
+ 
+   /* Stream references to early generated DIEs.  Keep in sync with the
+      trees handled in dwarf2out_register_external_die.  */
+   if ((DECL_P (expr)
+        && TREE_CODE (expr) != FIELD_DECL
+        && TREE_CODE (expr) != DEBUG_EXPR_DECL
+        && TREE_CODE (expr) != TYPE_DECL)
+       || TREE_CODE (expr) == BLOCK)
+     {
+       const char *str = streamer_read_string (data_in, ib);
+       if (str)
+ 	{
+ 	  unsigned HOST_WIDE_INT off = streamer_read_uhwi (ib);
+ 	  dref_entry e = { expr, str, off };
+ 	  dref_queue.safe_push (e);
+ 	}
+     }
  }
  
  /* Read the physical representation of a tree node with tag TAG from
*************** lto_input_tree (struct lto_input_block *
*** 1486,1491 ****
--- 1518,1530 ----
      {
        unsigned len, entry_len;
        lto_input_scc (ib, data_in, &len, &entry_len);
+ 
+       /* Register DECLs with the debuginfo machinery.  */
+       while (!dref_queue.is_empty ())
+ 	{
+ 	  dref_entry e = dref_queue.pop ();
+ 	  debug_hooks->register_external_die (e.decl, e.sym, e.off);
+ 	}
      }
    return lto_input_tree_1 (ib, data_in, tag, 0);
  }
Index: early-lto-debug/gcc/lto-streamer-out.c
===================================================================
*** early-lto-debug.orig/gcc/lto-streamer-out.c	2017-08-02 10:21:25.150319901 +0200
--- early-lto-debug/gcc/lto-streamer-out.c	2017-08-02 10:21:39.178562854 +0200
*************** along with GCC; see the file COPYING3.
*** 40,45 ****
--- 40,46 ----
  #include "cfgloop.h"
  #include "builtins.h"
  #include "gomp-constants.h"
+ #include "debug.h"
  
  
  static void lto_write_tree (struct output_block*, tree, bool);
*************** lto_write_tree_1 (struct output_block *o
*** 406,411 ****
--- 407,432 ----
  			 (ob->decl_state->symtab_node_encoder, expr);
        stream_write_tree (ob, initial, ref_p);
      }
+ 
+   /* Stream references to early generated DIEs.  Keep in sync with the
+      trees handled in dwarf2out_die_ref_for_decl.  */
+   if ((DECL_P (expr)
+        && TREE_CODE (expr) != FIELD_DECL
+        && TREE_CODE (expr) != DEBUG_EXPR_DECL
+        && TREE_CODE (expr) != TYPE_DECL)
+       || TREE_CODE (expr) == BLOCK)
+     {
+       const char *sym;
+       unsigned HOST_WIDE_INT off;
+       if (debug_info_level > DINFO_LEVEL_NONE
+ 	  && debug_hooks->die_ref_for_decl (expr, &sym, &off))
+ 	{
+ 	  streamer_write_string (ob, ob->main_stream, sym, true);
+ 	  streamer_write_uhwi (ob, off);
+ 	}
+       else
+ 	streamer_write_string (ob, ob->main_stream, NULL, true);
+     }
  }
  
  /* Write a physical representation of tree node EXPR to output block
*************** DFS::DFS_write_tree_body (struct output_
*** 745,751 ****
  	;
        else
  	DFS_follow_tree_edge (DECL_NAME (expr));
!       DFS_follow_tree_edge (DECL_CONTEXT (expr));
      }
  
    if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
--- 766,776 ----
  	;
        else
  	DFS_follow_tree_edge (DECL_NAME (expr));
!       if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
! 	  && ! DECL_CONTEXT (expr))
! 	DFS_follow_tree_edge ((*all_translation_units)[0]);
!       else
! 	DFS_follow_tree_edge (DECL_CONTEXT (expr));
      }
  
    if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
*************** DFS::DFS_write_tree_body (struct output_
*** 765,770 ****
--- 790,796 ----
  	 declarations which should be eliminated by decl merging. Be sure none
  	 leaks to this point.  */
        gcc_assert (DECL_ABSTRACT_ORIGIN (expr) != error_mark_node);
+       DFS_follow_tree_edge (DECL_ABSTRACT_ORIGIN (expr));
  
        if ((VAR_P (expr)
  	   || TREE_CODE (expr) == PARM_DECL)
*************** output_function (struct cgraph_node *nod
*** 2061,2066 ****
--- 2087,2103 ----
    stream_write_tree (ob, DECL_RESULT (function), true);
    streamer_write_chain (ob, DECL_ARGUMENTS (function), true);
  
+   /* Output debug args if available. */
+   vec<tree, va_gc> **debugargs = decl_debug_args_lookup (function);
+   if (! debugargs)
+     streamer_write_uhwi (ob, 0);
+   else
+     {
+       streamer_write_uhwi (ob, (*debugargs)->length ());
+       for (unsigned i = 0; i < (*debugargs)->length (); ++i)
+ 	stream_write_tree (ob, (**debugargs)[i], true);
+     }
+ 
    /* Output DECL_INITIAL for the function, which contains the tree of
       lexical scopes.  */
    stream_write_tree (ob, DECL_INITIAL (function), true);
Index: early-lto-debug/gcc/lto-streamer.h
===================================================================
*** early-lto-debug.orig/gcc/lto-streamer.h	2017-08-02 10:21:25.150319901 +0200
--- early-lto-debug/gcc/lto-streamer.h	2017-08-02 10:21:39.182562923 +0200
*************** DEFINE_DECL_STREAM_FUNCS (TYPE_DECL, typ
*** 1212,1215 ****
--- 1212,1225 ----
  DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl)
  DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl)
  
+ /* Entry for the delayed registering of decl -> DIE references.  */
+ struct dref_entry {
+     tree decl;
+     const char *sym;
+     unsigned HOST_WIDE_INT off;
+ };
+ 
+ extern vec<dref_entry> dref_queue;
+ 
+ 
  #endif /* GCC_LTO_STREAMER_H  */
Index: early-lto-debug/gcc/lto-wrapper.c
===================================================================
*** early-lto-debug.orig/gcc/lto-wrapper.c	2017-08-02 10:21:25.150319901 +0200
--- early-lto-debug/gcc/lto-wrapper.c	2017-08-02 10:21:39.182562923 +0200
*************** static char **output_names;
*** 70,75 ****
--- 70,76 ----
  static char **offload_names;
  static char *offload_objects_file_name;
  static char *makefile;
+ static char *debug_obj;
  
  const char tool_name[] = "lto-wrapper";
  
*************** tool_cleanup (bool)
*** 88,93 ****
--- 89,96 ----
      maybe_unlink (offload_objects_file_name);
    if (makefile)
      maybe_unlink (makefile);
+   if (debug_obj)
+     maybe_unlink (debug_obj);
    for (i = 0; i < nr; ++i)
      {
        maybe_unlink (input_names[i]);
*************** find_and_merge_options (int fd, off_t fi
*** 960,965 ****
--- 963,1029 ----
    return true;
  }
  
+ /* Copy early debug info sections from INFILE to a new file whose name
+    is returned.  Return NULL on error.  */
+ 
+ const char *
+ debug_objcopy (const char *infile)
+ {
+   const char *outfile;
+   const char *errmsg;
+   int err;
+ 
+   const char *p;
+   off_t inoff = 0;
+   long loffset;
+   int consumed;
+   if ((p = strrchr (infile, '@'))
+       && p != infile
+       && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
+       && strlen (p) == (unsigned int) consumed)
+     {
+       char *fname = xstrdup (infile);
+       fname[p - infile] = '\0';
+       infile = fname;
+       inoff = (off_t) loffset;
+     }
+   int infd = open (infile, O_RDONLY);
+   if (infd == -1)
+     return NULL;
+   simple_object_read *inobj = simple_object_start_read (infd, inoff,
+ 							"__GNU_LTO",
+ 							&errmsg, &err);
+   if (!inobj)
+     return NULL;
+ 
+   off_t off, len;
+   if (simple_object_find_section (inobj, ".gnu.debuglto_.debug_info",
+ 				  &off, &len, &errmsg, &err) != 1)
+     {
+       if (errmsg)
+ 	fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
+ 
+       simple_object_release_read (inobj);
+       close (infd);
+       return NULL;
+     }
+ 
+   outfile = make_temp_file ("debugobjtem");
+   errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err);
+   if (errmsg)
+     {
+       unlink_if_ordinary (outfile);
+       fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
+     }
+ 
+   simple_object_release_read (inobj);
+   close (infd);
+ 
+   return outfile;
+ }
+ 
+ 
+ 
  /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
  
  static void
*************** run_gcc (unsigned argc, char *argv[])
*** 984,991 ****
    int new_head_argc;
    bool have_lto = false;
    bool have_offload = false;
!   unsigned lto_argc = 0;
!   char **lto_argv;
  
    /* Get the driver and options.  */
    collect_gcc = getenv ("COLLECT_GCC");
--- 1048,1057 ----
    int new_head_argc;
    bool have_lto = false;
    bool have_offload = false;
!   unsigned lto_argc = 0, ltoobj_argc = 0;
!   char **lto_argv, **ltoobj_argv;
!   bool skip_debug = false;
!   unsigned n_debugobj;
  
    /* Get the driver and options.  */
    collect_gcc = getenv ("COLLECT_GCC");
*************** run_gcc (unsigned argc, char *argv[])
*** 1004,1009 ****
--- 1070,1076 ----
    /* Allocate array for input object files with LTO IL,
       and for possible preceding arguments.  */
    lto_argv = XNEWVEC (char *, argc);
+   ltoobj_argv = XNEWVEC (char *, argc);
  
    /* Look at saved options in the IL files.  */
    for (i = 1; i < argc; ++i)
*************** run_gcc (unsigned argc, char *argv[])
*** 1046,1052 ****
  				  collect_gcc))
  	{
  	  have_lto = true;
! 	  lto_argv[lto_argc++] = argv[i];
  	}
        close (fd);
      }
--- 1113,1119 ----
  				  collect_gcc))
  	{
  	  have_lto = true;
! 	  ltoobj_argv[ltoobj_argc++] = argv[i];
  	}
        close (fd);
      }
*************** run_gcc (unsigned argc, char *argv[])
*** 1107,1112 ****
--- 1174,1190 ----
  	}
      }
  
+   /* Output lto-wrapper invocation command.  */
+   if (verbose)
+     {
+       for (i = 0; i < argc; ++i)
+ 	{
+ 	  fputs (argv[i], stderr);
+ 	  fputc (' ', stderr);
+ 	}
+       fputc ('\n', stderr);
+     }
+ 
    if (no_partition)
      {
        lto_mode = LTO_MODE_LTO;
*************** cont1:
*** 1296,1313 ****
          obstack_ptr_grow (&argv_obstack, "-fwpa");
      }
  
!   /* Append the input objects and possible preceding arguments.  */
    for (i = 0; i < lto_argc; ++i)
      obstack_ptr_grow (&argv_obstack, lto_argv[i]);
    obstack_ptr_grow (&argv_obstack, NULL);
  
    new_argv = XOBFINISH (&argv_obstack, const char **);
    argv_ptr = &new_argv[new_head_argc];
    fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
  
    if (lto_mode == LTO_MODE_LTO)
      {
        printf ("%s\n", flto_out);
        free (flto_out);
        flto_out = NULL;
      }
--- 1374,1478 ----
          obstack_ptr_grow (&argv_obstack, "-fwpa");
      }
  
!   /* Append input arguments.  */
    for (i = 0; i < lto_argc; ++i)
      obstack_ptr_grow (&argv_obstack, lto_argv[i]);
+   /* Append the input objects.  */
+   for (i = 0; i < ltoobj_argc; ++i)
+     obstack_ptr_grow (&argv_obstack, ltoobj_argv[i]);
    obstack_ptr_grow (&argv_obstack, NULL);
  
    new_argv = XOBFINISH (&argv_obstack, const char **);
    argv_ptr = &new_argv[new_head_argc];
    fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
  
+   /* Handle early generated debug information.  At compile-time
+      we output early DWARF debug info into .gnu.debuglto_ prefixed
+      sections.  LTRANS object DWARF debug info refers to that.
+      So we need to transfer the .gnu.debuglto_ sections to the final
+      link.  Ideally the linker plugin interface would allow us to
+      not claim those sections and instruct the linker to keep
+      them, renaming them in the process.  For now we extract and
+      rename those sections via a simple-object interface to produce
+      regular objects containing only the early debug info.  We
+      then partially link those to a single early debug info object
+      and pass that as additional output back to the linker plugin.  */
+ 
+   /* Prepare the partial link to gather the compile-time generated
+      debug-info into a single input for the final link.  */
+   debug_obj = make_temp_file ("debugobj");
+   obstack_ptr_grow (&argv_obstack, collect_gcc);
+   for (i = 1; i < decoded_options_count; ++i)
+     {
+       /* Retain linker choice and -B.  */
+       if (decoded_options[i].opt_index == OPT_B
+ 	  || decoded_options[i].opt_index == OPT_fuse_ld_bfd
+ 	  || decoded_options[i].opt_index == OPT_fuse_ld_gold)
+ 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
+       /* Retain all target options, this preserves -m32 for example.  */
+       if (cl_options[decoded_options[i].opt_index].flags & CL_TARGET)
+ 	append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
+       /* Recognize -g0.  */
+       if (decoded_options[i].opt_index == OPT_g
+ 	  && strcmp (decoded_options[i].arg, "0") == 0)
+ 	skip_debug = true;
+     }
+   obstack_ptr_grow (&argv_obstack, "-r");
+   obstack_ptr_grow (&argv_obstack, "-nostdlib");
+   obstack_ptr_grow (&argv_obstack, "-o");
+   obstack_ptr_grow (&argv_obstack, debug_obj);
+ 
+   /* Copy the early generated debug info from the objects to temporary
+      files and append those to the partial link commandline.  */
+   n_debugobj = 0;
+   if (! skip_debug)
+     for (i = 0; i < ltoobj_argc; ++i)
+       {
+ 	const char *tem;
+ 	if ((tem = debug_objcopy (ltoobj_argv[i])))
+ 	  {
+ 	    obstack_ptr_grow (&argv_obstack, tem);
+ 	    n_debugobj++;
+ 	  }
+       }
+ 
+   /* Link them all into a single object.  Ideally this would reduce
+      disk space usage mainly due to .debug_str merging but unfortunately
+      GNU ld doesn't perform this with -r.  */
+   if (n_debugobj)
+     {
+       obstack_ptr_grow (&argv_obstack, NULL);
+       const char **debug_link_argv = XOBFINISH (&argv_obstack, const char **);
+       fork_execute (debug_link_argv[0],
+ 		    CONST_CAST (char **, debug_link_argv), false);
+ 
+       /* And dispose the temporaries.  */
+       for (i = 0; debug_link_argv[i]; ++i)
+ 	;
+       for (--i; i > 0; --i)
+ 	{
+ 	  if (strcmp (debug_link_argv[i], debug_obj) == 0)
+ 	    break;
+ 	  maybe_unlink (debug_link_argv[i]);
+ 	}
+     }
+   else
+     {
+       unlink_if_ordinary (debug_obj);
+       free (debug_obj);
+       debug_obj = NULL;
+       skip_debug = true;
+     }
+ 
    if (lto_mode == LTO_MODE_LTO)
      {
        printf ("%s\n", flto_out);
+       if (!skip_debug)
+ 	{
+ 	  printf ("%s\n", debug_obj);
+ 	  free (debug_obj);
+ 	  debug_obj = NULL;
+ 	}
        free (flto_out);
        flto_out = NULL;
      }
*************** cont:
*** 1456,1461 ****
--- 1621,1632 ----
  	  for (i = 0; i < nr; ++i)
  	    maybe_unlink (input_names[i]);
  	}
+       if (!skip_debug)
+ 	{
+ 	  printf ("%s\n", debug_obj);
+ 	  free (debug_obj);
+ 	  debug_obj = NULL;
+ 	}
        for (i = 0; i < nr; ++i)
  	{
  	  fputs (output_names[i], stdout);
Index: early-lto-debug/gcc/tree-streamer-in.c
===================================================================
*** early-lto-debug.orig/gcc/tree-streamer-in.c	2017-08-02 10:21:25.150319901 +0200
--- early-lto-debug/gcc/tree-streamer-in.c	2017-08-02 10:21:39.182562923 +0200
*************** lto_input_ts_decl_common_tree_pointers (
*** 688,697 ****
    DECL_SIZE (expr) = stream_read_tree (ib, data_in);
    DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
    DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
! 
!   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
!      for early inlining so drop it on the floor instead of ICEing in
!      dwarf2out.c.  */
  
    if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
        && DECL_HAS_VALUE_EXPR_P (expr))
--- 688,694 ----
    DECL_SIZE (expr) = stream_read_tree (ib, data_in);
    DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
    DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
!   DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
  
    if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
        && DECL_HAS_VALUE_EXPR_P (expr))
Index: early-lto-debug/gcc/tree-streamer-out.c
===================================================================
*** early-lto-debug.orig/gcc/tree-streamer-out.c	2017-08-02 10:21:25.154319970 +0200
--- early-lto-debug/gcc/tree-streamer-out.c	2017-08-02 10:21:39.182562923 +0200
*************** write_ts_decl_minimal_tree_pointers (str
*** 566,572 ****
      stream_write_tree (ob, NULL_TREE, ref_p);
    else
      stream_write_tree (ob, DECL_NAME (expr), ref_p);
!   stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
  }
  
  
--- 566,576 ----
      stream_write_tree (ob, NULL_TREE, ref_p);
    else
      stream_write_tree (ob, DECL_NAME (expr), ref_p);
!   if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
!       && ! DECL_CONTEXT (expr))
!     stream_write_tree (ob, (*all_translation_units)[0], ref_p);
!   else
!     stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
  }
  
  
*************** write_ts_decl_common_tree_pointers (stru
*** 585,594 ****
       special handling in LTO, it must be handled by streamer hooks.  */
  
    stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
! 
!   /* Do not stream DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
!      for early inlining so drop it on the floor instead of ICEing in
!      dwarf2out.c.  */
  
    if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
        && DECL_HAS_VALUE_EXPR_P (expr))
--- 589,595 ----
       special handling in LTO, it must be handled by streamer hooks.  */
  
    stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
!   stream_write_tree (ob, DECL_ABSTRACT_ORIGIN (expr), ref_p);
  
    if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
        && DECL_HAS_VALUE_EXPR_P (expr))
Index: early-lto-debug/gcc/config/darwin.c
===================================================================
*** early-lto-debug.orig/gcc/config/darwin.c	2017-08-02 10:21:25.154319970 +0200
--- early-lto-debug/gcc/config/darwin.c	2017-08-02 10:21:39.182562923 +0200
*************** darwin_asm_lto_end (void)
*** 1959,1965 ****
  }
  
  static void
! darwin_asm_dwarf_section (const char *name, unsigned int flags, tree decl);
  
  /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
  
--- 1959,1966 ----
  }
  
  static void
! darwin_asm_dwarf_section (const char *name, unsigned int flags,
! 			  tree decl, bool is_for_lto);
  
  /*  Called for the TARGET_ASM_NAMED_SECTION hook.  */
  
*************** darwin_asm_named_section (const char *na
*** 2001,2007 ****
        vec_safe_push (lto_section_names, e);
     }
    else if (strncmp (name, "__DWARF,", 8) == 0)
!     darwin_asm_dwarf_section (name, flags, decl);
    else
      fprintf (asm_out_file, "\t.section %s\n", name);
  }
--- 2002,2010 ----
        vec_safe_push (lto_section_names, e);
     }
    else if (strncmp (name, "__DWARF,", 8) == 0)
!     darwin_asm_dwarf_section (name, flags, decl, false);
!   else if (strncmp (name, "__GNU_DWARF_LTO,", 16) == 0)
!     darwin_asm_dwarf_section (name, flags, decl, true);
    else
      fprintf (asm_out_file, "\t.section %s\n", name);
  }
*************** static GTY (()) vec<dwarf_sect_used_entr
*** 2783,2801 ****
  
  static void
  darwin_asm_dwarf_section (const char *name, unsigned int flags,
! 			  tree ARG_UNUSED (decl))
  {
    unsigned i;
!   int namelen;
!   const char * sname;
    dwarf_sect_used_entry *ref;
    bool found = false;
!   gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
! 		    == (SECTION_DEBUG | SECTION_NAMED));
!   /* We know that the name starts with __DWARF,  */
!   sname = name + 8;
!   namelen = strchr (sname, ',') - sname;
!   gcc_assert (namelen);
    if (dwarf_sect_names_table == NULL)
      vec_alloc (dwarf_sect_names_table, 16);
    else
--- 2786,2822 ----
  
  static void
  darwin_asm_dwarf_section (const char *name, unsigned int flags,
! 			  tree ARG_UNUSED (decl), bool is_for_lto)
  {
    unsigned i;
!   int namelen, extra = 0;
!   const char *sect, *lto_add = "";
!   char sname[64];
    dwarf_sect_used_entry *ref;
    bool found = false;
! 
!   gcc_checking_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
! 			== (SECTION_DEBUG | SECTION_NAMED));
! 
!   /* We know that the name starts with __DWARF, or __GNU_DAWRF_LTO  */
!   sect = strchr (name, ',') + 1;
!   namelen = strchr (sect, ',') - sect;
!   gcc_checking_assert (namelen);
! 
!   /* The section switch is output as written...  */
!   fprintf (asm_out_file, "\t.section %s\n", name);
! 
!   /* ... but the string we keep to make section start labels needs
!      adjustment for lto cases.  */
!   if (is_for_lto)
!     {
!       lto_add = "_lto";
!       extra = 4;
!     }
! 
!   snprintf (sname, 64, "%.*s%.*s", namelen, sect, extra, lto_add);
!   namelen += extra;
! 
    if (dwarf_sect_names_table == NULL)
      vec_alloc (dwarf_sect_names_table, 16);
    else
*************** darwin_asm_dwarf_section (const char *na
*** 2813,2819 ****
  	  }
        }
  
-   fprintf (asm_out_file, "\t.section %s\n", name);
    if (!found)
      {
        dwarf_sect_used_entry e;
--- 2834,2839 ----
*************** darwin_asm_output_dwarf_offset (FILE *fi
*** 2866,2879 ****
  				HOST_WIDE_INT offset, section *base)
  {
    char sname[64];
!   int namelen;
  
!   gcc_assert (base->common.flags & SECTION_NAMED);
!   gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
!   gcc_assert (strchr (base->named.name + 8, ','));
! 
!   namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
!   sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
    darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
  }
  
--- 2886,2909 ----
  				HOST_WIDE_INT offset, section *base)
  {
    char sname[64];
!   int namelen, extra = 0;
!   bool is_for_lto;
!   const char *lto_add = "";
! 
!   gcc_checking_assert (base->common.flags & SECTION_NAMED);
!   is_for_lto = strncmp (base->named.name, "__GNU_DWARF_LTO,", 16) == 0;
!   gcc_checking_assert (is_for_lto
! 		       || strncmp (base->named.name, "__DWARF,", 8) == 0);
!   const char *name = strchr (base->named.name, ',') + 1;
!   gcc_checking_assert (name);
  
!   namelen = strchr (name, ',') - (name);
!   if (is_for_lto)
!     {
!       lto_add = "_lto";
!       extra = 4;
!     }
!   snprintf (sname, 64, "*Lsection%.*s%.*s", namelen, name, extra, lto_add);
    darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
  }
  
Index: early-lto-debug/gcc/config/darwin.h
===================================================================
*** early-lto-debug.orig/gcc/config/darwin.h	2017-08-02 10:21:25.154319970 +0200
--- early-lto-debug/gcc/config/darwin.h	2017-08-02 10:21:39.182562923 +0200
*************** extern GTY(()) int darwin_ms_struct;
*** 445,451 ****
  #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
  #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
  #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
! #define DEBUG_MACRO_SECTION    "__DWARF,__debug_macro,regular,debug"
  
  #define TARGET_WANT_DEBUG_PUB_SECTIONS true
  
--- 445,458 ----
  #define DEBUG_PUBTYPES_SECTION	"__DWARF,__debug_pubtypes,regular,debug"
  #define DEBUG_STR_SECTION	"__DWARF,__debug_str,regular,debug"
  #define DEBUG_RANGES_SECTION	"__DWARF,__debug_ranges,regular,debug"
! #define DEBUG_MACRO_SECTION     "__DWARF,__debug_macro,regular,debug"
! 
! #define DEBUG_LTO_INFO_SECTION	  "__GNU_DWARF_LTO,__debug_info,regular,debug"
! #define DEBUG_LTO_ABBREV_SECTION  "__GNU_DWARF_LTO,__debug_abbrev,regular,debug"
! #define DEBUG_LTO_MACINFO_SECTION "__GNU_DWARF_LTO,__debug_macinfo,regular,debug"
! #define DEBUG_LTO_LINE_SECTION	  "__GNU_DWARF_LTO,__debug_line,regular,debug"
! #define DEBUG_LTO_STR_SECTION	  "__GNU_DWARF_LTO,__debug_str,regular,debug"
! #define DEBUG_LTO_MACRO_SECTION   "__GNU_DWARF_LTO,__debug_macro,regular,debug"
  
  #define TARGET_WANT_DEBUG_PUB_SECTIONS true
  
Index: early-lto-debug/gcc/vmsdbgout.c
===================================================================
*** early-lto-debug.orig/gcc/vmsdbgout.c	2017-08-02 10:21:39.186562992 +0200
--- early-lto-debug/gcc/vmsdbgout.c	2017-08-02 10:27:59.217149976 +0200
*************** const struct gcc_debug_hooks vmsdbg_debu
*** 198,203 ****
--- 198,205 ----
     vmsdbgout_late_global_decl,
     vmsdbgout_type_decl,		  /* type_decl */
     debug_nothing_tree_tree_tree_bool_bool, /* imported_module_or_decl */
+    debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
+    debug_nothing_tree_charstar_uhwi, /* register_external_die */
     debug_nothing_tree,		  /* deferred_inline_function */
     vmsdbgout_abstract_function,
     debug_nothing_rtx_code_label,  /* label */
Index: early-lto-debug/gcc/tree.c
===================================================================
*** early-lto-debug.orig/gcc/tree.c	2017-08-02 10:21:25.158320039 +0200
--- early-lto-debug/gcc/tree.c	2017-08-02 10:21:39.186562992 +0200
*************** free_lang_data (void)
*** 5980,5985 ****
--- 5980,5989 ----
        || (!flag_generate_lto && !flag_generate_offload))
      return 0;
  
+   /* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one.  */
+   if (vec_safe_is_empty (all_translation_units))
+     build_translation_unit_decl (NULL_TREE);
+ 
    /* Allocate and assign alias sets to the standard integer types
       while the slots are still in the way the frontends generated them.  */
    for (i = 0; i < itk_none; ++i)
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-08-02 10:21:25.158320039 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/global-overflow-1.c	2017-08-02 10:21:39.186562992 +0200
*************** int main() {
*** 23,28 ****
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
  /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
  /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
--- 23,28 ----
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
  /* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
  /* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-08-02 10:21:25.158320039 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c	2017-08-02 10:21:39.190563062 +0200
*************** int main(int argc, char **argv) {
*** 24,31 ****
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- 24,31 ----
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-08-02 10:21:25.162320109 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-1.c	2017-08-02 10:21:39.190563062 +0200
*************** main ()
*** 39,43 ****
  /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
--- 39,43 ----
  /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-08-02 10:21:25.162320109 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/misalign-2.c	2017-08-02 10:21:39.190563062 +0200
*************** main ()
*** 39,43 ****
  /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
--- 39,43 ----
  /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-08-02 10:21:25.162320109 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/null-deref-1.c	2017-08-02 10:21:39.190563062 +0200
*************** int main()
*** 18,22 ****
  
  /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- 18,22 ----
  
  /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-08-02 10:21:25.162320109 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c	2017-08-02 10:21:39.190563062 +0200
*************** int main() {
*** 18,23 ****
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
--- 18,23 ----
  }
  
  /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-08-02 10:21:25.162320109 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c	2017-08-02 10:21:39.190563062 +0200
*************** int main(int argc, char **argv) {
*** 14,21 ****
  
  /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- 14,21 ----
  
  /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-08-02 10:21:25.162320109 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/use-after-free-1.c	2017-08-02 10:21:39.190563062 +0200
*************** int main() {
*** 12,22 ****
  /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
--- 12,22 ----
  /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
  /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
Index: early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C
===================================================================
*** early-lto-debug.orig/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-08-02 10:21:25.162320109 +0200
--- early-lto-debug/gcc/testsuite/g++.dg/asan/large-func-test-1.C	2017-08-02 10:21:39.190563062 +0200
*************** int main() {
*** 38,44 ****
  // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
  // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
  // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
--- 38,44 ----
  // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
  // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
! // { dg-output "    #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
  // { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
  // { dg-output "    #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }
Index: early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp
===================================================================
*** early-lto-debug.orig/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-08-02 10:21:25.162320109 +0200
--- early-lto-debug/libstdc++-v3/testsuite/libstdc++-prettyprinters/prettyprinters.exp	2017-08-02 10:21:39.190563062 +0200
***************
*** 15,20 ****
--- 15,21 ----
  # <http://www.gnu.org/licenses/>.
  
  load_lib gdb-test.exp
+ load_lib target-supports.exp
  
  dg-init
  v3-build_support
*************** global PCH_CXXFLAGS
*** 46,51 ****
--- 47,60 ----
  gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
    "" "$DEFAULT_CXXFLAGS $PCH_CXXFLAGS"
  
+ if { [check_effective_target_lto] } {
+   append cxxflags " -flto"
+   # work around sourceware.org 20882
+   regsub {^(.*)-Wl,--gc-sections(.*)$} $cxxldflags {\1\2} cxxldflags
+   gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
+     "" "$DEFAULT_CXXFLAGS -flto $PCH_CXXFLAGS"
+ }
+ 
  if [info exists guality_gdb_name] {
      unsetenv GUALITY_GDB_NAME
  }
Index: early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- early-lto-debug/gcc/testsuite/gfortran.dg/save_6.f90	2017-08-02 10:21:39.190563062 +0200
***************
*** 0 ****
--- 1,54 ----
+ ! { dg-do run }
+ ! { dg-require-effective-target lto }
+ ! { dg-options "-fno-automatic -flto -g" }
+ !
+ ! PR fortran/55733
+ !
+ ! Check that -fno-automatic makes the local variable SAVEd
+ ! Check that -flto -g works
+ !
+ 
+ ! Scalar allocatable
+ subroutine foo(i)
+   integer :: i
+   integer, allocatable :: j
+   if (i == 1) j = 42
+   if (.not. allocated (j)) call abort ()
+   if (j /= 42) call abort ()
+ end
+ 
+ ! Deferred-length string scalar
+ subroutine bar()
+   logical, save :: first = .true.
+   character(len=:), allocatable :: str
+   if (first) then
+     first = .false.
+     if (allocated (str)) call abort ()
+     str = "ABCDEF"
+   end if
+   if (.not. allocated (str)) call abort ()
+   if (len (str) /= 6) call abort ()
+   if (str(1:6) /= "ABCDEF") call abort ()
+ end subroutine bar
+ 
+ ! Deferred-length string array
+ subroutine bar_array()
+   logical, save :: first = .true.
+   character(len=:), allocatable :: str
+   if (first) then
+     first = .false.
+     if (allocated (str)) call abort ()
+     str = "ABCDEF"
+   end if
+   if (.not. allocated (str)) call abort ()
+   if (len (str) /= 6) call abort ()
+   if (str(1:6) /= "ABCDEF") call abort ()
+ end subroutine bar_array
+ 
+ call foo(1)
+ call foo(2)
+ call bar()
+ call bar_array()
+ call bar()
+ call bar_array()
+ end
Index: early-lto-debug/gcc/config/i386/i386.c
===================================================================
*** early-lto-debug.orig/gcc/config/i386/i386.c	2017-08-02 10:21:25.174320316 +0200
--- early-lto-debug/gcc/config/i386/i386.c	2017-08-02 10:21:39.198563200 +0200
*************** make_resolver_func (const tree default_d
*** 33898,33904 ****
    DECL_NAME (decl) = decl_name;
    TREE_USED (decl) = 1;
    DECL_ARTIFICIAL (decl) = 1;
!   DECL_IGNORED_P (decl) = 0;
    /* IFUNC resolvers have to be externally visible.  */
    TREE_PUBLIC (decl) = 1;
    DECL_UNINLINABLE (decl) = 1;
--- 33898,33904 ----
    DECL_NAME (decl) = decl_name;
    TREE_USED (decl) = 1;
    DECL_ARTIFICIAL (decl) = 1;
!   DECL_IGNORED_P (decl) = 1;
    /* IFUNC resolvers have to be externally visible.  */
    TREE_PUBLIC (decl) = 1;
    DECL_UNINLINABLE (decl) = 1;
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/alloca_big_alignment.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/alloca_big_alignment.c	2017-07-17 09:52:30.728120381 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/alloca_big_alignment.c	2017-08-03 09:41:02.010368309 +0200
*************** int main() {
*** 17,22 ****
  }
  
  /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_big_alignment.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in foo.*alloca_big_alignment.c.*(\n|\r\n|\r)" */
--- 17,22 ----
  }
  
  /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_big_alignment.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r\]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in foo.*alloca_big_alignment.c.*(\n|\r\n|\r)" */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/alloca_detect_custom_size.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/alloca_detect_custom_size.c	2017-07-17 09:52:30.728120381 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/alloca_detect_custom_size.c	2017-08-03 09:41:48.967159382 +0200
*************** int main(int argc, char **argv) {
*** 22,27 ****
  }
  
  /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_detect_custom_size.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in foo.*alloca_detect_custom_size.c.*(\n|\r\n|\r)" */
--- 22,27 ----
  }
  
  /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_detect_custom_size.c:16|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in foo.*alloca_detect_custom_size.c.*(\n|\r\n|\r)" */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/alloca_overflow_partial.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/alloca_overflow_partial.c	2017-07-17 09:52:30.728120381 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/alloca_overflow_partial.c	2017-08-03 09:42:20.443689680 +0200
*************** int main(int argc, char **argv) {
*** 17,22 ****
  }
  
  /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_overflow_partial.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in foo.*alloca_overflow_partial.c.*(\n|\r\n|\r)" */
--- 17,22 ----
  }
  
  /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_overflow_partial.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in foo.*alloca_overflow_partial.c.*(\n|\r\n|\r)" */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/alloca_overflow_right.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/alloca_overflow_right.c	2017-07-17 09:52:30.732120446 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/alloca_overflow_right.c	2017-08-03 09:42:53.304243311 +0200
*************** int main(int argc, char **argv) {
*** 17,22 ****
  }
  
  /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_overflow_right.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in foo.*alloca_overflow_right.c.*(\n|\r\n|\r)" */
--- 17,22 ----
  }
  
  /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_overflow_right.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in foo.*alloca_overflow_right.c.*(\n|\r\n|\r)" */
Index: early-lto-debug/gcc/testsuite/c-c++-common/asan/alloca_underflow_left.c
===================================================================
*** early-lto-debug.orig/gcc/testsuite/c-c++-common/asan/alloca_underflow_left.c	2017-07-17 09:52:30.732120446 +0200
--- early-lto-debug/gcc/testsuite/c-c++-common/asan/alloca_underflow_left.c	2017-08-03 09:43:33.680923594 +0200
*************** int main(int argc, char **argv) {
*** 17,22 ****
  }
  
  /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_underflow_left.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in foo.*alloca_underflow_left.c.*(\n|\r\n|\r)" */
--- 17,22 ----
  }
  
  /* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
! /* { dg-output "    #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_underflow_left.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
  /* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
  /* { dg-output "\[^\n\r]*in foo.*alloca_underflow_left.c.*(\n|\r\n|\r)" */
Index: early-lto-debug/gcc/cfgexpand.c
===================================================================
*** early-lto-debug.orig/gcc/cfgexpand.c	2017-08-02 10:20:44.093608890 +0200
--- early-lto-debug/gcc/cfgexpand.c	2017-08-03 12:21:08.348962776 +0200
*************** pass_expand::execute (function *fun)
*** 6527,6538 ****
  	  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1;
      }
  
-   /* We are now committed to emitting code for this function.  Do any
-      preparation, such as emitting abstract debug info for the inline
-      before it gets mangled by optimization.  */
-   if (cgraph_function_possibly_inlined_p (current_function_decl))
-     (*debug_hooks->outlining_inline_function) (current_function_decl);
- 
    TREE_ASM_WRITTEN (current_function_decl) = 1;
  
    /* After expanding, the return labels are no longer needed. */
--- 6527,6532 ----

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-08-04 12:21           ` Richard Biener
@ 2017-08-22 10:49             ` Szabolcs Nagy
  2017-08-22 10:57               ` Richard Biener
  2017-09-19 15:24             ` Jakub Jelinek
  1 sibling, 1 reply; 22+ messages in thread
From: Szabolcs Nagy @ 2017-08-22 10:49 UTC (permalink / raw)
  To: Richard Biener, Jason Merrill; +Cc: nd, gcc-patches List

On 04/08/17 13:21, Richard Biener wrote:
> On Thu, 3 Aug 2017, Jason Merrill wrote:
>> OK if testing passes.
> 
> Thanks.  Meanwhile testing passed.
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu, LTO bootstrapped
> on x86_64-unknown-linux-gnu (both all languages).  I've successfully
> built SPEC CPU 2006 with -flto -g (provides reasonable Fortran coverage).
> I've successfully ran the GCC testsuite with -flto -g which shows lots
> of FAILs but doesn't regress in any unexpected ways compared to before
> the patches.
> 
> I'll ping Ian about the simple-object part again and will apply
> earliest at Aug 14th.
> 
> Richard.
> 

on aarch64_be-none-elf i see

PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 (test for excess errors)
PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -O (test for excess errors)
PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -O3 (test for excess errors)
PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 (test for excess errors)
PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 -O (test for excess errors)
PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 -O3 (test for excess errors)
PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 (test for excess errors)
PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 -O (test for excess errors)
PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 -O3 (test for excess errors)
PASS->FAIL: gcc.dg/lto/20090914-1 c_lto_20090914-1_0.o-c_lto_20090914-1_0.o link, -flto
PASS->FAIL: gcc.dg/lto/20100426 c_lto_20100426_0.o-c_lto_20100426_0.o link, -r -nostdlib -flto -g
PASS->FAIL: gcc.dg/lto/20111207-2 c_lto_20111207-2_0.o-c_lto_20111207-2_0.o link,  -g -O -flto
PASS->FAIL: gcc.dg/lto/20111213-1 c_lto_20111213-1_0.o-c_lto_20111213-1_0.o link,  -flto -g
PASS->FAIL: gcc.dg/lto/pr51572-1 c_lto_pr51572-1_0.o-c_lto_pr51572-1_0.o link,  -flto -g
PASS->FAIL: gcc.dg/lto/pr53470 c_lto_pr53470_0.o-c_lto_pr53470_0.o link,  -flto -g
PASS->FAIL: gcc.dg/lto/pr59323 c_lto_pr59323_0.o-c_lto_pr59323_0.o link,  -O2 -g -flto
PASS->FAIL: gcc.dg/lto/pr59323-2 c_lto_pr59323-2_0.o-c_lto_pr59323-2_0.o link,  -O2 -g -flto
PASS->FAIL: gcc.dg/pr43557-1.c (test for excess errors)

linking seems to fail with

/tmp/ccqAb1Wfdebugobjtem: file not recognized: Bad value
collect2: error: ld returned 1 exit status
lto-wrapper: fatal error: B/gcc/xgcc returned 1 exit status
compilation terminated.
P/aarch64_be-none-elf/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
compiler exited with status 1

similar regressions on g++ tests:

PASS->FAIL: g++.dg/lto/20101010-4 cp_lto_20101010-4_0.o-cp_lto_20101010-4_0.o link,  -std=c++0x -flto -g -r
-nostdlib
PASS->FAIL: g++.dg/lto/20101015-2 cp_lto_20101015-2_0.o-cp_lto_20101015-2_0.o link,  -g -flto
PASS->FAIL: g++.dg/lto/pr42987 cp_lto_pr42987_0.o-cp_lto_pr42987_1.o link,  -flto -flto-partition=none -g
PASS->FAIL: g++.dg/lto/pr42987 cp_lto_pr42987_0.o-cp_lto_pr42987_1.o link,  -flto -g
PASS->FAIL: g++.dg/lto/pr48207 cp_lto_pr48207_0.o-cp_lto_pr48207_0.o link,  -flto -g
PASS->FAIL: g++.dg/lto/pr48207-2 cp_lto_pr48207-2_0.o-cp_lto_pr48207-2_0.o link,  -flto -g
PASS->FAIL: g++.dg/lto/pr48207-3 cp_lto_pr48207-3_0.o-cp_lto_pr48207-3_0.o link,  -flto -g
PASS->FAIL: g++.dg/lto/pr48354-1 cp_lto_pr48354-1_0.o-cp_lto_pr48354-1_0.o link,  -g -flto
PASS->FAIL: g++.dg/lto/pr48508-1 cp_lto_pr48508-1_0.o-cp_lto_pr48508-1_1.o link,  -g -O2 -flto
-flto-partition=none
PASS->FAIL: g++.dg/lto/pr51564-1 cp_lto_pr51564-1_0.o-cp_lto_pr51564-1_0.o link,  -flto -g
PASS->FAIL: g++.dg/lto/pr51567-1 cp_lto_pr51567-1_0.o-cp_lto_pr51567-1_0.o link,  -flto -g
PASS->FAIL: g++.dg/lto/pr51572-2 cp_lto_pr51572-2_0.o-cp_lto_pr51572-2_0.o link,  -g -flto
PASS->FAIL: g++.dg/lto/pr51573-1 cp_lto_pr51573-1_0.o-cp_lto_pr51573-1_0.o link,  -flto -g
PASS->FAIL: g++.dg/lto/pr51650-1 cp_lto_pr51650-1_0.o-cp_lto_pr51650-1_0.o link,  -flto -g
PASS->FAIL: g++.dg/lto/pr51650-2 cp_lto_pr51650-2_0.o-cp_lto_pr51650-2_0.o link,  -flto -g
PASS->FAIL: g++.dg/lto/pr51650-3 cp_lto_pr51650-3_0.o-cp_lto_pr51650-3_0.o link,  -flto -g
PASS->FAIL: g++.dg/lto/pr52605 cp_lto_pr52605_0.o-cp_lto_pr52605_0.o link, -flto -g
PASS->FAIL: g++.dg/lto/pr53470 cp_lto_pr53470_0.o-cp_lto_pr53470_0.o link,  -g -flto
PASS->FAIL: g++.dg/lto/pr65193 cp_lto_pr65193_0.o-cp_lto_pr65193_0.o link, -fPIC -r -nostdlib -flto -O2 -g
PASS->FAIL: g++.dg/lto/pr65316 cp_lto_pr65316_0.o-cp_lto_pr65316_1.o link,  -flto -std=c++11 -g2
-fno-lto-odr-type-merging -O2
PASS->FAIL: g++.dg/lto/pr65549 cp_lto_pr65549_0.o-cp_lto_pr65549_0.o link,  -std=gnu++14 -flto -g
PASS->FAIL: g++.dg/lto/pr65549 cp_lto_pr65549_0.o-cp_lto_pr65549_0.o link,  -std=gnu++14 -flto -g -O2
-fno-inline -flto-partition=max
PASS->FAIL: g++.dg/lto/pr69077 cp_lto_pr69077_0.o-cp_lto_pr69077_1.o link,  -O3 -g -flto
PASS->FAIL: g++.dg/lto/pr69137 cp_lto_pr69137_0.o-cp_lto_pr69137_0.o link,  -std=c++11 -g -flto
PASS->FAIL: g++.dg/lto/pr79000 cp_lto_pr79000_0.o-cp_lto_pr79000_1.o link, -flto -g
NA->FAIL: g++.dg/template/pr81899.C  -std=c++98 (test for excess errors)

> 2017-08-04  Richard Biener  <rguenther@suse.de>
> 
>         * debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and
>         register_external_die hooks.
>         (debug_false_tree_charstarstar_uhwistar): Declare.
>         (debug_nothing_tree_charstar_uhwi): Likewise.
>         * debug.c (do_nothing_debug_hooks): Adjust.
>         (debug_false_tree_charstarstar_uhwistar): New do nothing.
>         (debug_nothing_tree_charstar_uhwi): Likewise.
>         * dbxout.c (dbx_debug_hooks): Adjust.
>         (xcoff_debug_hooks): Likewise.
>         * sdbout.c (sdb_debug_hooks): Likewise.
>         * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
> 
>         * dwarf2out.c (macinfo_label_base): New global.
> 	(dwarf2out_register_external_die): New function for the
> 	register_external_die hook.
>         (dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl.
>         (dwarf2_debug_hooks): Use them.
>         (dwarf2_lineno_debug_hooks): Adjust.
>         (struct die_struct): Add with_offset flag.
>         (DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION,
>         DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION,
>         DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION,
>         DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION,
>         DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
>         DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros
>         defining section names for the early LTO debug variants.
> 	(reset_indirect_string): New helper.
>         (add_AT_external_die_ref): Helper for dwarf2out_register_external_die.
>         (print_dw_val): Add support for offsetted symbol references.
> 	(get_ultimate_context): Split out from is_cxx.
> 	(is_cxx): Use get_ultimate_context.
> 	(is_fortran): Add decl overload.
>         (compute_comp_unit_symbol): Split out worker from
> 	compute_section_prefix.
>         (compute_section_prefix): Call compute_comp_unit_symbol and
> 	set comdat_type_p here.
>         (output_die): Skip DIE symbol output for the LTO added one.
>         Handle DIE symbol references with offset.
>         (output_comp_unit): Guard section name mangling properly.
>         For LTO debug sections emit a symbol at the section beginning
>         which we use to refer to its DIEs.
>         (add_abstract_origin_attribute): For DIEs registered via
>         dwarf2out_register_external_die directly refer to the early
>         DIE rather than indirectly through the shadow one we created.
> 	Remove obsolete call to dwarf2out_abstract_function for
> 	non-function/block origins.
>         (gen_array_type_die): When generating early LTO debug do
>         not emit DW_AT_string_length.
>         (gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs
>         late when in LTO.  As suggested place a gcc_unreachable for
> 	the DECL_ABSTRACT_P case.
>         (gen_subprogram_die): Avoid another specification DIE
>         for early built declarations/definitions for the late LTO case.
>         (gen_variable_die): Add type references for late duplicated VLA dies
>         when in late LTO.
>         (gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function,
>         we have the abstract instance already.
>         (process_scope_var): Adjust decl DIE contexts in LTO which
>         first puts them in limbo.
>         (gen_decl_die): Do not generate type DIEs late apart from
>         types for VLAs or for decls we do not yet have a DIE.  Do not
> 	call dwarf2out_abstract_function late.
>         (dwarf2out_early_global_decl): Make sure to create DIEs
>         for abstract instances of a decl first.
>         (dwarf2out_late_global_decl): Adjust comment.
>         (output_macinfo_op): With multiple macro sections use
> 	macinfo_label_base to distinguish labels.
>         (output_macinfo): Likewise.  Update macinfo_label_base.
> 	Pass in the line info label.
> 	(note_variable_value_in_expr): When generating LTO resolve
> 	all variable values here by generating DIEs as needed.
>         (init_sections_and_labels): Add early LTO debug flag parameter
>         and generate different sections and names if set.  Add generation
>         counter for the labels so we can have multiple of them.
>         (reset_dies): Helper to allow DIEs to be output multiple times.
>         (dwarf2out_finish): When outputting DIEs to the fat part of an
> 	LTO object first reset DIEs.
>         (dwarf2out_early_finish): Output early DIEs when generating LTO.
> 
> Cleanups we can do (and need) when removing the "old" LTO path and add
> the early LTO path.
> 
>         (set_decl_abstract_flags): Remove.
>         (set_block_abstract_flags): Likewise.
>         (dwarf2out_abstract_function): Treat the early generated DIEs
>         as the abstract copy and only add DW_AT_inline and
>         DW_AT_artificial here and call set_decl_origin_self.
> 	If the DIE has an abstract origin don't do anything.
> 
> 	* tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL
> 	if we have none yet (Go fails to build one, PR78628).
>         * lto-streamer-in.c: Include debug.h.
>         (dref_queue): New global.
>         (lto_read_tree_1): Stream in DIE references.
>         (lto_input_tree): Register DIE references.
> 	(input_function): Stream DECL_DEBUG_ARGS.
>         * lto-streamer-out.c: Include debug.h.
>         (lto_write_tree_1): Output DIE references.
>         (DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN.
> 	Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls.
> 	(output_function): Stream DECL_DEBUG_ARGS.
>         * tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers):
>         Stream DECL_ABSTRACT_ORIGIN.
>         * tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise.
> 	(write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL
> 	DECL_CONTEXT for file-scope decls.
>         * lto-streamer.h (struct dref_entry): Declare.
>         (dref_queue): Likewise.
> 	* cfgexpand.c (pass_expand::execute): Do not call the
> 	outlining_inline_function hook here.
> 
>         * lto-wrapper.c (debug_obj): New global.
>         (tool_cleanup): Unlink it if required.
>         (debug_objcopy): New function.
>         (run_gcc): Handle early debug sections in the IL files by
>         extracting them to separate files, partially linkin them and
>         feeding the result back as result to the linker.
> 
>         * config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION,
>         DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION,
>         DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug
>         sections into a separate segment.
>         * config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO
>         segments.
>         (darwin_asm_dwarf_section): Likewise.
>         (darwin_asm_output_dwarf_offset): Likewise.
> 
> 	* config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P.
> 
>         lto/
>         * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
>         (lto_read_decls): Process TRANSLATION_UNIT_DECLs.  Remove
>         TYPE_DECL debug processing, register DIE references from
>         prevailing SCCs with the debug machinery.
>         (lto_section_with_id): Handle LTO debug sections.
> 
> 	libstdc++/
> 	* testsuite/libstdc++-prettyprinters/prettyprinters.exp: Run all
> 	tests with -flto as well if supported.
> 
> 	* c-c++-common/asan/global-overflow-1.c: Adjust diagnostic location
> 	regex to handle the LTO case.
> 	* c-c++-common/asan/heap-overflow-1.c: Likewise.
> 	* c-c++-common/asan/misalign-1.c: Likewise.
> 	* c-c++-common/asan/misalign-2.c: Likewise.
> 	* c-c++-common/asan/null-deref-1.c: Likewise.
> 	* c-c++-common/asan/stack-overflow-1.c: Likewise.
> 	* c-c++-common/asan/strncpy-overflow-1.c: Likewise.
> 	* c-c++-common/asan/use-after-free-1.c: Likewise.
> 	* c-c++-common/asan/alloca_big_alignment.c: Likewise.
> 	* c-c++-common/asan/alloca_detect_custom_size.c: Likewise.
> 	* c-c++-common/asan/alloca_overflow_partial.c: Likewise.
> 	* c-c++-common/asan/alloca_overflow_right.c: Likewise.
> 	* c-c++-common/asan/alloca_underflow_left.c: Likewise.
> 	* g++.dg/asan/large-func-test-1.C: Likewise.
> 	* gfortran.dg/save_6.f90: Add -flto -g variant of save_5.f90.
> 
...

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-08-22 10:49             ` Szabolcs Nagy
@ 2017-08-22 10:57               ` Richard Biener
  2017-08-22 13:01                 ` Szabolcs Nagy
  0 siblings, 1 reply; 22+ messages in thread
From: Richard Biener @ 2017-08-22 10:57 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: Jason Merrill, nd, gcc-patches List

On Tue, 22 Aug 2017, Szabolcs Nagy wrote:

> On 04/08/17 13:21, Richard Biener wrote:
> > On Thu, 3 Aug 2017, Jason Merrill wrote:
> >> OK if testing passes.
> > 
> > Thanks.  Meanwhile testing passed.
> > 
> > Bootstrapped and tested on x86_64-unknown-linux-gnu, LTO bootstrapped
> > on x86_64-unknown-linux-gnu (both all languages).  I've successfully
> > built SPEC CPU 2006 with -flto -g (provides reasonable Fortran coverage).
> > I've successfully ran the GCC testsuite with -flto -g which shows lots
> > of FAILs but doesn't regress in any unexpected ways compared to before
> > the patches.
> > 
> > I'll ping Ian about the simple-object part again and will apply
> > earliest at Aug 14th.
> > 
> > Richard.
> > 
> 
> on aarch64_be-none-elf i see
> 
> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 (test for excess errors)
> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -O (test for excess errors)
> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -O3 (test for excess errors)
> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 (test for excess errors)
> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 -O (test for excess errors)
> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 -O3 (test for excess errors)
> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 (test for excess errors)
> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 -O (test for excess errors)
> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 -O3 (test for excess errors)
> PASS->FAIL: gcc.dg/lto/20090914-1 c_lto_20090914-1_0.o-c_lto_20090914-1_0.o link, -flto
> PASS->FAIL: gcc.dg/lto/20100426 c_lto_20100426_0.o-c_lto_20100426_0.o link, -r -nostdlib -flto -g
> PASS->FAIL: gcc.dg/lto/20111207-2 c_lto_20111207-2_0.o-c_lto_20111207-2_0.o link,  -g -O -flto
> PASS->FAIL: gcc.dg/lto/20111213-1 c_lto_20111213-1_0.o-c_lto_20111213-1_0.o link,  -flto -g
> PASS->FAIL: gcc.dg/lto/pr51572-1 c_lto_pr51572-1_0.o-c_lto_pr51572-1_0.o link,  -flto -g
> PASS->FAIL: gcc.dg/lto/pr53470 c_lto_pr53470_0.o-c_lto_pr53470_0.o link,  -flto -g
> PASS->FAIL: gcc.dg/lto/pr59323 c_lto_pr59323_0.o-c_lto_pr59323_0.o link,  -O2 -g -flto
> PASS->FAIL: gcc.dg/lto/pr59323-2 c_lto_pr59323-2_0.o-c_lto_pr59323-2_0.o link,  -O2 -g -flto
> PASS->FAIL: gcc.dg/pr43557-1.c (test for excess errors)
> 
> linking seems to fail with
> 
> /tmp/ccqAb1Wfdebugobjtem: file not recognized: Bad value
> collect2: error: ld returned 1 exit status
> lto-wrapper: fatal error: B/gcc/xgcc returned 1 exit status
> compilation terminated.
> P/aarch64_be-none-elf/bin/ld: error: lto-wrapper failed
> collect2: error: ld returned 1 exit status
> compiler exited with status 1

Can you file a bugreport please?  Can you investigate a bit, I suspect
a simple int main() {} and ./xgcc -B. -flto -g t.c fails the same way.
With -save-temps -v you should be able to inspect the generated
debugobj with readelf.

Is this a native compiler or a cross-compiler?  [I suspect endianess
issues somewhere?]

Thanks,
Richard.

> similar regressions on g++ tests:
> 
> PASS->FAIL: g++.dg/lto/20101010-4 cp_lto_20101010-4_0.o-cp_lto_20101010-4_0.o link,  -std=c++0x -flto -g -r
> -nostdlib
> PASS->FAIL: g++.dg/lto/20101015-2 cp_lto_20101015-2_0.o-cp_lto_20101015-2_0.o link,  -g -flto
> PASS->FAIL: g++.dg/lto/pr42987 cp_lto_pr42987_0.o-cp_lto_pr42987_1.o link,  -flto -flto-partition=none -g
> PASS->FAIL: g++.dg/lto/pr42987 cp_lto_pr42987_0.o-cp_lto_pr42987_1.o link,  -flto -g
> PASS->FAIL: g++.dg/lto/pr48207 cp_lto_pr48207_0.o-cp_lto_pr48207_0.o link,  -flto -g
> PASS->FAIL: g++.dg/lto/pr48207-2 cp_lto_pr48207-2_0.o-cp_lto_pr48207-2_0.o link,  -flto -g
> PASS->FAIL: g++.dg/lto/pr48207-3 cp_lto_pr48207-3_0.o-cp_lto_pr48207-3_0.o link,  -flto -g
> PASS->FAIL: g++.dg/lto/pr48354-1 cp_lto_pr48354-1_0.o-cp_lto_pr48354-1_0.o link,  -g -flto
> PASS->FAIL: g++.dg/lto/pr48508-1 cp_lto_pr48508-1_0.o-cp_lto_pr48508-1_1.o link,  -g -O2 -flto
> -flto-partition=none
> PASS->FAIL: g++.dg/lto/pr51564-1 cp_lto_pr51564-1_0.o-cp_lto_pr51564-1_0.o link,  -flto -g
> PASS->FAIL: g++.dg/lto/pr51567-1 cp_lto_pr51567-1_0.o-cp_lto_pr51567-1_0.o link,  -flto -g
> PASS->FAIL: g++.dg/lto/pr51572-2 cp_lto_pr51572-2_0.o-cp_lto_pr51572-2_0.o link,  -g -flto
> PASS->FAIL: g++.dg/lto/pr51573-1 cp_lto_pr51573-1_0.o-cp_lto_pr51573-1_0.o link,  -flto -g
> PASS->FAIL: g++.dg/lto/pr51650-1 cp_lto_pr51650-1_0.o-cp_lto_pr51650-1_0.o link,  -flto -g
> PASS->FAIL: g++.dg/lto/pr51650-2 cp_lto_pr51650-2_0.o-cp_lto_pr51650-2_0.o link,  -flto -g
> PASS->FAIL: g++.dg/lto/pr51650-3 cp_lto_pr51650-3_0.o-cp_lto_pr51650-3_0.o link,  -flto -g
> PASS->FAIL: g++.dg/lto/pr52605 cp_lto_pr52605_0.o-cp_lto_pr52605_0.o link, -flto -g
> PASS->FAIL: g++.dg/lto/pr53470 cp_lto_pr53470_0.o-cp_lto_pr53470_0.o link,  -g -flto
> PASS->FAIL: g++.dg/lto/pr65193 cp_lto_pr65193_0.o-cp_lto_pr65193_0.o link, -fPIC -r -nostdlib -flto -O2 -g
> PASS->FAIL: g++.dg/lto/pr65316 cp_lto_pr65316_0.o-cp_lto_pr65316_1.o link,  -flto -std=c++11 -g2
> -fno-lto-odr-type-merging -O2
> PASS->FAIL: g++.dg/lto/pr65549 cp_lto_pr65549_0.o-cp_lto_pr65549_0.o link,  -std=gnu++14 -flto -g
> PASS->FAIL: g++.dg/lto/pr65549 cp_lto_pr65549_0.o-cp_lto_pr65549_0.o link,  -std=gnu++14 -flto -g -O2
> -fno-inline -flto-partition=max
> PASS->FAIL: g++.dg/lto/pr69077 cp_lto_pr69077_0.o-cp_lto_pr69077_1.o link,  -O3 -g -flto
> PASS->FAIL: g++.dg/lto/pr69137 cp_lto_pr69137_0.o-cp_lto_pr69137_0.o link,  -std=c++11 -g -flto
> PASS->FAIL: g++.dg/lto/pr79000 cp_lto_pr79000_0.o-cp_lto_pr79000_1.o link, -flto -g
> NA->FAIL: g++.dg/template/pr81899.C  -std=c++98 (test for excess errors)
> 
> > 2017-08-04  Richard Biener  <rguenther@suse.de>
> > 
> >         * debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and
> >         register_external_die hooks.
> >         (debug_false_tree_charstarstar_uhwistar): Declare.
> >         (debug_nothing_tree_charstar_uhwi): Likewise.
> >         * debug.c (do_nothing_debug_hooks): Adjust.
> >         (debug_false_tree_charstarstar_uhwistar): New do nothing.
> >         (debug_nothing_tree_charstar_uhwi): Likewise.
> >         * dbxout.c (dbx_debug_hooks): Adjust.
> >         (xcoff_debug_hooks): Likewise.
> >         * sdbout.c (sdb_debug_hooks): Likewise.
> >         * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
> > 
> >         * dwarf2out.c (macinfo_label_base): New global.
> > 	(dwarf2out_register_external_die): New function for the
> > 	register_external_die hook.
> >         (dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl.
> >         (dwarf2_debug_hooks): Use them.
> >         (dwarf2_lineno_debug_hooks): Adjust.
> >         (struct die_struct): Add with_offset flag.
> >         (DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION,
> >         DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION,
> >         DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION,
> >         DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION,
> >         DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
> >         DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros
> >         defining section names for the early LTO debug variants.
> > 	(reset_indirect_string): New helper.
> >         (add_AT_external_die_ref): Helper for dwarf2out_register_external_die.
> >         (print_dw_val): Add support for offsetted symbol references.
> > 	(get_ultimate_context): Split out from is_cxx.
> > 	(is_cxx): Use get_ultimate_context.
> > 	(is_fortran): Add decl overload.
> >         (compute_comp_unit_symbol): Split out worker from
> > 	compute_section_prefix.
> >         (compute_section_prefix): Call compute_comp_unit_symbol and
> > 	set comdat_type_p here.
> >         (output_die): Skip DIE symbol output for the LTO added one.
> >         Handle DIE symbol references with offset.
> >         (output_comp_unit): Guard section name mangling properly.
> >         For LTO debug sections emit a symbol at the section beginning
> >         which we use to refer to its DIEs.
> >         (add_abstract_origin_attribute): For DIEs registered via
> >         dwarf2out_register_external_die directly refer to the early
> >         DIE rather than indirectly through the shadow one we created.
> > 	Remove obsolete call to dwarf2out_abstract_function for
> > 	non-function/block origins.
> >         (gen_array_type_die): When generating early LTO debug do
> >         not emit DW_AT_string_length.
> >         (gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs
> >         late when in LTO.  As suggested place a gcc_unreachable for
> > 	the DECL_ABSTRACT_P case.
> >         (gen_subprogram_die): Avoid another specification DIE
> >         for early built declarations/definitions for the late LTO case.
> >         (gen_variable_die): Add type references for late duplicated VLA dies
> >         when in late LTO.
> >         (gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function,
> >         we have the abstract instance already.
> >         (process_scope_var): Adjust decl DIE contexts in LTO which
> >         first puts them in limbo.
> >         (gen_decl_die): Do not generate type DIEs late apart from
> >         types for VLAs or for decls we do not yet have a DIE.  Do not
> > 	call dwarf2out_abstract_function late.
> >         (dwarf2out_early_global_decl): Make sure to create DIEs
> >         for abstract instances of a decl first.
> >         (dwarf2out_late_global_decl): Adjust comment.
> >         (output_macinfo_op): With multiple macro sections use
> > 	macinfo_label_base to distinguish labels.
> >         (output_macinfo): Likewise.  Update macinfo_label_base.
> > 	Pass in the line info label.
> > 	(note_variable_value_in_expr): When generating LTO resolve
> > 	all variable values here by generating DIEs as needed.
> >         (init_sections_and_labels): Add early LTO debug flag parameter
> >         and generate different sections and names if set.  Add generation
> >         counter for the labels so we can have multiple of them.
> >         (reset_dies): Helper to allow DIEs to be output multiple times.
> >         (dwarf2out_finish): When outputting DIEs to the fat part of an
> > 	LTO object first reset DIEs.
> >         (dwarf2out_early_finish): Output early DIEs when generating LTO.
> > 
> > Cleanups we can do (and need) when removing the "old" LTO path and add
> > the early LTO path.
> > 
> >         (set_decl_abstract_flags): Remove.
> >         (set_block_abstract_flags): Likewise.
> >         (dwarf2out_abstract_function): Treat the early generated DIEs
> >         as the abstract copy and only add DW_AT_inline and
> >         DW_AT_artificial here and call set_decl_origin_self.
> > 	If the DIE has an abstract origin don't do anything.
> > 
> > 	* tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL
> > 	if we have none yet (Go fails to build one, PR78628).
> >         * lto-streamer-in.c: Include debug.h.
> >         (dref_queue): New global.
> >         (lto_read_tree_1): Stream in DIE references.
> >         (lto_input_tree): Register DIE references.
> > 	(input_function): Stream DECL_DEBUG_ARGS.
> >         * lto-streamer-out.c: Include debug.h.
> >         (lto_write_tree_1): Output DIE references.
> >         (DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN.
> > 	Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls.
> > 	(output_function): Stream DECL_DEBUG_ARGS.
> >         * tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers):
> >         Stream DECL_ABSTRACT_ORIGIN.
> >         * tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise.
> > 	(write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL
> > 	DECL_CONTEXT for file-scope decls.
> >         * lto-streamer.h (struct dref_entry): Declare.
> >         (dref_queue): Likewise.
> > 	* cfgexpand.c (pass_expand::execute): Do not call the
> > 	outlining_inline_function hook here.
> > 
> >         * lto-wrapper.c (debug_obj): New global.
> >         (tool_cleanup): Unlink it if required.
> >         (debug_objcopy): New function.
> >         (run_gcc): Handle early debug sections in the IL files by
> >         extracting them to separate files, partially linkin them and
> >         feeding the result back as result to the linker.
> > 
> >         * config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION,
> >         DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION,
> >         DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug
> >         sections into a separate segment.
> >         * config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO
> >         segments.
> >         (darwin_asm_dwarf_section): Likewise.
> >         (darwin_asm_output_dwarf_offset): Likewise.
> > 
> > 	* config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P.
> > 
> >         lto/
> >         * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
> >         (lto_read_decls): Process TRANSLATION_UNIT_DECLs.  Remove
> >         TYPE_DECL debug processing, register DIE references from
> >         prevailing SCCs with the debug machinery.
> >         (lto_section_with_id): Handle LTO debug sections.
> > 
> > 	libstdc++/
> > 	* testsuite/libstdc++-prettyprinters/prettyprinters.exp: Run all
> > 	tests with -flto as well if supported.
> > 
> > 	* c-c++-common/asan/global-overflow-1.c: Adjust diagnostic location
> > 	regex to handle the LTO case.
> > 	* c-c++-common/asan/heap-overflow-1.c: Likewise.
> > 	* c-c++-common/asan/misalign-1.c: Likewise.
> > 	* c-c++-common/asan/misalign-2.c: Likewise.
> > 	* c-c++-common/asan/null-deref-1.c: Likewise.
> > 	* c-c++-common/asan/stack-overflow-1.c: Likewise.
> > 	* c-c++-common/asan/strncpy-overflow-1.c: Likewise.
> > 	* c-c++-common/asan/use-after-free-1.c: Likewise.
> > 	* c-c++-common/asan/alloca_big_alignment.c: Likewise.
> > 	* c-c++-common/asan/alloca_detect_custom_size.c: Likewise.
> > 	* c-c++-common/asan/alloca_overflow_partial.c: Likewise.
> > 	* c-c++-common/asan/alloca_overflow_right.c: Likewise.
> > 	* c-c++-common/asan/alloca_underflow_left.c: Likewise.
> > 	* g++.dg/asan/large-func-test-1.C: Likewise.
> > 	* gfortran.dg/save_6.f90: Add -flto -g variant of save_5.f90.
> > 
> ...
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-08-22 10:57               ` Richard Biener
@ 2017-08-22 13:01                 ` Szabolcs Nagy
  2017-08-22 13:29                   ` Richard Biener
  0 siblings, 1 reply; 22+ messages in thread
From: Szabolcs Nagy @ 2017-08-22 13:01 UTC (permalink / raw)
  To: Richard Biener; +Cc: nd, Jason Merrill, gcc-patches List

On 22/08/17 11:17, Richard Biener wrote:
> On Tue, 22 Aug 2017, Szabolcs Nagy wrote:
>> on aarch64_be-none-elf i see
>>
>> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 (test for excess errors)
>> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -O (test for excess errors)
>> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -O3 (test for excess errors)
>> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 (test for excess errors)
>> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 -O (test for excess errors)
>> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 -O3 (test for excess errors)
>> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 (test for excess errors)
>> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 -O (test for excess errors)
>> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 -O3 (test for excess errors)
>> PASS->FAIL: gcc.dg/lto/20090914-1 c_lto_20090914-1_0.o-c_lto_20090914-1_0.o link, -flto
>> PASS->FAIL: gcc.dg/lto/20100426 c_lto_20100426_0.o-c_lto_20100426_0.o link, -r -nostdlib -flto -g
>> PASS->FAIL: gcc.dg/lto/20111207-2 c_lto_20111207-2_0.o-c_lto_20111207-2_0.o link,  -g -O -flto
>> PASS->FAIL: gcc.dg/lto/20111213-1 c_lto_20111213-1_0.o-c_lto_20111213-1_0.o link,  -flto -g
>> PASS->FAIL: gcc.dg/lto/pr51572-1 c_lto_pr51572-1_0.o-c_lto_pr51572-1_0.o link,  -flto -g
>> PASS->FAIL: gcc.dg/lto/pr53470 c_lto_pr53470_0.o-c_lto_pr53470_0.o link,  -flto -g
>> PASS->FAIL: gcc.dg/lto/pr59323 c_lto_pr59323_0.o-c_lto_pr59323_0.o link,  -O2 -g -flto
>> PASS->FAIL: gcc.dg/lto/pr59323-2 c_lto_pr59323-2_0.o-c_lto_pr59323-2_0.o link,  -O2 -g -flto
>> PASS->FAIL: gcc.dg/pr43557-1.c (test for excess errors)
>>
>> linking seems to fail with
>>
>> /tmp/ccqAb1Wfdebugobjtem: file not recognized: Bad value
>> collect2: error: ld returned 1 exit status
>> lto-wrapper: fatal error: B/gcc/xgcc returned 1 exit status
>> compilation terminated.
>> P/aarch64_be-none-elf/bin/ld: error: lto-wrapper failed
>> collect2: error: ld returned 1 exit status
>> compiler exited with status 1
> 
> Can you file a bugreport please?  Can you investigate a bit, I suspect
> a simple int main() {} and ./xgcc -B. -flto -g t.c fails the same way.
> With -save-temps -v you should be able to inspect the generated
> debugobj with readelf.
> 

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81925

i could not figure much out, readelf could parse lto1 input
but printed errors on the final link command input.

> Is this a native compiler or a cross-compiler?  [I suspect endianess
> issues somewhere?]

cross compiler (from aarch64-linux-gnu to aarch64_be-none-elf)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-08-22 13:01                 ` Szabolcs Nagy
@ 2017-08-22 13:29                   ` Richard Biener
  0 siblings, 0 replies; 22+ messages in thread
From: Richard Biener @ 2017-08-22 13:29 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: nd, Jason Merrill, gcc-patches List

On Tue, 22 Aug 2017, Szabolcs Nagy wrote:

> On 22/08/17 11:17, Richard Biener wrote:
> > On Tue, 22 Aug 2017, Szabolcs Nagy wrote:
> >> on aarch64_be-none-elf i see
> >>
> >> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 (test for excess errors)
> >> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -O (test for excess errors)
> >> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -O3 (test for excess errors)
> >> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 (test for excess errors)
> >> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 -O (test for excess errors)
> >> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g1 -O3 (test for excess errors)
> >> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 (test for excess errors)
> >> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 -O (test for excess errors)
> >> PASS->FAIL: gcc.dg/debug/pr41893-1.c -gdwarf-2 -g3 -O3 (test for excess errors)
> >> PASS->FAIL: gcc.dg/lto/20090914-1 c_lto_20090914-1_0.o-c_lto_20090914-1_0.o link, -flto
> >> PASS->FAIL: gcc.dg/lto/20100426 c_lto_20100426_0.o-c_lto_20100426_0.o link, -r -nostdlib -flto -g
> >> PASS->FAIL: gcc.dg/lto/20111207-2 c_lto_20111207-2_0.o-c_lto_20111207-2_0.o link,  -g -O -flto
> >> PASS->FAIL: gcc.dg/lto/20111213-1 c_lto_20111213-1_0.o-c_lto_20111213-1_0.o link,  -flto -g
> >> PASS->FAIL: gcc.dg/lto/pr51572-1 c_lto_pr51572-1_0.o-c_lto_pr51572-1_0.o link,  -flto -g
> >> PASS->FAIL: gcc.dg/lto/pr53470 c_lto_pr53470_0.o-c_lto_pr53470_0.o link,  -flto -g
> >> PASS->FAIL: gcc.dg/lto/pr59323 c_lto_pr59323_0.o-c_lto_pr59323_0.o link,  -O2 -g -flto
> >> PASS->FAIL: gcc.dg/lto/pr59323-2 c_lto_pr59323-2_0.o-c_lto_pr59323-2_0.o link,  -O2 -g -flto
> >> PASS->FAIL: gcc.dg/pr43557-1.c (test for excess errors)
> >>
> >> linking seems to fail with
> >>
> >> /tmp/ccqAb1Wfdebugobjtem: file not recognized: Bad value
> >> collect2: error: ld returned 1 exit status
> >> lto-wrapper: fatal error: B/gcc/xgcc returned 1 exit status
> >> compilation terminated.
> >> P/aarch64_be-none-elf/bin/ld: error: lto-wrapper failed
> >> collect2: error: ld returned 1 exit status
> >> compiler exited with status 1
> > 
> > Can you file a bugreport please?  Can you investigate a bit, I suspect
> > a simple int main() {} and ./xgcc -B. -flto -g t.c fails the same way.
> > With -save-temps -v you should be able to inspect the generated
> > debugobj with readelf.
> > 
> 
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81925
> 
> i could not figure much out, readelf could parse lto1 input
> but printed errors on the final link command input.
> 
> > Is this a native compiler or a cross-compiler?  [I suspect endianess
> > issues somewhere?]
> 
> cross compiler (from aarch64-linux-gnu to aarch64_be-none-elf)

I am testing the following fix (verified with a cross), will apply
as obvious if that succeeds.

Richard.

2017-08-22  Richard Biener  <rguenther@suse.de>

	PR lto/81925
	* simple-object-elf.c (simple_object_elf_write_shdr): Adjust
	type of sh_addralign and sh_entsize and properly write
	sh_entsize as Elf_Addr.
	(simple_object_elf_write_to_file): Read sh_entsize as Elf_Addr.

Index: libiberty/simple-object-elf.c
===================================================================
--- libiberty/simple-object-elf.c	(revision 251273)
+++ libiberty/simple-object-elf.c	(working copy)
@@ -830,8 +830,8 @@ simple_object_elf_write_shdr (simple_obj
 			      off_t sh_addr,
 			      unsigned int sh_offset, unsigned int sh_size,
 			      unsigned int sh_link, unsigned int sh_info,
-			      unsigned int sh_addralign,
-			      unsigned int sh_entsize,
+			      size_t sh_addralign,
+			      size_t sh_entsize,
 			      const char **errmsg, int *err)
 {
   struct simple_object_elf_attributes *attrs =
@@ -858,7 +858,7 @@ simple_object_elf_write_shdr (simple_obj
   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link);
   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_info, Elf_Word, sh_info);
   ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
-  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_entsize, Elf_Word, sh_entsize);
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_entsize, Elf_Addr, sh_entsize);
 
   return simple_object_internal_write (descriptor, offset, buf, shdr_size,
 				       errmsg, err);
@@ -948,8 +948,8 @@ simple_object_elf_write_to_file (simple_
       off_t sh_addr = 0;
       unsigned int sh_link = 0;
       unsigned int sh_info = 0;
-      unsigned int sh_addralign = 1U << section->align;
-      unsigned int sh_entsize = 0;
+      size_t sh_addralign = 1U << section->align;
+      size_t sh_entsize = 0;
       if (eow->shdrs)
 	{
 	  sh_type = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
@@ -972,7 +972,7 @@ simple_object_elf_write_to_file (simple_
 					  sh_addralign, Elf_Addr);
 	  sh_entsize = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
 					eow->shdrs + secnum * shdr_size,
-					sh_entsize, Elf_Word);
+					sh_entsize, Elf_Addr);
 	  secnum++;
 	}
 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-08-04 12:21           ` Richard Biener
  2017-08-22 10:49             ` Szabolcs Nagy
@ 2017-09-19 15:24             ` Jakub Jelinek
  2017-09-19 21:22               ` Jakub Jelinek
  1 sibling, 1 reply; 22+ messages in thread
From: Jakub Jelinek @ 2017-09-19 15:24 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jason Merrill, gcc-patches List

On Fri, Aug 04, 2017 at 02:21:29PM +0200, Richard Biener wrote:
> ! /* Initialize the various sections and labels for dwarf output.  */
>   
>   static void
> ! init_sections_and_labels (void)

...

These changes broke DWARF-5 support.  E.g. in gcc-7 and before this change
there was:

> !   if (!dwarf_split_debug_info)
>       {
...
> !       debug_loc_section = get_section (dwarf_version >= 5
> ! 				       ? DEBUG_LOCLISTS_SECTION
> ! 				       : DEBUG_LOC_SECTION,
> !                                        SECTION_DEBUG, NULL);

the above which would use .debug_loclists section for debug_loc_section
instead of .debug_loc for -gdwarf-5, because that is what DWARF-5 requires
and the section content is ABI incompatible.  But current trunk does
> ! 	  debug_loc_section = get_section (DEBUG_LOC_SECTION,
> ! 					   SECTION_DEBUG, NULL);
only, so the DWARF-5 content is emitted into .debug_loc section.

Or, there used to be:

> !   if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
> !     debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
> ! 					  DEBUG_STR_SECTION_FLAGS, NULL);

which has no replacement at all, debug_line_str_hash is NULL and
so !DWARF2_ASM_LINE_DEBUG_INFO compiler ICEs on pretty much all
-gdwarf-5, because it can't emit the strings into that section.

Do you have rough time when you wrote changes to these functions (so that
I could diff init_sections_and_labels changes in between that date and
before your LTO debug changes and find out what needs to be double checked
besides those two)?

I presume we'll need some name for a LTO .debug_loclists variant.

Also, seeing:

#ifndef DEBUG_LINE_SECTION
#define DEBUG_LINE_SECTION      ".debug_line"
#endif
#ifndef DEBUG_DWO_LINE_SECTION
#define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
#endif
#ifndef DEBUG_LTO_LINE_SECTION
#define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
#endif

that looks like a pasto, , I'd expect the last one, since it doesn't have
DWO_ in the name, to be just .gnu.debuglto_.debug_line .

	Jakub

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-09-19 15:24             ` Jakub Jelinek
@ 2017-09-19 21:22               ` Jakub Jelinek
  2017-09-20  8:20                 ` Richard Biener
  0 siblings, 1 reply; 22+ messages in thread
From: Jakub Jelinek @ 2017-09-19 21:22 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jason Merrill, gcc-patches List

On Tue, Sep 19, 2017 at 05:24:14PM +0200, Jakub Jelinek wrote:
> These changes broke DWARF-5 support.  E.g. in gcc-7 and before this change
> there was:

Here is a fix, make check-g++ RUNTESTFLAGS=dwarf2.exp now passes again
even with !DWARF2_ASM_LINE_DEBUG_INFO compiler.  Haven't tried LTO (except
for what is in make check).  Bootstrapped/regtested on x86_64-linux and
i686-linux, ok for trunk?

2017-09-19  Jakub Jelinek  <jakub@redhat.com>

	* dwarf2out.c (DEBUG_LTO_DWO_INFO_SECTION): Reorder defines.
	(DEBUG_LTO_ABBREV_SECTION): Likewise.
	(DEBUG_LTO_MACINFO_SECTION): Likewise.
	(DEBUG_MACRO_SECTION): Likewise.
	(DEBUG_LTO_MACRO_SECTION): Likewise.
	(DEBUG_STR_DWO_SECTION): Likewise.
	(DEBUG_LTO_STR_DWO_SECTION): Likewise.
	(DEBUG_LTO_LINE_SECTION): Drop .dwo suffix from the name.
	(DEBUG_LTO_DWO_LINE_SECTION): Define.
	(DEBUG_LTO_LINE_STR_SECTION): Define.
	(init_sections_and_labels): Initialize debug_line_str_section
	variable.  Initialize debug_loc_section for -gdwarf-5 to
	DEBUG_LOCLISTS_SECTION.  Formatting fixes.

--- gcc/dwarf2out.c.jj	2017-09-19 16:51:16.000000000 +0200
+++ gcc/dwarf2out.c	2017-09-19 18:07:51.348919965 +0200
@@ -3702,24 +3702,24 @@ new_addr_loc_descr (rtx addr, enum dtpre
 #ifndef DEBUG_DWO_INFO_SECTION
 #define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
 #endif
-#ifndef DEBUG_LTO_DWO_INFO_SECTION
-#define DEBUG_LTO_DWO_INFO_SECTION ".gnu.debuglto_.debug_info.dwo"
-#endif
 #ifndef DEBUG_LTO_INFO_SECTION
 #define DEBUG_LTO_INFO_SECTION	".gnu.debuglto_.debug_info"
 #endif
+#ifndef DEBUG_LTO_DWO_INFO_SECTION
+#define DEBUG_LTO_DWO_INFO_SECTION ".gnu.debuglto_.debug_info.dwo"
+#endif
 #ifndef DEBUG_ABBREV_SECTION
 #define DEBUG_ABBREV_SECTION	".debug_abbrev"
 #endif
+#ifndef DEBUG_LTO_ABBREV_SECTION
+#define DEBUG_LTO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev"
+#endif
 #ifndef DEBUG_DWO_ABBREV_SECTION
 #define DEBUG_DWO_ABBREV_SECTION ".debug_abbrev.dwo"
 #endif
 #ifndef DEBUG_LTO_DWO_ABBREV_SECTION
 #define DEBUG_LTO_DWO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev.dwo"
 #endif
-#ifndef DEBUG_LTO_ABBREV_SECTION
-#define DEBUG_LTO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev"
-#endif
 #ifndef DEBUG_ARANGES_SECTION
 #define DEBUG_ARANGES_SECTION	".debug_aranges"
 #endif
@@ -3729,35 +3729,38 @@ new_addr_loc_descr (rtx addr, enum dtpre
 #ifndef DEBUG_MACINFO_SECTION
 #define DEBUG_MACINFO_SECTION     ".debug_macinfo"
 #endif
+#ifndef DEBUG_LTO_MACINFO_SECTION
+#define DEBUG_LTO_MACINFO_SECTION      ".gnu.debuglto_.debug_macinfo"
+#endif
 #ifndef DEBUG_DWO_MACINFO_SECTION
 #define DEBUG_DWO_MACINFO_SECTION      ".debug_macinfo.dwo"
 #endif
 #ifndef DEBUG_LTO_DWO_MACINFO_SECTION
 #define DEBUG_LTO_DWO_MACINFO_SECTION  ".gnu.debuglto_.debug_macinfo.dwo"
 #endif
-#ifndef DEBUG_LTO_MACINFO_SECTION
-#define DEBUG_LTO_MACINFO_SECTION      ".gnu.debuglto_.debug_macinfo"
+#ifndef DEBUG_MACRO_SECTION
+#define DEBUG_MACRO_SECTION	".debug_macro"
+#endif
+#ifndef DEBUG_LTO_MACRO_SECTION
+#define DEBUG_LTO_MACRO_SECTION ".gnu.debuglto_.debug_macro"
 #endif
 #ifndef DEBUG_DWO_MACRO_SECTION
 #define DEBUG_DWO_MACRO_SECTION        ".debug_macro.dwo"
 #endif
-#ifndef DEBUG_MACRO_SECTION
-#define DEBUG_MACRO_SECTION	".debug_macro"
-#endif
 #ifndef DEBUG_LTO_DWO_MACRO_SECTION
 #define DEBUG_LTO_DWO_MACRO_SECTION    ".gnu.debuglto_.debug_macro.dwo"
 #endif
-#ifndef DEBUG_LTO_MACRO_SECTION
-#define DEBUG_LTO_MACRO_SECTION ".gnu.debuglto_.debug_macro"
-#endif
 #ifndef DEBUG_LINE_SECTION
 #define DEBUG_LINE_SECTION	".debug_line"
 #endif
+#ifndef DEBUG_LTO_LINE_SECTION
+#define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line"
+#endif
 #ifndef DEBUG_DWO_LINE_SECTION
 #define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
 #endif
-#ifndef DEBUG_LTO_LINE_SECTION
-#define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
+#ifndef DEBUG_LTO_DWO_LINE_SECTION
+#define DEBUG_LTO_DWO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
 #endif
 #ifndef DEBUG_LOC_SECTION
 #define DEBUG_LOC_SECTION	".debug_loc"
@@ -3790,18 +3793,18 @@ new_addr_loc_descr (rtx addr, enum dtpre
 #ifndef DEBUG_LTO_DWO_STR_OFFSETS_SECTION
 #define DEBUG_LTO_DWO_STR_OFFSETS_SECTION ".gnu.debuglto_.debug_str_offsets.dwo"
 #endif
-#ifndef DEBUG_STR_DWO_SECTION
-#define DEBUG_STR_DWO_SECTION   ".debug_str.dwo"
-#endif
-#ifndef DEBUG_LTO_STR_DWO_SECTION
-#define DEBUG_LTO_STR_DWO_SECTION ".gnu.debuglto_.debug_str.dwo"
-#endif
 #ifndef DEBUG_STR_SECTION
 #define DEBUG_STR_SECTION  ".debug_str"
 #endif
 #ifndef DEBUG_LTO_STR_SECTION
 #define DEBUG_LTO_STR_SECTION ".gnu.debuglto_.debug_str"
 #endif
+#ifndef DEBUG_STR_DWO_SECTION
+#define DEBUG_STR_DWO_SECTION   ".debug_str.dwo"
+#endif
+#ifndef DEBUG_LTO_STR_DWO_SECTION
+#define DEBUG_LTO_STR_DWO_SECTION ".gnu.debuglto_.debug_str.dwo"
+#endif
 #ifndef DEBUG_RANGES_SECTION
 #define DEBUG_RANGES_SECTION	".debug_ranges"
 #endif
@@ -3811,6 +3814,9 @@ new_addr_loc_descr (rtx addr, enum dtpre
 #ifndef DEBUG_LINE_STR_SECTION
 #define DEBUG_LINE_STR_SECTION  ".debug_line_str"
 #endif
+#ifndef DEBUG_LTO_LINE_STR_SECTION
+#define DEBUG_LTO_LINE_STR_SECTION  ".gnu.debuglto_.debug_line_str"
+#endif
 
 /* Standard ELF section names for compiled code and data.  */
 #ifndef TEXT_SECTION_NAME
@@ -27188,7 +27194,8 @@ output_macinfo (const char *debug_line_l
 static void
 init_sections_and_labels (bool early_lto_debug)
 {
-  /* As we may get called multiple times have a generation count for labels.  */
+  /* As we may get called multiple times have a generation count for
+     labels.  */
   static unsigned generation = 0;
 
   if (early_lto_debug)
@@ -27201,14 +27208,14 @@ init_sections_and_labels (bool early_lto
 	  debug_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
 					      SECTION_DEBUG | SECTION_EXCLUDE,
 					      NULL);
-	  debug_macinfo_section_name = ((dwarf_strict && dwarf_version < 5)
-					? DEBUG_LTO_MACINFO_SECTION
-					: DEBUG_LTO_MACRO_SECTION);
+	  debug_macinfo_section_name
+	    = ((dwarf_strict && dwarf_version < 5)
+	       ? DEBUG_LTO_MACINFO_SECTION : DEBUG_LTO_MACRO_SECTION);
 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
 					       SECTION_DEBUG
 					       | SECTION_EXCLUDE, NULL);
-	  /* For macro info we have to refer to a debug_line section, so similar
-	     to split-dwarf emit a skeleton one for early debug.  */
+	  /* For macro info we have to refer to a debug_line section, so
+	     similar to split-dwarf emit a skeleton one for early debug.  */
 	  debug_skeleton_line_section
 	    = get_section (DEBUG_LTO_LINE_SECTION,
 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
@@ -27228,15 +27235,16 @@ init_sections_and_labels (bool early_lto
 	  debug_skeleton_info_section = get_section (DEBUG_LTO_INFO_SECTION,
 						     SECTION_DEBUG
 						     | SECTION_EXCLUDE, NULL);
-	  debug_skeleton_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
-						       SECTION_DEBUG
-						       | SECTION_EXCLUDE, NULL);
+	  debug_skeleton_abbrev_section
+	    = get_section (DEBUG_LTO_ABBREV_SECTION,
+			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
 				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
 				       generation);
 
-	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
-	     the main .o, but the skeleton_line goes into the split off dwo.  */
+	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections
+	     stay in the main .o, but the skeleton_line goes into the split
+	     off dwo.  */
 	  debug_skeleton_line_section
 	    = get_section (DEBUG_LTO_LINE_SECTION,
 			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
@@ -27251,9 +27259,10 @@ init_sections_and_labels (bool early_lto
 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
 				       generation);
 	  debug_str_dwo_section = get_section (DEBUG_LTO_STR_DWO_SECTION,
-					       DEBUG_STR_DWO_SECTION_FLAGS, NULL);
+					       DEBUG_STR_DWO_SECTION_FLAGS,
+					       NULL);
 	  debug_macinfo_section_name
-	    = (dwarf_strict
+	    = ((dwarf_strict && dwarf_version < 5)
 	       ? DEBUG_LTO_DWO_MACINFO_SECTION : DEBUG_LTO_DWO_MACRO_SECTION);
 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
 					       SECTION_DEBUG | SECTION_EXCLUDE,
@@ -27262,6 +27271,10 @@ init_sections_and_labels (bool early_lto
       debug_str_section = get_section (DEBUG_LTO_STR_SECTION,
 				       DEBUG_STR_SECTION_FLAGS
 				       | SECTION_EXCLUDE, NULL);
+      if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
+	debug_line_str_section
+	  = get_section (DEBUG_LTO_LINE_STR_SECTION,
+			 DEBUG_STR_SECTION_FLAGS | SECTION_EXCLUDE, NULL);
     }
   else
     {
@@ -27271,10 +27284,13 @@ init_sections_and_labels (bool early_lto
 					    SECTION_DEBUG, NULL);
 	  debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
 					      SECTION_DEBUG, NULL);
-	  debug_loc_section = get_section (DEBUG_LOC_SECTION,
+	  debug_loc_section = get_section (dwarf_version >= 5
+					   ? DEBUG_LOCLISTS_SECTION
+					   : DEBUG_LOC_SECTION,
 					   SECTION_DEBUG, NULL);
 	  debug_macinfo_section_name
-	      = dwarf_strict ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
+	    = ((dwarf_strict && dwarf_version < 5)
+	       ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION);
 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
 					       SECTION_DEBUG, NULL);
 	}
@@ -27311,15 +27327,17 @@ init_sections_and_labels (bool early_lto
 	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
 				       DEBUG_SKELETON_INFO_SECTION_LABEL,
 				       generation);
-	  debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION,
+	  debug_loc_section = get_section (dwarf_version >= 5
+					   ? DEBUG_DWO_LOCLISTS_SECTION
+					   : DEBUG_DWO_LOC_SECTION,
 					   SECTION_DEBUG | SECTION_EXCLUDE,
 					   NULL);
 	  debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
 					       DEBUG_STR_DWO_SECTION_FLAGS,
 					       NULL);
 	  debug_macinfo_section_name
-	    = (dwarf_strict && dwarf_version < 5)
-	      ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
+	    = ((dwarf_strict && dwarf_version < 5)
+	       ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION);
 	  debug_macinfo_section = get_section (debug_macinfo_section_name,
 					       SECTION_DEBUG | SECTION_EXCLUDE,
 					       NULL);
@@ -27334,6 +27352,9 @@ init_sections_and_labels (bool early_lto
 					    SECTION_DEBUG, NULL);
       debug_str_section = get_section (DEBUG_STR_SECTION,
 				       DEBUG_STR_SECTION_FLAGS, NULL);
+      if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
+	debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
+					      DEBUG_STR_SECTION_FLAGS, NULL);
       debug_ranges_section = get_section (dwarf_version >= 5
 					  ? DEBUG_RNGLISTS_SECTION
 					  : DEBUG_RANGES_SECTION,
@@ -27355,7 +27376,7 @@ init_sections_and_labels (bool early_lto
     ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
 				 DEBUG_RANGES_SECTION_LABEL, 2 + generation);
   ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
-                               DEBUG_ADDR_SECTION_LABEL, generation);
+			       DEBUG_ADDR_SECTION_LABEL, generation);
   ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
 			       (dwarf_strict && dwarf_version < 5)
 			       ? DEBUG_MACINFO_SECTION_LABEL


	Jakub

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-09-19 21:22               ` Jakub Jelinek
@ 2017-09-20  8:20                 ` Richard Biener
  2017-09-20  8:31                   ` Jakub Jelinek
  0 siblings, 1 reply; 22+ messages in thread
From: Richard Biener @ 2017-09-20  8:20 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jason Merrill, gcc-patches List

On Tue, 19 Sep 2017, Jakub Jelinek wrote:

> On Tue, Sep 19, 2017 at 05:24:14PM +0200, Jakub Jelinek wrote:
> > These changes broke DWARF-5 support.  E.g. in gcc-7 and before this change
> > there was:

Sorry for the breakage I had to manually merge conflicts in this
part quite a few times since the 1.5 years the patch was under review.
Appearantly there's no testsuite coverage for this when testing with
default flags (nor is there any coverage for -gsplit-dwarf btw...).

> Here is a fix, make check-g++ RUNTESTFLAGS=dwarf2.exp now passes again
> even with !DWARF2_ASM_LINE_DEBUG_INFO compiler.  Haven't tried LTO (except
> for what is in make check).  Bootstrapped/regtested on x86_64-linux and
> i686-linux, ok for trunk?
> 
> 2017-09-19  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* dwarf2out.c (DEBUG_LTO_DWO_INFO_SECTION): Reorder defines.
> 	(DEBUG_LTO_ABBREV_SECTION): Likewise.
> 	(DEBUG_LTO_MACINFO_SECTION): Likewise.
> 	(DEBUG_MACRO_SECTION): Likewise.
> 	(DEBUG_LTO_MACRO_SECTION): Likewise.
> 	(DEBUG_STR_DWO_SECTION): Likewise.
> 	(DEBUG_LTO_STR_DWO_SECTION): Likewise.
> 	(DEBUG_LTO_LINE_SECTION): Drop .dwo suffix from the name.

I think this has .dwo because similar to DWO this section can
be dropped (it's only "fake" because for some reason we do have
to have a line section).

Anyway, I did a quick LTO bootstrap with your patch and it seems
to work fine.

Can you add a testcase verifying -gdwarf-5 works ok (properly
emitting a debug_line_str section?).

Ok with that change.

Thanks and sorry for the breakage,
Richard.

> 	(DEBUG_LTO_DWO_LINE_SECTION): Define.
> 	(DEBUG_LTO_LINE_STR_SECTION): Define.
> 	(init_sections_and_labels): Initialize debug_line_str_section
> 	variable.  Initialize debug_loc_section for -gdwarf-5 to
> 	DEBUG_LOCLISTS_SECTION.  Formatting fixes.
> 
> --- gcc/dwarf2out.c.jj	2017-09-19 16:51:16.000000000 +0200
> +++ gcc/dwarf2out.c	2017-09-19 18:07:51.348919965 +0200
> @@ -3702,24 +3702,24 @@ new_addr_loc_descr (rtx addr, enum dtpre
>  #ifndef DEBUG_DWO_INFO_SECTION
>  #define DEBUG_DWO_INFO_SECTION ".debug_info.dwo"
>  #endif
> -#ifndef DEBUG_LTO_DWO_INFO_SECTION
> -#define DEBUG_LTO_DWO_INFO_SECTION ".gnu.debuglto_.debug_info.dwo"
> -#endif
>  #ifndef DEBUG_LTO_INFO_SECTION
>  #define DEBUG_LTO_INFO_SECTION	".gnu.debuglto_.debug_info"
>  #endif
> +#ifndef DEBUG_LTO_DWO_INFO_SECTION
> +#define DEBUG_LTO_DWO_INFO_SECTION ".gnu.debuglto_.debug_info.dwo"
> +#endif
>  #ifndef DEBUG_ABBREV_SECTION
>  #define DEBUG_ABBREV_SECTION	".debug_abbrev"
>  #endif
> +#ifndef DEBUG_LTO_ABBREV_SECTION
> +#define DEBUG_LTO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev"
> +#endif
>  #ifndef DEBUG_DWO_ABBREV_SECTION
>  #define DEBUG_DWO_ABBREV_SECTION ".debug_abbrev.dwo"
>  #endif
>  #ifndef DEBUG_LTO_DWO_ABBREV_SECTION
>  #define DEBUG_LTO_DWO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev.dwo"
>  #endif
> -#ifndef DEBUG_LTO_ABBREV_SECTION
> -#define DEBUG_LTO_ABBREV_SECTION ".gnu.debuglto_.debug_abbrev"
> -#endif
>  #ifndef DEBUG_ARANGES_SECTION
>  #define DEBUG_ARANGES_SECTION	".debug_aranges"
>  #endif
> @@ -3729,35 +3729,38 @@ new_addr_loc_descr (rtx addr, enum dtpre
>  #ifndef DEBUG_MACINFO_SECTION
>  #define DEBUG_MACINFO_SECTION     ".debug_macinfo"
>  #endif
> +#ifndef DEBUG_LTO_MACINFO_SECTION
> +#define DEBUG_LTO_MACINFO_SECTION      ".gnu.debuglto_.debug_macinfo"
> +#endif
>  #ifndef DEBUG_DWO_MACINFO_SECTION
>  #define DEBUG_DWO_MACINFO_SECTION      ".debug_macinfo.dwo"
>  #endif
>  #ifndef DEBUG_LTO_DWO_MACINFO_SECTION
>  #define DEBUG_LTO_DWO_MACINFO_SECTION  ".gnu.debuglto_.debug_macinfo.dwo"
>  #endif
> -#ifndef DEBUG_LTO_MACINFO_SECTION
> -#define DEBUG_LTO_MACINFO_SECTION      ".gnu.debuglto_.debug_macinfo"
> +#ifndef DEBUG_MACRO_SECTION
> +#define DEBUG_MACRO_SECTION	".debug_macro"
> +#endif
> +#ifndef DEBUG_LTO_MACRO_SECTION
> +#define DEBUG_LTO_MACRO_SECTION ".gnu.debuglto_.debug_macro"
>  #endif
>  #ifndef DEBUG_DWO_MACRO_SECTION
>  #define DEBUG_DWO_MACRO_SECTION        ".debug_macro.dwo"
>  #endif
> -#ifndef DEBUG_MACRO_SECTION
> -#define DEBUG_MACRO_SECTION	".debug_macro"
> -#endif
>  #ifndef DEBUG_LTO_DWO_MACRO_SECTION
>  #define DEBUG_LTO_DWO_MACRO_SECTION    ".gnu.debuglto_.debug_macro.dwo"
>  #endif
> -#ifndef DEBUG_LTO_MACRO_SECTION
> -#define DEBUG_LTO_MACRO_SECTION ".gnu.debuglto_.debug_macro"
> -#endif
>  #ifndef DEBUG_LINE_SECTION
>  #define DEBUG_LINE_SECTION	".debug_line"
>  #endif
> +#ifndef DEBUG_LTO_LINE_SECTION
> +#define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line"
> +#endif
>  #ifndef DEBUG_DWO_LINE_SECTION
>  #define DEBUG_DWO_LINE_SECTION ".debug_line.dwo"
>  #endif
> -#ifndef DEBUG_LTO_LINE_SECTION
> -#define DEBUG_LTO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
> +#ifndef DEBUG_LTO_DWO_LINE_SECTION
> +#define DEBUG_LTO_DWO_LINE_SECTION ".gnu.debuglto_.debug_line.dwo"
>  #endif
>  #ifndef DEBUG_LOC_SECTION
>  #define DEBUG_LOC_SECTION	".debug_loc"
> @@ -3790,18 +3793,18 @@ new_addr_loc_descr (rtx addr, enum dtpre
>  #ifndef DEBUG_LTO_DWO_STR_OFFSETS_SECTION
>  #define DEBUG_LTO_DWO_STR_OFFSETS_SECTION ".gnu.debuglto_.debug_str_offsets.dwo"
>  #endif
> -#ifndef DEBUG_STR_DWO_SECTION
> -#define DEBUG_STR_DWO_SECTION   ".debug_str.dwo"
> -#endif
> -#ifndef DEBUG_LTO_STR_DWO_SECTION
> -#define DEBUG_LTO_STR_DWO_SECTION ".gnu.debuglto_.debug_str.dwo"
> -#endif
>  #ifndef DEBUG_STR_SECTION
>  #define DEBUG_STR_SECTION  ".debug_str"
>  #endif
>  #ifndef DEBUG_LTO_STR_SECTION
>  #define DEBUG_LTO_STR_SECTION ".gnu.debuglto_.debug_str"
>  #endif
> +#ifndef DEBUG_STR_DWO_SECTION
> +#define DEBUG_STR_DWO_SECTION   ".debug_str.dwo"
> +#endif
> +#ifndef DEBUG_LTO_STR_DWO_SECTION
> +#define DEBUG_LTO_STR_DWO_SECTION ".gnu.debuglto_.debug_str.dwo"
> +#endif
>  #ifndef DEBUG_RANGES_SECTION
>  #define DEBUG_RANGES_SECTION	".debug_ranges"
>  #endif
> @@ -3811,6 +3814,9 @@ new_addr_loc_descr (rtx addr, enum dtpre
>  #ifndef DEBUG_LINE_STR_SECTION
>  #define DEBUG_LINE_STR_SECTION  ".debug_line_str"
>  #endif
> +#ifndef DEBUG_LTO_LINE_STR_SECTION
> +#define DEBUG_LTO_LINE_STR_SECTION  ".gnu.debuglto_.debug_line_str"
> +#endif
>  
>  /* Standard ELF section names for compiled code and data.  */
>  #ifndef TEXT_SECTION_NAME
> @@ -27188,7 +27194,8 @@ output_macinfo (const char *debug_line_l
>  static void
>  init_sections_and_labels (bool early_lto_debug)
>  {
> -  /* As we may get called multiple times have a generation count for labels.  */
> +  /* As we may get called multiple times have a generation count for
> +     labels.  */
>    static unsigned generation = 0;
>  
>    if (early_lto_debug)
> @@ -27201,14 +27208,14 @@ init_sections_and_labels (bool early_lto
>  	  debug_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
>  					      SECTION_DEBUG | SECTION_EXCLUDE,
>  					      NULL);
> -	  debug_macinfo_section_name = ((dwarf_strict && dwarf_version < 5)
> -					? DEBUG_LTO_MACINFO_SECTION
> -					: DEBUG_LTO_MACRO_SECTION);
> +	  debug_macinfo_section_name
> +	    = ((dwarf_strict && dwarf_version < 5)
> +	       ? DEBUG_LTO_MACINFO_SECTION : DEBUG_LTO_MACRO_SECTION);
>  	  debug_macinfo_section = get_section (debug_macinfo_section_name,
>  					       SECTION_DEBUG
>  					       | SECTION_EXCLUDE, NULL);
> -	  /* For macro info we have to refer to a debug_line section, so similar
> -	     to split-dwarf emit a skeleton one for early debug.  */
> +	  /* For macro info we have to refer to a debug_line section, so
> +	     similar to split-dwarf emit a skeleton one for early debug.  */
>  	  debug_skeleton_line_section
>  	    = get_section (DEBUG_LTO_LINE_SECTION,
>  			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> @@ -27228,15 +27235,16 @@ init_sections_and_labels (bool early_lto
>  	  debug_skeleton_info_section = get_section (DEBUG_LTO_INFO_SECTION,
>  						     SECTION_DEBUG
>  						     | SECTION_EXCLUDE, NULL);
> -	  debug_skeleton_abbrev_section = get_section (DEBUG_LTO_ABBREV_SECTION,
> -						       SECTION_DEBUG
> -						       | SECTION_EXCLUDE, NULL);
> +	  debug_skeleton_abbrev_section
> +	    = get_section (DEBUG_LTO_ABBREV_SECTION,
> +			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
>  	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_abbrev_section_label,
>  				       DEBUG_SKELETON_ABBREV_SECTION_LABEL,
>  				       generation);
>  
> -	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections stay in
> -	     the main .o, but the skeleton_line goes into the split off dwo.  */
> +	  /* Somewhat confusing detail: The skeleton_[abbrev|info] sections
> +	     stay in the main .o, but the skeleton_line goes into the split
> +	     off dwo.  */
>  	  debug_skeleton_line_section
>  	    = get_section (DEBUG_LTO_LINE_SECTION,
>  			   SECTION_DEBUG | SECTION_EXCLUDE, NULL);
> @@ -27251,9 +27259,10 @@ init_sections_and_labels (bool early_lto
>  				       DEBUG_SKELETON_INFO_SECTION_LABEL,
>  				       generation);
>  	  debug_str_dwo_section = get_section (DEBUG_LTO_STR_DWO_SECTION,
> -					       DEBUG_STR_DWO_SECTION_FLAGS, NULL);
> +					       DEBUG_STR_DWO_SECTION_FLAGS,
> +					       NULL);
>  	  debug_macinfo_section_name
> -	    = (dwarf_strict
> +	    = ((dwarf_strict && dwarf_version < 5)
>  	       ? DEBUG_LTO_DWO_MACINFO_SECTION : DEBUG_LTO_DWO_MACRO_SECTION);
>  	  debug_macinfo_section = get_section (debug_macinfo_section_name,
>  					       SECTION_DEBUG | SECTION_EXCLUDE,
> @@ -27262,6 +27271,10 @@ init_sections_and_labels (bool early_lto
>        debug_str_section = get_section (DEBUG_LTO_STR_SECTION,
>  				       DEBUG_STR_SECTION_FLAGS
>  				       | SECTION_EXCLUDE, NULL);
> +      if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
> +	debug_line_str_section
> +	  = get_section (DEBUG_LTO_LINE_STR_SECTION,
> +			 DEBUG_STR_SECTION_FLAGS | SECTION_EXCLUDE, NULL);
>      }
>    else
>      {
> @@ -27271,10 +27284,13 @@ init_sections_and_labels (bool early_lto
>  					    SECTION_DEBUG, NULL);
>  	  debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
>  					      SECTION_DEBUG, NULL);
> -	  debug_loc_section = get_section (DEBUG_LOC_SECTION,
> +	  debug_loc_section = get_section (dwarf_version >= 5
> +					   ? DEBUG_LOCLISTS_SECTION
> +					   : DEBUG_LOC_SECTION,
>  					   SECTION_DEBUG, NULL);
>  	  debug_macinfo_section_name
> -	      = dwarf_strict ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
> +	    = ((dwarf_strict && dwarf_version < 5)
> +	       ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION);
>  	  debug_macinfo_section = get_section (debug_macinfo_section_name,
>  					       SECTION_DEBUG, NULL);
>  	}
> @@ -27311,15 +27327,17 @@ init_sections_and_labels (bool early_lto
>  	  ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
>  				       DEBUG_SKELETON_INFO_SECTION_LABEL,
>  				       generation);
> -	  debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION,
> +	  debug_loc_section = get_section (dwarf_version >= 5
> +					   ? DEBUG_DWO_LOCLISTS_SECTION
> +					   : DEBUG_DWO_LOC_SECTION,
>  					   SECTION_DEBUG | SECTION_EXCLUDE,
>  					   NULL);
>  	  debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
>  					       DEBUG_STR_DWO_SECTION_FLAGS,
>  					       NULL);
>  	  debug_macinfo_section_name
> -	    = (dwarf_strict && dwarf_version < 5)
> -	      ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
> +	    = ((dwarf_strict && dwarf_version < 5)
> +	       ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION);
>  	  debug_macinfo_section = get_section (debug_macinfo_section_name,
>  					       SECTION_DEBUG | SECTION_EXCLUDE,
>  					       NULL);
> @@ -27334,6 +27352,9 @@ init_sections_and_labels (bool early_lto
>  					    SECTION_DEBUG, NULL);
>        debug_str_section = get_section (DEBUG_STR_SECTION,
>  				       DEBUG_STR_SECTION_FLAGS, NULL);
> +      if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
> +	debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
> +					      DEBUG_STR_SECTION_FLAGS, NULL);
>        debug_ranges_section = get_section (dwarf_version >= 5
>  					  ? DEBUG_RNGLISTS_SECTION
>  					  : DEBUG_RANGES_SECTION,
> @@ -27355,7 +27376,7 @@ init_sections_and_labels (bool early_lto
>      ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
>  				 DEBUG_RANGES_SECTION_LABEL, 2 + generation);
>    ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
> -                               DEBUG_ADDR_SECTION_LABEL, generation);
> +			       DEBUG_ADDR_SECTION_LABEL, generation);
>    ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
>  			       (dwarf_strict && dwarf_version < 5)
>  			       ? DEBUG_MACINFO_SECTION_LABEL
> 
> 
> 	Jakub
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-09-20  8:20                 ` Richard Biener
@ 2017-09-20  8:31                   ` Jakub Jelinek
  2017-09-20 18:08                     ` Jeff Law
  0 siblings, 1 reply; 22+ messages in thread
From: Jakub Jelinek @ 2017-09-20  8:31 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jason Merrill, gcc-patches List

On Wed, Sep 20, 2017 at 10:20:03AM +0200, Richard Biener wrote:
> Anyway, I did a quick LTO bootstrap with your patch and it seems
> to work fine.
> 
> Can you add a testcase verifying -gdwarf-5 works ok (properly
> emitting a debug_line_str section?).

I'm afraid I can't.  We don't have a command line switch for
DWARF2_ASM_LINE_DEBUG_INFO, it is something tested solely at configure time
(I've noticed this because my working directory for whatever reason
(many hundreds of reconfigures) doesn't have this defined), and we actually emit
proper DWARF5 .debug_line{,_str} only in that case; when using .file
directives, it is waiting for missing binutils support.

Perhaps we should add -fno-dwarf2-loc-asm to force emitting .debug_line*
by gcc?

As for general DWARF5 testing, I think best coverage is GDB (say guality
testing with -gdwarf-5), I think GDB 8.0 should have the needed support.
I'll try to install it (am only at 7.12.1 right now) and try to do some
testing.

	Jakub

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-09-20  8:31                   ` Jakub Jelinek
@ 2017-09-20 18:08                     ` Jeff Law
  2017-09-21 14:29                       ` Pierre-Marie de Rodat
  0 siblings, 1 reply; 22+ messages in thread
From: Jeff Law @ 2017-09-20 18:08 UTC (permalink / raw)
  To: Jakub Jelinek, Richard Biener; +Cc: Jason Merrill, gcc-patches List

On 09/20/2017 02:31 AM, Jakub Jelinek wrote:
> On Wed, Sep 20, 2017 at 10:20:03AM +0200, Richard Biener wrote:
>> Anyway, I did a quick LTO bootstrap with your patch and it seems
>> to work fine.
>>
>> Can you add a testcase verifying -gdwarf-5 works ok (properly
>> emitting a debug_line_str section?).
> 
> I'm afraid I can't.  We don't have a command line switch for
> DWARF2_ASM_LINE_DEBUG_INFO, it is something tested solely at configure time
> (I've noticed this because my working directory for whatever reason
> (many hundreds of reconfigures) doesn't have this defined), and we actually emit
> proper DWARF5 .debug_line{,_str} only in that case; when using .file
> directives, it is waiting for missing binutils support.
> 
> Perhaps we should add -fno-dwarf2-loc-asm to force emitting .debug_line*
> by gcc?
> 
> As for general DWARF5 testing, I think best coverage is GDB (say guality
> testing with -gdwarf-5), I think GDB 8.0 should have the needed support.
> I'll try to install it (am only at 7.12.1 right now) and try to do some
> testing.
What about Pierre-Marie's work to be able to use python to parse and
check dwarf output?

jeff

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-09-20 18:08                     ` Jeff Law
@ 2017-09-21 14:29                       ` Pierre-Marie de Rodat
  2017-09-21 14:33                         ` Jakub Jelinek
  0 siblings, 1 reply; 22+ messages in thread
From: Pierre-Marie de Rodat @ 2017-09-21 14:29 UTC (permalink / raw)
  To: Jeff Law, Jakub Jelinek, Richard Biener; +Cc: Jason Merrill, gcc-patches List

On 09/20/2017 08:08 PM, Jeff Law wrote:
>> As for general DWARF5 testing, I think best coverage is GDB (say guality
>> testing with -gdwarf-5), I think GDB 8.0 should have the needed support.
>> I'll try to install it (am only at 7.12.1 right now) and try to do some
>> testing.
> > What about Pierre-Marie's work to be able to use python to parse and
> check dwarf output?

I’m not sure from reading the thread what is to be tested, here. Is it 
just the presence of the .debug_line_str section? (in which case for 
once just scanning the .s sounds enough) Or is it rather about checking 
that objdump (or alike) can properly parse the line table?

-- 
Pierre-Marie de Rodat

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH][2/2] early LTO debug, main part
  2017-09-21 14:29                       ` Pierre-Marie de Rodat
@ 2017-09-21 14:33                         ` Jakub Jelinek
  0 siblings, 0 replies; 22+ messages in thread
From: Jakub Jelinek @ 2017-09-21 14:33 UTC (permalink / raw)
  To: Pierre-Marie de Rodat
  Cc: Jeff Law, Richard Biener, Jason Merrill, gcc-patches List

On Thu, Sep 21, 2017 at 04:29:34PM +0200, Pierre-Marie de Rodat wrote:
> On 09/20/2017 08:08 PM, Jeff Law wrote:
> > > As for general DWARF5 testing, I think best coverage is GDB (say guality
> > > testing with -gdwarf-5), I think GDB 8.0 should have the needed support.
> > > I'll try to install it (am only at 7.12.1 right now) and try to do some
> > > testing.
> > > What about Pierre-Marie's work to be able to use python to parse and
> > check dwarf output?
> 
> I’m not sure from reading the thread what is to be tested, here. Is it just
> the presence of the .debug_line_str section? (in which case for once just
> scanning the .s sounds enough) Or is it rather about checking that objdump
> (or alike) can properly parse the line table?

The latter, basically verify that a line info (and also location info etc.)
consumer can grok the DWARF5 stuff.  And for that IMNSHO we really need a
consumer that follows the spec and complains if it is wrong.

	Jakub

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2017-09-21 14:33 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-19 10:44 [PATCH][2/2] early LTO debug, main part Richard Biener
2017-06-07  8:21 ` Richard Biener
2017-06-20 11:16   ` Richard Biener
2017-07-04 11:10     ` Richard Biener
2017-07-28 12:55       ` Richard Biener
2017-08-02  4:30 ` Jason Merrill
2017-08-02 10:35   ` Richard Biener
2017-08-02 19:01     ` Jason Merrill
2017-08-03 10:51       ` Richard Biener
2017-08-03 17:04         ` Jason Merrill
2017-08-04 12:21           ` Richard Biener
2017-08-22 10:49             ` Szabolcs Nagy
2017-08-22 10:57               ` Richard Biener
2017-08-22 13:01                 ` Szabolcs Nagy
2017-08-22 13:29                   ` Richard Biener
2017-09-19 15:24             ` Jakub Jelinek
2017-09-19 21:22               ` Jakub Jelinek
2017-09-20  8:20                 ` Richard Biener
2017-09-20  8:31                   ` Jakub Jelinek
2017-09-20 18:08                     ` Jeff Law
2017-09-21 14:29                       ` Pierre-Marie de Rodat
2017-09-21 14:33                         ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).