From 989f386cf019cc7892918f98715c3bfcaaaab071 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Thu, 4 Sep 2014 16:38:21 +0000 Subject: [PATCH] + * c/c-decl.c (write_global_declarations_1): Call global_decl() + with early=true. + * c/c-decl.c (write_global_declarations_1): Call global_decl() + with early=true. + (write_global_declarations_2): Call global_decl() with + early=false. + * dbxout.c (dbxout_global_decl): New argument. + * debug.c (do_nothing_debug_hooks): Use debug_nothing_tree_bool + for global_decl hook. + (debug_nothing_tree_bool): New. + (struct gcc_debug_hooks): New argument to global_decl. + * dwarf2out.c (output_die): Add misc debugging information. + (gen_variable_die): Do not reparent children. + (dwarf2out_global_decl): Add new documentation. Add EARLY + argument. + (dwarf2out_decl): Make sure we don't generate new DIEs if we + already have a DIE. + * cp/name-lookup.c (do_namespace_alias): New argument to + global_decl debug hook. + * fortran/trans-decl.c (gfc_emit_parameter_debug_info): Same. + * godump.c (go_global_decl): Same. + * lto/lto-lang.c (lto_write_globals): Same. + * sdbout.c (sdbout_global_decl): Same. + * toplev.c (emit_debug_global_declarations): Same. + * vmsdbgout.c (vmsdbgout_global_decl): Same. + * tree.c (free_lang_data_in_decl): Do not call + dwarf2out_early_decl from here. From-SVN: r214911 --- gcc/ChangeLog.debug-early | 28 ++++++++++++++++++++ gcc/c/c-decl.c | 7 +++-- gcc/cp/name-lookup.c | 2 +- gcc/dbxout.c | 4 +-- gcc/debug.c | 8 +++++- gcc/debug.h | 8 ++++-- gcc/dwarf2out.c | 56 +++++++++++++++++++++++++++++++-------- gcc/fortran/trans-decl.c | 2 +- gcc/godump.c | 4 +-- gcc/lto/lto-lang.c | 2 +- gcc/sdbout.c | 5 ++-- gcc/toplev.c | 2 +- gcc/tree.c | 4 --- gcc/vmsdbgout.c | 6 ++--- 14 files changed, 104 insertions(+), 34 deletions(-) diff --git a/gcc/ChangeLog.debug-early b/gcc/ChangeLog.debug-early index df571a47fde..980b65513fa 100644 --- a/gcc/ChangeLog.debug-early +++ b/gcc/ChangeLog.debug-early @@ -1,3 +1,31 @@ +2014-09-03 Aldy Hernandez + + * c/c-decl.c (write_global_declarations_1): Call global_decl() + with early=true. + (write_global_declarations_2): Call global_decl() with + early=false. + * dbxout.c (dbxout_global_decl): New argument. + * debug.c (do_nothing_debug_hooks): Use debug_nothing_tree_bool + for global_decl hook. + (debug_nothing_tree_bool): New. + (struct gcc_debug_hooks): New argument to global_decl. + * dwarf2out.c (output_die): Add misc debugging information. + (gen_variable_die): Do not reparent children. + (dwarf2out_global_decl): Add new documentation. Add EARLY + argument. + (dwarf2out_decl): Make sure we don't generate new DIEs if we + already have a DIE. + * cp/name-lookup.c (do_namespace_alias): New argument to + global_decl debug hook. + * fortran/trans-decl.c (gfc_emit_parameter_debug_info): Same. + * godump.c (go_global_decl): Same. + * lto/lto-lang.c (lto_write_globals): Same. + * sdbout.c (sdbout_global_decl): Same. + * toplev.c (emit_debug_global_declarations): Same. + * vmsdbgout.c (vmsdbgout_global_decl): Same. + * tree.c (free_lang_data_in_decl): Do not call + dwarf2out_early_decl from here. + 2014-08-26 Aldy Hernandez * dwarf2out.c (struct die_struct): Add dumped_early field. diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index b4995a67733..1e09404dd55 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -10308,7 +10308,10 @@ c_write_global_declarations_1 (tree globals) while (reconsider); for (decl = globals; decl; decl = DECL_CHAIN (decl)) - check_global_declaration_1 (decl); + { + check_global_declaration_1 (decl); + debug_hooks->global_decl (decl, /*early=*/true); + } } /* A subroutine of c_write_global_declarations Emit debug information for each @@ -10320,7 +10323,7 @@ c_write_global_declarations_2 (tree globals) tree decl; for (decl = globals; decl ; decl = DECL_CHAIN (decl)) - debug_hooks->global_decl (decl); + debug_hooks->global_decl (decl, /*early=*/false); } /* Callback to collect a source_ref from a DECL. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index ebcbb5c5580..45b3b999325 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3859,7 +3859,7 @@ do_namespace_alias (tree alias, tree name_space) /* Emit debug info for namespace alias. */ if (!building_stmt_list_p ()) - (*debug_hooks->global_decl) (alias); + (*debug_hooks->global_decl) (alias, /*early=*/false); } /* Like pushdecl, only it places X in the current namespace, diff --git a/gcc/dbxout.c b/gcc/dbxout.c index d856bddc115..208cec91b8e 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -325,7 +325,7 @@ static int dbxout_symbol_location (tree, tree, const char *, rtx); static void dbxout_symbol_name (tree, const char *, int); static void dbxout_common_name (tree, const char *, stab_code_type); static const char *dbxout_common_check (tree, int *); -static void dbxout_global_decl (tree); +static void dbxout_global_decl (tree, bool); static void dbxout_type_decl (tree, int); static void dbxout_handle_pch (unsigned); static void debug_free_queue (void); @@ -1320,7 +1320,7 @@ dbxout_function_decl (tree decl) /* Debug information for a global DECL. Called from toplev.c after compilation proper has finished. */ static void -dbxout_global_decl (tree decl) +dbxout_global_decl (tree decl, bool early ATTRIBUTE_UNUSED) { if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) { diff --git a/gcc/debug.c b/gcc/debug.c index dba068cc24a..b5818de3a3b 100644 --- a/gcc/debug.c +++ b/gcc/debug.c @@ -43,7 +43,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks = debug_nothing_tree, /* begin_function */ debug_nothing_int, /* end_function */ debug_nothing_tree, /* function_decl */ - debug_nothing_tree, /* global_decl */ + debug_nothing_tree_bool, /* global_decl */ debug_nothing_tree_int, /* type_decl */ debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */ debug_nothing_tree, /* deferred_inline_function */ @@ -70,6 +70,12 @@ debug_nothing_tree (tree decl ATTRIBUTE_UNUSED) { } +void +debug_nothing_tree_bool (tree decl ATTRIBUTE_UNUSED, + bool early ATTRIBUTE_UNUSED) +{ +} + void debug_nothing_tree_tree (tree t1 ATTRIBUTE_UNUSED, tree t2 ATTRIBUTE_UNUSED) diff --git a/gcc/debug.h b/gcc/debug.h index 28bc2104b1b..94405152443 100644 --- a/gcc/debug.h +++ b/gcc/debug.h @@ -93,8 +93,11 @@ struct gcc_debug_hooks void (* function_decl) (tree decl); /* Debug information for a global DECL. Called from toplev.c after - compilation proper has finished. */ - void (* global_decl) (tree decl); + compilation proper has finished. EARLY is true if global_decl() + is being called early on in the compilation process (i.e., before + cgraph information is available and before code is + generated). */ + void (* global_decl) (tree decl, bool early); /* Debug information for a type DECL. Called from toplev.c after compilation proper, also from various language front ends to @@ -156,6 +159,7 @@ extern void debug_nothing_int_charstar_int_bool (unsigned int, const char *, extern void debug_nothing_int (unsigned int); extern void debug_nothing_int_int (unsigned int, unsigned int); extern void debug_nothing_tree (tree); +extern void debug_nothing_tree_bool (tree, bool); extern void debug_nothing_tree_tree (tree, tree); extern void debug_nothing_tree_int (tree, int); extern void debug_nothing_tree_tree_tree_bool (tree, tree, tree, bool); diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index c4952e7f132..918f26177ee 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2430,7 +2430,7 @@ static void dwarf2out_function_decl (tree); static void dwarf2out_begin_block (unsigned, unsigned); static void dwarf2out_end_block (unsigned, unsigned); static bool dwarf2out_ignore_block (const_tree); -static void dwarf2out_global_decl (tree); +static void dwarf2out_global_decl (tree, bool); static void dwarf2out_type_decl (tree, int); static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool); static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree, @@ -8711,10 +8711,11 @@ output_die (dw_die_ref die) 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 (parent DIE=%#lx))", + dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s (parent DIE=%#lx) early=%d)", (unsigned long)die->die_offset, dwarf_tag_name (die->die_tag), - die->die_parent ? die->die_parent->die_offset : 0); + die->die_parent ? die->die_parent->die_offset : 0, + die->dumped_early); FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a) { @@ -19009,13 +19010,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) if (old_die && !declaration && !local_scope_p (context_die)) return; - /* When DIEs are created early, the context is the compilation unit. - Adjust the context when we know what it is the second time - around. */ + /* If a DIE was dumped early, it still needs location info. Skip to + the part where we fill the location bits. */ if (old_die && old_die->dumped_early) { - if (old_die->die_parent != context_die) - reparent_child (old_die, context_die); + gcc_assert (old_die->die_parent == context_die); var_die = old_die; old_die = NULL; goto gen_variable_die_location; @@ -20818,12 +20817,29 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die) return NULL; } -/* Output debug information for global decl DECL. Called from toplev.c after - compilation proper has finished. */ +/* Output debug information for global decl DECL. Called from + toplev.c after compilation proper has finished. + + dwarf2out_decl() will be called twice on each global symbol: once + immediately after parsing (EARLY=true), and once after the full + compilation has finished (EARLY=false). There are checks in + dwarf2out_decl() to make sure that if we have a DECL DIE upon + entry, that the previously created DIE is reused. No new DECL DIEs + should be created when EARLY=false. + + The second time dwarf2out_decl() is called (or for that matter, the + second time any DECL DIE is seen throughout dwarf2out), only + information not previously available (e.g. location) is tacked onto + the early dumped DIE. That's the plan anyhow ;-). */ static void -dwarf2out_global_decl (tree decl) +dwarf2out_global_decl (tree decl, bool early) { + if (early) + { + dwarf2out_early_decl (decl); + return; + } /* Output DWARF2 information for file-scope tentative data object declarations, file-scope (extern) function declarations (which had no corresponding body) and file-scope tagged type declarations @@ -21019,6 +21035,19 @@ dwarf2out_decl (tree decl) { dw_die_ref context_die = comp_unit_die (); +#ifdef ENABLE_CHECKING + /* Save some info so we can later determine if we erroneously + created a DIE for something we had already created a DIE for. + We should always be reusing DIEs created early. */ + dw_die_ref early_die = NULL; + if (decl_die_table) + { + early_die = lookup_decl_die (decl); + if (early_die && !early_die->dumped_early) + early_die = NULL; + } +#endif + switch (TREE_CODE (decl)) { case ERROR_MARK: @@ -21144,6 +21173,11 @@ dwarf2out_decl (tree decl) dw_die_ref die = lookup_decl_die (decl); if (die) check_die (die, 0); +#ifdef ENABLE_CHECKING + /* If we early created a DIE, make sure it didn't get re-created by + mistake. */ + gcc_assert (!early_die || early_die == die); +#endif return die; } diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 6afa6f3b696..38e6f990e68 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -4693,7 +4693,7 @@ gfc_emit_parameter_debug_info (gfc_symbol *sym) TREE_TYPE (decl), sym->attr.dimension, false, false); - debug_hooks->global_decl (decl); + debug_hooks->global_decl (decl, /*early=*/false); } diff --git a/gcc/godump.c b/gcc/godump.c index 7566f4d3eff..01f8410ccd7 100644 --- a/gcc/godump.c +++ b/gcc/godump.c @@ -496,9 +496,9 @@ go_function_decl (tree decl) /* A global variable decl. */ static void -go_global_decl (tree decl) +go_global_decl (tree decl, bool early) { - real_debug_hooks->global_decl (decl); + real_debug_hooks->global_decl (decl, early); go_decl (decl); } diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index 9e8524acac2..1f39949c811 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -1093,7 +1093,7 @@ lto_write_globals (void) varpool_node *vnode; FOR_EACH_DEFINED_VARIABLE (vnode) if (!decl_function_context (vnode->decl)) - debug_hooks->global_decl (vnode->decl); + debug_hooks->global_decl (vnode->decl, /*early=*/false); } static tree diff --git a/gcc/sdbout.c b/gcc/sdbout.c index 7b6f4573e05..d81b184c415 100644 --- a/gcc/sdbout.c +++ b/gcc/sdbout.c @@ -119,7 +119,7 @@ static void sdbout_begin_block (unsigned int, unsigned int); static void sdbout_end_block (unsigned int, unsigned int); static void sdbout_source_line (unsigned int, const char *, int, bool); static void sdbout_end_epilogue (unsigned int, const char *); -static void sdbout_global_decl (tree); +static void sdbout_global_decl (tree, bool); static void sdbout_begin_prologue (unsigned int, const char *); static void sdbout_end_prologue (unsigned int, const char *); static void sdbout_begin_function (tree); @@ -142,7 +142,6 @@ static void sdbout_field_types (tree); static void sdbout_one_type (tree); static void sdbout_parms (tree); static void sdbout_reg_parms (tree); -static void sdbout_global_decl (tree); /* Random macros describing parts of SDB data. */ @@ -1422,7 +1421,7 @@ sdbout_reg_parms (tree parms) after compilation proper has finished. */ static void -sdbout_global_decl (tree decl) +sdbout_global_decl (tree decl, bool early ATTRIBUTE_UNUSED) { if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl) diff --git a/gcc/toplev.c b/gcc/toplev.c index 492a7ef58e5..ceefa1bf6e9 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -532,7 +532,7 @@ emit_debug_global_declarations (tree *vec, int len) timevar_push (TV_SYMOUT); for (i = 0; i < len; i++) - debug_hooks->global_decl (vec[i]); + debug_hooks->global_decl (vec[i], /*early=*/false); timevar_pop (TV_SYMOUT); } diff --git a/gcc/tree.c b/gcc/tree.c index afc8e3d9559..8e9876ef4ed 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -5032,10 +5032,6 @@ free_lang_data_in_decl (tree decl) { gcc_assert (DECL_P (decl)); - /* Early dumping of DECLs before we lose language data. */ - if (debug_info_level > DINFO_LEVEL_NONE) - dwarf2out_early_decl (decl); - /* Give the FE a chance to remove its own data first. */ lang_hooks.free_lang_data (decl); diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c index 463a4182622..2ad9e9b5c14 100644 --- a/gcc/vmsdbgout.c +++ b/gcc/vmsdbgout.c @@ -163,7 +163,7 @@ static void vmsdbgout_begin_epilogue (unsigned int, const char *); static void vmsdbgout_end_epilogue (unsigned int, const char *); static void vmsdbgout_begin_function (tree); static void vmsdbgout_decl (tree); -static void vmsdbgout_global_decl (tree); +static void vmsdbgout_global_decl (tree, bool); static void vmsdbgout_type_decl (tree, int); static void vmsdbgout_abstract_function (tree); @@ -1510,10 +1510,10 @@ vmsdbgout_decl (tree decl) /* Not implemented in VMS Debug. */ static void -vmsdbgout_global_decl (tree decl) +vmsdbgout_global_decl (tree decl, bool early) { if (write_symbols == VMS_AND_DWARF2_DEBUG) - (*dwarf2_debug_hooks.global_decl) (decl); + (*dwarf2_debug_hooks.global_decl) (decl, early); } /* Not implemented in VMS Debug. */