diff options
author | Richard Biener <rguenther@suse.de> | 2017-08-21 10:29:00 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2017-08-21 10:29:00 +0000 |
commit | 1ea85365b430b5ade1d0b824e5406c006e6ffdb7 (patch) | |
tree | 3f66db94dd051305b43f1de3bf2077e236deb8a7 /gcc/dwarf2out.c | |
parent | 9f33a5d9acbed950bf446849e9d6968cf22cb9a2 (diff) | |
download | gcc-1ea85365b430b5ade1d0b824e5406c006e6ffdb7.zip gcc-1ea85365b430b5ade1d0b824e5406c006e6ffdb7.tar.gz gcc-1ea85365b430b5ade1d0b824e5406c006e6ffdb7.tar.bz2 |
re PR go/78628 (GO fails to build a translation unit decl)
2017-08-21 Richard Biener <rguenther@suse.de>
include/
* simple-object.h (simple_object_copy_lto_debug_sections): New
function.
libiberty/
* simple-object-common.h (struct simple_object_functions): Add
copy_lto_debug_sections hook.
* simple-object.c: Include fcntl.h.
(handle_lto_debug_sections): New helper function.
(simple_object_copy_lto_debug_sections): New function copying
early LTO debug sections to regular debug sections in a new file.
(simple_object_start_write): Handle NULL segment_name.
* simple-object-coff.c (simple_object_coff_functions): Adjust
for not implemented copy_lto_debug_sections hook.
* simple-object-mach-o.c (simple_object_mach_o_functions): Likewise.
* simple-object-xcoff.c (simple_object_xcoff_functions): Likewise.
* simple-object-elf.c (SHT_NULL, SHT_SYMTAB, SHT_RELA, SHT_REL,
SHT_GROUP): Add various sectopn header types.
(SHF_EXCLUDE): Add flag.
(Elf32_External_Sym, Elf64_External_Sym): Add symbol struct.
(ELF_ST_BIND, ELF_ST_TYPE, ELF_ST_INFO): Add accessors.
(STT_OBJECT, STT_FUNC, STT_TLS, STT_GNU_IFUNC): Add Symbol types.
(STV_DEFAULT): Add symbol visibility.
(SHN_COMMON): Add special section index name.
(struct simple_object_elf_write): New.
(simple_object_elf_start_write): Adjust for new private data.
(simple_object_elf_write_shdr): Pass in values for all fields
we write.
(simple_object_elf_write_to_file): Adjust. Copy from recorded
section headers if requested.
(simple_object_elf_release_write): Release private data.
(simple_object_elf_copy_lto_debug_sections): Copy and rename sections
as denoted by PFN and all their dependences, symbols and relocations
to the empty destination file.
(simple_object_elf_functions): Adjust for copy_lto_debug_sections hook.
gcc/
* 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.
(modified_type_die): Check for decl_ultimate_origin being self
before recursing.
(gen_type_die_with_usage): Likewise.
(gen_typedef_die): Allow decl_ultimate_origin being self.
(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).
(variably_modified_type_p): Prevent endless recursion for Ada
cyclic pointer types.
* 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.
testsuite/
* 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.
From-SVN: r251220
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 1173 |
1 files changed, 865 insertions, 308 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 917ab9f..764fd36 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -164,6 +164,7 @@ static GTY(()) section *debug_aranges_section; 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; @@ -2692,6 +2693,10 @@ static void dwarf2out_begin_function (tree); static void dwarf2out_end_function (unsigned int); static void dwarf2out_register_main_translation_unit (tree unit); static void dwarf2out_set_name (tree, tree); +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. */ @@ -2726,6 +2731,8 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = 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 @@ -2767,6 +2774,8 @@ const struct gcc_debug_hooks dwarf2_lineno_debug_hooks = 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 */ @@ -2895,6 +2904,9 @@ typedef struct GTY((chain_circular ("%h.die_sib"), for_user)) die_struct { /* 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. */ @@ -3698,12 +3710,24 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel) #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 @@ -3716,18 +3740,33 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel) #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 @@ -3756,12 +3795,21 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel) #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 @@ -3786,6 +3834,10 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel) /* 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. */ @@ -4374,6 +4426,24 @@ set_indirect_string (struct indirect_string_node *node) } } +/* 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. */ @@ -5019,6 +5089,21 @@ get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind) 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 @@ -5037,14 +5122,7 @@ is_cxx (const_tree decl) { if (in_lto_p) { - const_tree context = decl; - while (context && TREE_CODE (context) != TRANSLATION_UNIT_DECL) - { - if (TREE_CODE (context) == BLOCK) - context = BLOCK_SUPERCONTEXT (context); - else - context = get_containing_scope (context); - } + const_tree context = get_ultimate_context (decl); if (context && TRANSLATION_UNIT_LANGUAGE (context)) return strncmp (TRANSLATION_UNIT_LANGUAGE (context), "GNU C++", 7) == 0; } @@ -5065,6 +5143,21 @@ is_fortran (void) || lang == DW_LANG_Fortran08); } +static inline bool +is_fortran (const_tree decl) +{ + if (in_lto_p) + { + const_tree context = get_ultimate_context (decl); + if (context && TRANSLATION_UNIT_LANGUAGE (context)) + return (strncmp (TRANSLATION_UNIT_LANGUAGE (context), + "GNU Fortran", 11) == 0 + || strcmp (TRANSLATION_UNIT_LANGUAGE (context), + "GNU F77") == 0); + } + return is_fortran (); +} + /* Return TRUE if the language is Ada. */ static inline bool @@ -5409,6 +5502,184 @@ lookup_decl_die (tree decl) 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 @@ -5896,7 +6167,11 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile) die->die_id.die_type_node->signature); } else if (die->die_id.die_symbol) - fprintf (outfile, "die -> label: %s", 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); @@ -7209,10 +7484,10 @@ static const char *comdat_symbol_id; static unsigned int comdat_symbol_number; /* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its - children, and set comdat_symbol_id accordingly. */ + children, and set die_symbol. */ static void -compute_section_prefix (dw_die_ref unit_die) +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"; @@ -7231,7 +7506,11 @@ compute_section_prefix (dw_die_ref unit_die) unmark_all_dies (unit_die); md5_finish_ctx (&ctx, checksum); - sprintf (name, "%s.", base); + /* 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); @@ -7241,7 +7520,15 @@ compute_section_prefix (dw_die_ref unit_die) p += 2; } - comdat_symbol_id = unit_die->die_id.die_symbol = xstrdup (name); + 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; } @@ -9967,7 +10254,11 @@ output_die (dw_die_ref die) /* If someone in another CU might refer to us, set up a symbol for them to point to. */ - if (! die->comdat_type_p && die->die_id.die_symbol) + 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)", @@ -10160,8 +10451,20 @@ output_die (dw_die_ref die) size = DWARF2_ADDR_SIZE; else size = DWARF_OFFSET_SIZE; - dw2_asm_output_offset (size, sym, debug_info_section, "%s", - name); + /* ??? 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 @@ -10387,7 +10690,7 @@ output_comp_unit (dw_die_ref die, int output_if_empty, calc_die_sizes (die); oldsym = die->die_id.die_symbol; - if (oldsym) + if (oldsym && die->comdat_type_p) { tmp = XALLOCAVEC (char, strlen (oldsym) + 24); @@ -10403,6 +10706,29 @@ output_comp_unit (dw_die_ref die, int output_if_empty, 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); @@ -12511,7 +12837,7 @@ modified_type_die (tree type, int cv_quals, bool reverse, /* Typedef variants that have an abstract origin don't get their own type DIE (see gen_typedef_die), so fall back on the ultimate abstract origin instead. */ - if (origin != NULL) + if (origin != NULL && origin != name) return modified_type_die (TREE_TYPE (origin), cv_quals, reverse, context_die); @@ -14528,6 +14854,9 @@ parameter_ref_descriptor (rtx rtl) 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) @@ -20199,27 +20528,19 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin) { dw_die_ref origin_die = NULL; - if (TREE_CODE (origin) != FUNCTION_DECL - && TREE_CODE (origin) != BLOCK) + if (DECL_P (origin)) { - /* 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); + 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; } - - 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) @@ -20778,7 +21099,10 @@ gen_array_type_die (tree type, dw_die_ref context_die) 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 + /* ??? 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)); @@ -21188,8 +21512,11 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p, parm_die = lookup_decl_die (node); /* If the contexts differ, we may not be talking about the same - thing. */ - if (parm_die && parm_die->die_parent != context_die) + thing. + ??? When in LTO the DIE parent is the "abstract" copy and the + context_die is the specification "copy". But this whole block + should eventually be no longer needed. */ + if (parm_die && parm_die->die_parent != context_die && !in_lto_p) { if (!DECL_ABSTRACT_P (node)) { @@ -21199,18 +21526,7 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p, parm_die = NULL; } else - { - /* FIXME: Reuse DIE even with a differing context. - - This can happen when calling - dwarf2out_abstract_function to build debug info for - the abstract instance of a function for which we have - already generated a DIE in - dwarf2out_early_global_decl. - - Once we remove dwarf2out_abstract_function, we should - have a call to gcc_unreachable here. */ - } + gcc_unreachable (); } if (parm_die && parm_die->die_parent == NULL) @@ -21465,7 +21781,6 @@ gen_type_die_for_member (tree type, tree member, dw_die_ref context_die) /* Forward declare these functions, because they are mutually recursive with their set_block_* pairing functions. */ static void set_decl_origin_self (tree); -static void set_decl_abstract_flags (tree, 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 @@ -21538,151 +21853,48 @@ set_decl_origin_self (tree decl) } } -/* 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. */ +/* Mark the early DIE for DECL as the abstract instance. */ 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); + if (DECL_IGNORED_P (decl)) + return; + old_die = lookup_decl_die (decl); - if (old_die && get_AT (old_die, DW_AT_inline)) + /* 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; - /* 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) + /* 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 { - context = decl_class_context (decl); - if (context) - gen_type_die_for_member - (context, decl, decl_function_context (decl) ? NULL : comp_unit_die ()); + 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); } - /* Pretend we've just finished compiling this function. */ - save_fn = current_function_decl; - current_function_decl = decl; + if (DECL_DECLARED_INLINE_P (decl) + && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl))) + add_AT_flag (old_die, DW_AT_artificial, 1); - 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; + set_decl_origin_self (decl); } /* Helper function of premark_used_types() which gets called through @@ -21894,7 +22106,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) && debug_info_level > DINFO_LEVEL_TERSE) old_die = force_decl_die (decl); - /* An inlined instance, tag a new DIE with DW_AT_abstract_origin. */ + /* A concrete instance, tag a new DIE with DW_AT_abstract_origin. */ if (origin != NULL) { gcc_assert (!declaration || local_scope_p (context_die)); @@ -21973,6 +22185,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) && 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) @@ -22839,6 +23055,24 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) /* 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; } } @@ -23239,12 +23473,6 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die) 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 @@ -24317,7 +24545,8 @@ gen_typedef_die (tree decl, dw_die_ref context_die) /* As we avoid creating DIEs for local typedefs (see decl_ultimate_origin checks in process_scope_var and modified_type_die), this should be called only for original types. */ - gcc_assert (decl_ultimate_origin (decl) == NULL); + gcc_assert (decl_ultimate_origin (decl) == NULL + || decl_ultimate_origin (decl) == decl); TREE_ASM_WRITTEN (decl) = 1; type_die = new_die (DW_TAG_typedef, context_die, decl); @@ -24492,7 +24721,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die, tree name = TYPE_NAME (type); tree origin = decl_ultimate_origin (name); - if (origin != NULL) + if (origin != NULL && origin != name) { gen_decl_die (origin, NULL, NULL, context_die); return; @@ -24850,7 +25079,22 @@ process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die) stmt, context_die); } else - gen_decl_die (decl, origin, NULL, context_die); + { + 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) @@ -25261,14 +25505,19 @@ gen_decl_die (tree decl, tree origin, struct vlr_context *ctx, /* This is only a declaration. */; #endif + /* We should have abstract copies already and should not generate + stray type DIEs in late LTO dumping. */ + if (! early_dwarf) + ; + /* If we're emitting a clone, emit info for the abstract instance. */ - if (origin || DECL_ORIGIN (decl) != decl) + else if (origin || DECL_ORIGIN (decl) != decl) dwarf2out_abstract_function (origin ? DECL_ORIGIN (origin) : DECL_ABSTRACT_ORIGIN (decl)); - /* 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. */ + /* 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) @@ -25276,10 +25525,7 @@ gen_decl_die (tree decl, tree origin, struct vlr_context *ctx, a declaration. We must avoid setting DECL_ABSTRACT_ORIGIN in that case, because that works only if we have a die. */ && DECL_INITIAL (decl) != NULL_TREE) - { - dwarf2out_abstract_function (decl); - set_decl_origin_self (decl); - } + dwarf2out_abstract_function (decl); /* Otherwise we're emitting the primary DIE for this decl. */ else if (debug_info_level > DINFO_LEVEL_TERSE) @@ -25349,20 +25595,36 @@ gen_decl_die (tree decl, tree origin, struct vlr_context *ctx, 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); + /* 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); + } - /* 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); + 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); + /* 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 @@ -25392,10 +25654,23 @@ gen_decl_die (tree decl, tree origin, struct vlr_context *ctx, 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); + /* 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); @@ -25467,6 +25742,16 @@ dwarf2out_early_global_decl (tree decl) 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); @@ -25488,7 +25773,9 @@ dwarf2out_late_global_decl (tree decl) { dw_die_ref die = lookup_decl_die (decl); - /* We have to generate early debug late for LTO. */ + /* 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); @@ -26842,7 +27129,8 @@ output_macinfo_op (macinfo_entry *ref) case DW_MACRO_import: dw2_asm_output_data (1, ref->code, "Import"); ASM_GENERATE_INTERNAL_LABEL (label, - DEBUG_MACRO_SECTION_LABEL, ref->lineno); + DEBUG_MACRO_SECTION_LABEL, + ref->lineno + macinfo_label_base); dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL); break; default: @@ -27016,7 +27304,7 @@ save_macinfo_strings (void) /* Output macinfo section(s). */ static void -output_macinfo (void) +output_macinfo (const char *debug_line_label, bool early_lto_debug) { unsigned i; unsigned long length = vec_safe_length (macinfo_table); @@ -27036,7 +27324,7 @@ output_macinfo (void) /* AIX Assembler inserts the length, so adjust the reference to match the offset expected by debuggers. */ - strcpy (dl_section_ref, debug_line_section_label); + strcpy (dl_section_ref, debug_line_label); if (XCOFF_DEBUGGING_INFO) strcat (dl_section_ref, DWARF_INITIAL_LENGTH_SIZE_STR); @@ -27049,9 +27337,7 @@ output_macinfo (void) dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present"); else dw2_asm_output_data (1, 2, "Flags: 32-bit, lineptr present"); - dw2_asm_output_offset (DWARF_OFFSET_SIZE, - (!dwarf_split_debug_info ? dl_section_ref - : debug_skeleton_line_section_label), + dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_line_label, debug_line_section, NULL); } @@ -27105,6 +27391,10 @@ output_macinfo (void) 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; @@ -27124,11 +27414,13 @@ output_macinfo (void) dw2_asm_output_data (1, 0, "End compilation unit"); targetm.asm_out.named_section (debug_macinfo_section_name, SECTION_DEBUG - | SECTION_LINKONCE, + | SECTION_LINKONCE + | (early_lto_debug + ? SECTION_EXCLUDE : 0), comdat_key); ASM_GENERATE_INTERNAL_LABEL (label, DEBUG_MACRO_SECTION_LABEL, - ref->lineno); + ref->lineno + macinfo_label_base); ASM_OUTPUT_LABEL (asm_out_file, label); ref->code = 0; ref->info = NULL; @@ -27149,109 +27441,192 @@ output_macinfo (void) default: gcc_unreachable (); } + + macinfo_label_base += macinfo_label_base_adj; } -/* Initialize the various sections and labels for dwarf output. */ +/* Initialize the various sections and labels for dwarf output and prefix + them with PREFIX if non-NULL. */ static void -init_sections_and_labels (void) +init_sections_and_labels (bool early_lto_debug) { - if (!dwarf_split_debug_info) + /* As we may get called multiple times have a generation count for labels. */ + static unsigned generation = 0; + + if (early_lto_debug) { - 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); + 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 { - 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, + 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_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, + 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_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); + 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, 0); + DEBUG_ABBREV_SECTION_LABEL, generation); ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label, - DEBUG_INFO_SECTION_LABEL, 0); + DEBUG_INFO_SECTION_LABEL, generation); + info_section_emitted = false; ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label, - DEBUG_LINE_SECTION_LABEL, 0); + DEBUG_LINE_SECTION_LABEL, generation); ASM_GENERATE_INTERNAL_LABEL (ranges_section_label, - DEBUG_RANGES_SECTION_LABEL, 0); + DEBUG_RANGES_SECTION_LABEL, generation); if (dwarf_version >= 5 && dwarf_split_debug_info) ASM_GENERATE_INTERNAL_LABEL (ranges_base_label, - DEBUG_RANGES_SECTION_LABEL, 1); + DEBUG_RANGES_SECTION_LABEL, 2 + generation); ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label, - DEBUG_ADDR_SECTION_LABEL, 0); + 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, 0); - ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0); + : 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. */ @@ -29598,6 +29973,22 @@ flush_limbo_die_list (void) } } +/* 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. */ @@ -29625,6 +30016,46 @@ dwarf2out_finish (const char *) 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; @@ -29635,7 +30066,7 @@ dwarf2out_finish (const char *) move_marked_base_types (); /* Initialize sections and labels used for actual assembler output. */ - init_sections_and_labels (); + init_sections_and_labels (false); /* Traverse the DIE's and add sibling attributes to those DIE's that have children. */ @@ -29736,9 +30167,7 @@ dwarf2out_finish (const char *) 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, + add_AT_macptr (comp_unit_die (), DEBUG_MACRO_ATTRIBUTE, macinfo_section_label); if (dwarf_split_debug_info) @@ -29943,7 +30372,8 @@ dwarf2out_finish (const char *) { switch_to_section (debug_macinfo_section); ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label); - output_macinfo (); + 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"); } @@ -30164,6 +30594,20 @@ note_variable_value_in_expr (dw_die_ref die, dw_loc_descr_ref loc) { 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; @@ -30374,6 +30818,119 @@ dwarf2out_early_finish (const char *filename) /* 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 |