This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH][2/2] early LTO debug, main part


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 ****
      }
  }
  
! /* 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 ----
      }
  }
  
! /* 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 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]