From patchwork Fri Sep 12 00:51:22 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 388459 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 5A83214007B for ; Fri, 12 Sep 2014 10:51:44 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=SFfzR/AM0gLptdn4+ lmWg4GLIRuaBVtMyeFpF/UdTfDbiJNqTVHDxiXepXPtJm6nqnbLcdHA2R5zBxJHq 17qN228vJ7FCPMxDDJJcQdTmoqiXBIbqPGXzfzwNwEGImlXB4d1FCnQvEhFBU4s8 4LJ1EoW9OTXJ3tHZiBHH4F/a/g= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; s=default; bh=HC7jrH1UhRrtP7N4i6WgLD0 AZ8k=; b=yK0r+agcWFw0sKA0yD/3MXbdfX+jD2p7jH8NM5jhf8Jnc9nUnXH1Uoc GLyHSX5pQlFYDEw1dGpW24hf0NtmRI/oM1xWzp8PMru+0YszW4BkKPh2kAtKahsV RJogIsKdnF/rTUh5WJCP9ntLPFeC0ecex9+uKTYnRwkcmodiIzwg= Received: (qmail 4727 invoked by alias); 12 Sep 2014 00:51:34 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 4715 invoked by uid 89); 12 Sep 2014 00:51:33 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 12 Sep 2014 00:51:27 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s8C0pQjQ017818 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 11 Sep 2014 20:51:26 -0400 Received: from reynosa.quesejoda.com (vpn-51-38.rdu2.redhat.com [10.10.51.38]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s8C0pNhu010824; Thu, 11 Sep 2014 20:51:24 -0400 Message-ID: <5412438A.6030305@redhat.com> Date: Thu, 11 Sep 2014 17:51:22 -0700 From: Aldy Hernandez User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.7.0 MIME-Version: 1.0 To: Richard Biener CC: Jason Merrill , gcc-patches Subject: Re: [debug-early] reuse variable DIEs and fix their context References: <53FD45A7.4000804@redhat.com> <53FF6840.9030505@redhat.com> <53FF6E61.6030507@redhat.com> <540755E5.7060602@redhat.com> <5409220E.6070100@redhat.com> <540E4337.70006@redhat.com> In-Reply-To: On 09/09/14 02:16, Richard Biener wrote: > On Tue, Sep 9, 2014 at 2:00 AM, Aldy Hernandez wrote: >> On 09/05/14 02:00, Richard Biener wrote: >> What I have in mind is: >> >> 1. Move the FE specific things that come before the call to >> finalize_compilation_unit currently in each LANG_HOOKS_WRITE_GLOBALS, into >> the FE proper (lang_hooks.parse_file). This may or may not mean calling >> {wrapup,check}_global_declarations directly from the FEs since some FE's >> call these in a sufficiently different order to merit everyone doing their >> own thing (not sure though). Done. >> >> 2. Generate debug information by gathering the list of globals with >> lang_hooks.decls.getdecls (??) and then doing >> debug_hooks->early_global_decl() as discussed. > > Or move that also to lang_hooks.parse_file? ISTR lang_hooks.decls.getdecls > is sort of an "alternative" hook to write_global_declarations that is only > used by the generic implementation of write_global_declarations. Done. > > So if we move everything else but calling debug_hooks->early_global_decl () > out of the write_global_declarations langhook then we could indeed > remove that hook and implement getdecls everywhere. > > I suppose one of the hooks should go in the end. > >> 2. Call finalize_compilation_unit() directly from compile_file(). Done. > > Great! > >> 3. Call some (new) hook for C++ stuff after finalize_compilation_unit (???). > > Or fix the C++ stuff to work properly in a symtab way? I suppose as > an intermediate step adding a new langhook for this on the branch is ok > but I'd rather not get that merged into trunk. Done. For now I've called it LANG_HOOK_POST_COMPILATION_PARSING_CLEANUPS, and it is only applicable to C++, unless some other FE acts up in the process and needs similar massaging. > Maybe Jason can help cleaning this up. Jason's not much of a beer drinker AFAICT, so I'm trying to come up with a suitable bribe. > >> 4. FOR_EACH_DEFINED_SYMBOL (node) >> debug_hooks->late_global_decl (node->decl) >> >> as suggested. Done. [Well... as DONE as a prototype can be :). This is a work in progress, but I'd like y'all to peek at it, to make sure I'm not making obvious wrong turns that will have me rewriting code months from now, and hating you in the process. And by you, I mean Jason *and* you. I don't want anyone to feel left out by my frustration and anger.] I drafted what I want Ada, Java, Fortran, and Go to look like (as well as the obvious C/C++ languages). For C, guality.exp exhibits less failures than mainline. I'm currently debugging inline virtual C++ destructors. It seems the inliner can also call generate debugging info (debug_hooks->outlining_inline_function). The rest of the languages are tested as far as building jc1/f951/go1 with no warnings :-))). There are various cleanups and comments along the way. Let me know if you're "mostly" OK with this, so I can push this to the branch and continue iterating with you incrementally. It seems there will be no shortage of weird bugs in dwarf generation due to the fact that we stream early. I'm hoping to start concentrating on those... As usual, thanks. Aldy diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index 240ca44..44af75f 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -105,6 +105,10 @@ gnat_parse_file (void) /* Call the front end. */ _ada_gnat1drv (); + + /* Output global declarations and generate debug information for + them. */ + gnat_write_global_declarations (); } /* Return language mask for option processing. */ diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 266a942..fb187a6 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -5178,27 +5178,9 @@ gnat_write_global_declarations (void) } } - /* Output debug information for all global type declarations first. This - ensures that global types whose compilation hasn't been finalized yet, - for example pointers to Taft amendment types, have their compilation - finalized in the right context. */ FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter) if (TREE_CODE (iter) == TYPE_DECL && !DECL_IGNORED_P (iter)) - debug_hooks->global_decl (iter); - - /* Proceed to optimize and emit assembly. */ - symtab->finalize_compilation_unit (); - - /* After cgraph has had a chance to emit everything that's going to - be emitted, output debug information for the rest of globals. */ - if (!seen_error ()) - { - timevar_push (TV_SYMOUT); - FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter) - if (TREE_CODE (iter) != TYPE_DECL && !DECL_IGNORED_P (iter)) - debug_hooks->global_decl (iter); - timevar_pop (TV_SYMOUT); - } + debug_hooks->early_global_decl (iter); } /* ************************************************************************ diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 993a97b..1f5d557 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -847,6 +847,8 @@ extern HOST_WIDE_INT c_common_to_target_charset (HOST_WIDE_INT); /* This is the basic parsing function. */ extern void c_parse_file (void); +extern void c_parse_final_cleanups (void); + extern void warn_for_omitted_condop (location_t, tree); /* These macros provide convenient access to the various _STMT nodes. */ diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 7486691..fac25cc 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -1070,6 +1070,9 @@ c_common_parse_file (void) if (!this_input_filename) break; } + + if (!flag_syntax_only) + c_parse_final_cleanups (); } /* Returns the appropriate dump file for PHASE to dump with FLAGS. */ diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 1e09404..a0a047f 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -10270,9 +10270,8 @@ finish_declspecs (struct c_declspecs *specs) return specs; } -/* A subroutine of c_write_global_declarations. Perform final processing - on one file scope's declarations (or the external scope's declarations), - GLOBALS. */ +/* Perform final processing on one file scope's declarations (or the + external scope's declarations), GLOBALS. */ static void c_write_global_declarations_1 (tree globals) @@ -10310,22 +10309,10 @@ c_write_global_declarations_1 (tree globals) for (decl = globals; decl; decl = DECL_CHAIN (decl)) { check_global_declaration_1 (decl); - debug_hooks->global_decl (decl, /*early=*/true); + debug_hooks->early_global_decl (decl); } } -/* A subroutine of c_write_global_declarations Emit debug information for each - of the declarations in GLOBALS. */ - -static void -c_write_global_declarations_2 (tree globals) -{ - tree decl; - - for (decl = globals; decl ; decl = DECL_CHAIN (decl)) - debug_hooks->global_decl (decl, /*early=*/false); -} - /* Callback to collect a source_ref from a DECL. */ static void @@ -10373,8 +10360,11 @@ for_each_global_decl (void (*callback) (tree decl)) callback (decl); } +/* Perform any final parser cleanups and generate initial debugging + information. */ + void -c_write_global_declarations (void) +c_parse_final_cleanups (void) { tree t; unsigned i; @@ -10383,8 +10373,6 @@ c_write_global_declarations (void) if (pch_file) return; - timevar_start (TV_PHASE_DEFERRED); - /* Do the Objective-C stuff. This is where all the Objective-C module stuff gets generated (symtab, class/protocol/selector lists etc). */ @@ -10426,29 +10414,7 @@ c_write_global_declarations (void) c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t))); c_write_global_declarations_1 (BLOCK_VARS (ext_block)); - timevar_stop (TV_PHASE_DEFERRED); - timevar_start (TV_PHASE_OPT_GEN); - - /* We're done parsing; proceed to optimize and emit assembly. - FIXME: shouldn't be the front end's responsibility to call this. */ - symtab->finalize_compilation_unit (); - - timevar_stop (TV_PHASE_OPT_GEN); - timevar_start (TV_PHASE_DBGINFO); - - /* After cgraph has had a chance to emit everything that's going to - be emitted, output debug information for globals. */ - if (!seen_error ()) - { - timevar_push (TV_SYMOUT); - FOR_EACH_VEC_ELT (*all_translation_units, i, t) - c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t))); - c_write_global_declarations_2 (BLOCK_VARS (ext_block)); - timevar_pop (TV_SYMOUT); - } - ext_block = NULL; - timevar_stop (TV_PHASE_DBGINFO); } /* Register reserved keyword WORD as qualifier for address space AS. */ diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h index 92cf60f..8ab4e67 100644 --- a/gcc/c/c-objc-common.h +++ b/gcc/c/c-objc-common.h @@ -92,8 +92,6 @@ along with GCC; see the file COPYING3. If not see #undef LANG_HOOKS_GETDECLS #define LANG_HOOKS_GETDECLS lhd_return_null_tree_v -#undef LANG_HOOKS_WRITE_GLOBALS -#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations /* Hooks for tree gimplification. */ #undef LANG_HOOKS_GIMPLIFY_EXPR diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 6004d50..7586813 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -669,7 +669,6 @@ extern enum machine_mode c_default_pointer_mode; /* In c-decl.c */ extern void c_finish_incomplete_decl (tree); -extern void c_write_global_declarations (void); extern tree c_omp_reduction_id (enum tree_code, tree); extern tree c_omp_reduction_decl (tree); extern tree c_omp_reduction_lookup (tree, tree); diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 246800e..c78e808 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -83,8 +83,8 @@ extern void cp_common_init_ts (void); #define LANG_HOOKS_PRINT_ERROR_FUNCTION cxx_print_error_function #undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL cxx_warn_unused_global_decl -#undef LANG_HOOKS_WRITE_GLOBALS -#define LANG_HOOKS_WRITE_GLOBALS cp_write_global_declarations +#undef LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS +#define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS cxx_post_compilation_parsing_cleanups #undef LANG_HOOKS_BUILTIN_FUNCTION #define LANG_HOOKS_BUILTIN_FUNCTION cxx_builtin_function #undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 19f5232..053058a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5370,7 +5370,7 @@ extern tree cp_reconstruct_complex_type (tree, tree); extern bool attributes_naming_typedef_ok (tree); extern void cplus_decl_attributes (tree *, tree, int); extern void finish_anon_union (tree); -extern void cp_write_global_declarations (void); +extern void cxx_post_compilation_parsing_cleanups (void); extern tree coerce_new_type (tree); extern tree coerce_delete_type (tree); extern void comdat_linkage (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d8fb35e..8d6913c 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -866,30 +866,19 @@ walk_namespaces (walk_namespaces_fn f, void* data) return walk_namespaces_r (global_namespace, f, data); } -/* Call wrapup_globals_declarations for the globals in NAMESPACE. If - DATA is non-NULL, this is the last time we will call - wrapup_global_declarations for this NAMESPACE. */ +/* Call wrapup_globals_declarations for the globals in NAMESPACE. */ int -wrapup_globals_for_namespace (tree name_space, void* data) +wrapup_globals_for_namespace (tree name_space, void* data ATTRIBUTE_UNUSED) { cp_binding_level *level = NAMESPACE_LEVEL (name_space); vec *statics = level->static_decls; tree *vec = statics->address (); int len = statics->length (); - int last_time = (data != 0); - - if (last_time) - { - check_global_declarations (vec, len); - emit_debug_global_declarations (vec, len); - return 0; - } /* Write out any globals that need to be output. */ return wrapup_global_declarations (vec, len); } - /* In C++, you don't have to write `struct S' to refer to `S'; you can just use `S'. We accomplish this by creating a TYPE_DECL as diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 4be4847..28bf6e4 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4286,24 +4286,43 @@ dump_tu (void) } } +/* Issue warnings for globals in NAME_SPACE (unused statics, etc) and + generate debug information for said globals. */ + +static int +emit_debug_for_namespace (tree name_space, void* data ATTRIBUTE_UNUSED) +{ + cp_binding_level *level = NAMESPACE_LEVEL (name_space); + vec *statics = level->static_decls; + tree *vec = statics->address (); + int len = statics->length (); + + check_global_declarations (vec, len); + emit_debug_global_declarations (vec, len, EMIT_DEBUG_EARLY); + return 0; +} + +/* Candidates for Java hidden aliases. */ +static hash_set *java_hidden_aliases; + +static location_t locus_at_end_of_parsing; + /* This routine is called at the end of compilation. Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction first, since that way we only need to reverse the decls once. */ void -cp_write_global_declarations (void) +c_parse_final_cleanups (void) { tree vars; bool reconsider; size_t i; - location_t locus; unsigned ssdf_count = 0; int retries = 0; tree decl; - hash_set *candidates; - locus = input_location; + locus_at_end_of_parsing = input_location; at_eof = 1; /* Bad parse errors. Just forget about it. */ @@ -4335,8 +4354,6 @@ cp_write_global_declarations (void) /* FIXME - huh? was input_line -= 1;*/ - timevar_start (TV_PHASE_DEFERRED); - /* We now have to write out all the stuff we put off writing out. These include: @@ -4432,7 +4449,7 @@ cp_write_global_declarations (void) /* Set the line and file, so that it is obviously not from the source file. */ - input_location = locus; + input_location = locus_at_end_of_parsing; ssdf_body = start_static_storage_duration_function (ssdf_count); /* Make sure the back end knows about all the variables. */ @@ -4458,7 +4475,7 @@ cp_write_global_declarations (void) /* Finish up the static storage duration function for this round. */ - input_location = locus; + input_location = locus_at_end_of_parsing; finish_static_storage_duration_function (ssdf_body); /* All those initializations and finalizations might cause @@ -4466,7 +4483,7 @@ cp_write_global_declarations (void) instantiations, etc. */ reconsider = true; ssdf_count++; - /* ??? was: locus.line++; */ + /* ??? was: locus_at_end_of_parsing.line++; */ } /* Now do the same for thread_local variables. */ @@ -4632,12 +4649,13 @@ cp_write_global_declarations (void) if (priority_info_map) splay_tree_foreach (priority_info_map, generate_ctor_and_dtor_functions_for_priority, - /*data=*/&locus); + /*data=*/&locus_at_end_of_parsing); else if (c_dialect_objc () && objc_static_init_needed_p ()) /* If this is obj-c++ and we need a static init, call generate_ctor_or_dtor_function. */ generate_ctor_or_dtor_function (/*constructor_p=*/true, - DEFAULT_INIT_PRIORITY, &locus); + DEFAULT_INIT_PRIORITY, + &locus_at_end_of_parsing); /* We're done with the splay-tree now. */ if (priority_info_map) @@ -4651,10 +4669,7 @@ cp_write_global_declarations (void) pop_lang_context (); /* Collect candidates for Java hidden aliases. */ - candidates = collect_candidates_for_java_method_aliases (); - - timevar_stop (TV_PHASE_DEFERRED); - timevar_start (TV_PHASE_OPT_GEN); + java_hidden_aliases = collect_candidates_for_java_method_aliases (); if (flag_vtable_verify) { @@ -4663,7 +4678,28 @@ cp_write_global_declarations (void) vtv_build_vtable_verify_fndecl (); } - symtab->finalize_compilation_unit (); + /* Issue warnings about static, but not defined, functions, etc, and + generate initial debug information. */ + walk_namespaces (emit_debug_for_namespace, 0); + if (vec_safe_length (pending_statics) != 0) + { + check_global_declarations (pending_statics->address (), + pending_statics->length ()); + emit_debug_global_declarations (pending_statics->address (), + pending_statics->length (), + EMIT_DEBUG_EARLY); + } + +} + +/* Perform any post compilation-proper cleanups for the C++ front-end. + This should really go away. No front-end should need to do + anything past the compilation process. */ + +void +cxx_post_compilation_parsing_cleanups (void) +{ + timevar_start (TV_PHASE_LATE_PARSING_CLEANUPS); if (flag_vtable_verify) { @@ -4675,27 +4711,13 @@ cp_write_global_declarations (void) vtv_generate_init_routine (); } - timevar_stop (TV_PHASE_OPT_GEN); - timevar_start (TV_PHASE_CHECK_DBGINFO); - - /* Now, issue warnings about static, but not defined, functions, - etc., and emit debugging information. */ - walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider); - if (vec_safe_length (pending_statics) != 0) - { - check_global_declarations (pending_statics->address (), - pending_statics->length ()); - emit_debug_global_declarations (pending_statics->address (), - pending_statics->length ()); - } - perform_deferred_noexcept_checks (); /* Generate hidden aliases for Java. */ - if (candidates) + if (java_hidden_aliases) { - build_java_method_aliases (candidates); - delete candidates; + build_java_method_aliases (java_hidden_aliases); + delete java_hidden_aliases; } finish_repo (); @@ -4709,13 +4731,13 @@ cp_write_global_declarations (void) dump_tree_statistics (); dump_time_statistics (); } - input_location = locus; + input_location = locus_at_end_of_parsing; #ifdef ENABLE_CHECKING validate_conversion_obstack (); #endif /* ENABLE_CHECKING */ - timevar_stop (TV_PHASE_CHECK_DBGINFO); + timevar_stop (TV_PHASE_LATE_PARSING_CLEANUPS); } /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 45b3b99..92c218f 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, /*early=*/false); + (*debug_hooks->early_global_decl) (alias); } /* Like pushdecl, only it places X in the current namespace, diff --git a/gcc/dbxout.c b/gcc/dbxout.c index 208cec9..3cba2dd 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -325,7 +325,8 @@ 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, bool); +static void dbxout_early_global_decl (tree); +static void dbxout_late_global_decl (tree); static void dbxout_type_decl (tree, int); static void dbxout_handle_pch (unsigned); static void debug_free_queue (void); @@ -366,7 +367,8 @@ const struct gcc_debug_hooks dbx_debug_hooks = #endif debug_nothing_int, /* end_function */ dbxout_function_decl, - dbxout_global_decl, /* global_decl */ + dbxout_early_global_decl, /* early_global_decl */ + dbxout_late_global_decl, /* late_global_decl */ dbxout_type_decl, /* type_decl */ debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */ debug_nothing_tree, /* deferred_inline_function */ @@ -402,7 +404,8 @@ const struct gcc_debug_hooks xcoff_debug_hooks = debug_nothing_tree, /* begin_function */ xcoffout_end_function, debug_nothing_tree, /* function_decl */ - dbxout_global_decl, /* global_decl */ + dbxout_early_global_decl, /* early_global_decl */ + dbxout_late_global_decl, /* late_global_decl */ dbxout_type_decl, /* type_decl */ debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */ debug_nothing_tree, /* deferred_inline_function */ @@ -1317,10 +1320,16 @@ dbxout_function_decl (tree decl) #endif /* DBX_DEBUGGING_INFO */ +static void +dbxout_early_global_decl (tree decl ATTRIBUTE_UNUSED) +{ + /* NYI for non-dwarf. */ +} + /* Debug information for a global DECL. Called from toplev.c after compilation proper has finished. */ static void -dbxout_global_decl (tree decl, bool early ATTRIBUTE_UNUSED) +dbxout_late_global_decl (tree decl) { if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) { diff --git a/gcc/debug.c b/gcc/debug.c index b5818de..449d3a1 100644 --- a/gcc/debug.c +++ b/gcc/debug.c @@ -43,7 +43,8 @@ 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_bool, /* global_decl */ + debug_nothing_tree, /* early_global_decl */ + debug_nothing_tree, /* late_global_decl */ debug_nothing_tree_int, /* type_decl */ debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */ debug_nothing_tree, /* deferred_inline_function */ @@ -71,12 +72,6 @@ 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 9440515..ec387ca 100644 --- a/gcc/debug.h +++ b/gcc/debug.h @@ -92,12 +92,15 @@ struct gcc_debug_hooks function. */ void (* function_decl) (tree decl); - /* Debug information for a global DECL. Called from toplev.c after - 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 global DECL. Called from the parser after + the parsing process has finished. */ + void (* early_global_decl) (tree decl); + + /* Augment debug information generated by early_global_decl with + more complete debug info (if applicable). Called from toplev.c + after the compilation proper has finished and cgraph information + is available. */ + void (* late_global_decl) (tree decl); /* Debug information for a type DECL. Called from toplev.c after compilation proper, also from various language front ends to @@ -159,7 +162,6 @@ 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 ddc44f4..0ad8b5d 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2430,7 +2430,8 @@ 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, bool); +static void dwarf2out_early_global_decl (tree); +static void dwarf2out_late_global_decl (tree); static void dwarf2out_type_decl (tree, int); static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool); static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree, @@ -2468,7 +2469,8 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = dwarf2out_begin_function, dwarf2out_end_function, /* end_function */ dwarf2out_function_decl, /* function_decl */ - dwarf2out_global_decl, + dwarf2out_early_global_decl, + dwarf2out_late_global_decl, dwarf2out_type_decl, /* type_decl */ dwarf2out_imported_module_or_decl, debug_nothing_tree, /* deferred_inline_function */ @@ -2609,7 +2611,7 @@ typedef struct GTY((chain_circular ("%h.die_sib"))) 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 */ - /* Die was generated early via dwarf2out_early_decl. */ + /* Die was generated early via dwarf2out_early_global_decl. */ BOOL_BITFIELD dumped_early : 1; /* Lots of spare bits. */ } @@ -17721,12 +17723,12 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p, decl_quals (node_or_origin), context_die); } + add_location: if (origin == NULL && DECL_ARTIFICIAL (node)) add_AT_flag (parm_die, DW_AT_artificial, 1); if (node && node != origin) equate_decl_number_to_die (node, parm_die); - add_location: if (! DECL_ABSTRACT (node_or_origin)) add_location_or_const_value_attribute (parm_die, node_or_origin, node == NULL, DW_AT_location); @@ -20817,29 +20819,64 @@ 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 initial debug information for global DECL. Called from the + end of the parsing process. - 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 ;-). */ + This is the initial debug generation process. As such, the DIEs + generated may be incomplete. A later debug generation pass + (dwarf2out_late_global_decl) will augment the information generated + in this pass (e.g., with complete location info). */ static void -dwarf2out_global_decl (tree decl, bool early) +dwarf2out_early_global_decl (tree decl) { - if (early) + /* gen_decl_die() will set DECL_ABSTRACT because + cgraph_function_possibly_inlined_p() returns true. This is in + turn will cause DW_AT_inline attributes to be set. + + This happens because at early dwarf generation, there is no + cgraph information, causing cgraph_function_possibly_inlined_p() + to return true. Trick cgraph_function_possibly_inlined_p() + while we generate dwarf early. */ + bool save = symtab->global_info_ready; + symtab->global_info_ready = true; + + /* We don't handle TYPE_DECLs. If required, they'll be reached via + other DECLs and they can point to template types or other things + that dwarf2out can't handle when done via dwarf2out_decl. */ + if (TREE_CODE (decl) != TYPE_DECL + && TREE_CODE (decl) != PARM_DECL) { - dwarf2out_early_decl (decl); - return; + if (TREE_CODE (decl) == FUNCTION_DECL) + { + /* A missing cfun means the symbol is unused and was removed + from the callgraph. */ + if (!DECL_STRUCT_FUNCTION (decl)) + goto early_decl_exit; + + push_cfun (DECL_STRUCT_FUNCTION (decl)); + current_function_decl = decl; + } + dw_die_ref die = dwarf2out_decl (decl); + if (die) + die->dumped_early = true; + if (TREE_CODE (decl) == FUNCTION_DECL) + { + pop_cfun (); + current_function_decl = NULL; + } } + early_decl_exit: + symtab->global_info_ready = save; + return; +} + +/* Output debug information for global decl DECL. Called from + toplev.c after compilation proper has finished. */ + +static void +dwarf2out_late_global_decl (tree decl) +{ /* Output DWARF2 information for file-scope tentative data object declarations, file-scope (extern) function declarations (which had no corresponding body) and file-scope tagged type declarations @@ -21041,11 +21078,7 @@ dwarf2out_decl (tree decl) 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; - } + early_die = lookup_decl_die (decl); #endif switch (TREE_CODE (decl)) @@ -21176,57 +21209,12 @@ dwarf2out_decl (tree decl) #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); + if (early_die && early_die->dumped_early) + gcc_assert (early_die == die); #endif return die; } -/* Early dumping of DECLs before we lose language data. */ - -void -dwarf2out_early_decl (tree decl) -{ - /* gen_decl_die() will set DECL_ABSTRACT because - cgraph_function_possibly_inlined_p() returns true. This is in - turn will cause DW_AT_inline attributes to be set. - - This happens because at early dwarf generation, there is no - cgraph information, causing cgraph_function_possibly_inlined_p() - to return true. Trick cgraph_function_possibly_inlined_p() - while we generate dwarf early. */ - bool save = symtab->global_info_ready; - symtab->global_info_ready = true; - - /* We don't handle TYPE_DECLs. If required, they'll be reached via - other DECLs and they can point to template types or other things - that dwarf2out can't handle when done via dwarf2out_decl. */ - if (TREE_CODE (decl) != TYPE_DECL - && TREE_CODE (decl) != PARM_DECL) - { - if (TREE_CODE (decl) == FUNCTION_DECL) - { - /* A missing cfun means the symbol is unused and was removed - from the callgraph. */ - if (!DECL_STRUCT_FUNCTION (decl)) - goto early_decl_exit; - - push_cfun (DECL_STRUCT_FUNCTION (decl)); - current_function_decl = decl; - } - dw_die_ref die = dwarf2out_decl (decl); - if (die) - die->dumped_early = true; - if (TREE_CODE (decl) == FUNCTION_DECL) - { - pop_cfun (); - current_function_decl = NULL; - } - } - early_decl_exit: - symtab->global_info_ready = save; - return; -} - /* Write the debugging output for DECL. */ static void diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index da3a0d0..ef0faac 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -81,7 +81,6 @@ static bool global_bindings_p (void); /* Each front end provides its own. */ static bool gfc_init (void); static void gfc_finish (void); -static void gfc_write_global_declarations (void); static void gfc_be_parse_file (void); static alias_set_type gfc_get_alias_set (tree); static void gfc_init_ts (void); @@ -108,7 +107,6 @@ static const struct attribute_spec gfc_attribute_table[] = #undef LANG_HOOKS_NAME #undef LANG_HOOKS_INIT #undef LANG_HOOKS_FINISH -#undef LANG_HOOKS_WRITE_GLOBALS #undef LANG_HOOKS_OPTION_LANG_MASK #undef LANG_HOOKS_INIT_OPTIONS_STRUCT #undef LANG_HOOKS_INIT_OPTIONS @@ -142,7 +140,6 @@ static const struct attribute_spec gfc_attribute_table[] = #define LANG_HOOKS_NAME "GNU Fortran" #define LANG_HOOKS_INIT gfc_init #define LANG_HOOKS_FINISH gfc_finish -#define LANG_HOOKS_WRITE_GLOBALS gfc_write_global_declarations #define LANG_HOOKS_OPTION_LANG_MASK gfc_option_lang_mask #define LANG_HOOKS_INIT_OPTIONS_STRUCT gfc_init_options_struct #define LANG_HOOKS_INIT_OPTIONS gfc_init_options @@ -220,6 +217,19 @@ gfc_be_parse_file (void) /* Clear the binding level stack. */ while (!global_bindings_p ()) poplevel (0, 0); + + /* Finalize all of the globals. + + Emulated tls lowering needs to see all TLS variables before we + call finalize_compilation_unit. The C/C++ front ends manage this + by calling decl_rest_of_compilation on each global and static + variable as they are seen. The Fortran front end waits until + here. */ + for (tree decl = getdecls (); decl ; decl = DECL_CHAIN (decl)) + rest_of_decl_compilation (decl, true, true); + + /* Do the debug dance. */ + global_decl_processing_and_early_debug (); } @@ -263,32 +273,6 @@ gfc_finish (void) return; } -/* ??? This is something of a hack. - - Emulated tls lowering needs to see all TLS variables before we call - finalize_compilation_unit. The C/C++ front ends manage this - by calling decl_rest_of_compilation on each global and static variable - as they are seen. The Fortran front end waits until this hook. - - A Correct solution is for finalize_compilation_unit not to be - called during the WRITE_GLOBALS langhook, and have that hook only do what - its name suggests and write out globals. But the C++ and Java front ends - have (unspecified) problems with aliases that gets in the way. It has - been suggested that these problems would be solved by completing the - conversion to cgraph-based aliases. */ - -static void -gfc_write_global_declarations (void) -{ - tree decl; - - /* Finalize all of the globals. */ - for (decl = getdecls(); decl ; decl = DECL_CHAIN (decl)) - rest_of_decl_compilation (decl, true, true); - - write_global_declarations (); -} - /* These functions and variables deal with binding contours. We only need these functions for the list of PARM_DECLs, but we leave the functions more general; these are a simplified version of the diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 38e6f99..0c7f50e 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, /*early=*/false); + debug_hooks->early_global_decl (decl); } diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 6bac84f..6d65e92 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -2915,7 +2915,8 @@ Gcc_backend::lookup_builtin(const std::string& name) } // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, -// FUNCTION_DECLS, and VARIABLE_DECLS declared globally. +// FUNCTION_DECLS, and VARIABLE_DECLS declared globally, as well as +// emit early debugging information. void Gcc_backend::write_global_definitions( @@ -2988,10 +2989,15 @@ Gcc_backend::write_global_definitions( wrapup_global_declarations(defs, i); - symtab->finalize_compilation_unit(); + emit_debug_global_declarations (defs, i, EMIT_DEBUG_EARLY); + /* ?? Can we leave this call here, thus getting called before + finalize_compilation_unit? + + Originally this was called *AFTER* finalize_compilation_unit. If + `go' really needs this call after finalize_compilation_unit, we + can use LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS (yuck). */ check_global_declarations(defs, i); - emit_debug_global_declarations(defs, i); delete[] defs; } diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c index 24b6437..e8412ac 100644 --- a/gcc/go/go-lang.c +++ b/gcc/go/go-lang.c @@ -284,6 +284,9 @@ go_langhook_parse_file (void) { go_parse_input_files (in_fnames, num_in_fnames, flag_syntax_only, go_require_return_statement); + + /* Final processing of globals and early debug info generation. */ + go_write_globals (); } static tree @@ -429,14 +432,6 @@ go_langhook_getdecls (void) return NULL; } -/* Write out globals. */ - -static void -go_langhook_write_globals (void) -{ - go_write_globals (); -} - /* Go specific gimplification. We need to gimplify CALL_EXPR_STATIC_CHAIN, because the gimplifier doesn't handle it. */ @@ -534,7 +529,6 @@ go_localize_identifier (const char *ident) #undef LANG_HOOKS_GLOBAL_BINDINGS_P #undef LANG_HOOKS_PUSHDECL #undef LANG_HOOKS_GETDECLS -#undef LANG_HOOKS_WRITE_GLOBALS #undef LANG_HOOKS_GIMPLIFY_EXPR #undef LANG_HOOKS_EH_PERSONALITY @@ -551,7 +545,6 @@ go_localize_identifier (const char *ident) #define LANG_HOOKS_GLOBAL_BINDINGS_P go_langhook_global_bindings_p #define LANG_HOOKS_PUSHDECL go_langhook_pushdecl #define LANG_HOOKS_GETDECLS go_langhook_getdecls -#define LANG_HOOKS_WRITE_GLOBALS go_langhook_write_globals #define LANG_HOOKS_GIMPLIFY_EXPR go_langhook_gimplify_expr #define LANG_HOOKS_EH_PERSONALITY go_langhook_eh_personality diff --git a/gcc/godump.c b/gcc/godump.c index 01f8410..ea89ed6 100644 --- a/gcc/godump.c +++ b/gcc/godump.c @@ -493,12 +493,18 @@ go_function_decl (tree decl) go_decl (decl); } +static void +go_early_global_decl (tree decl) +{ + real_debug_hooks->early_global_decl (decl); +} + /* A global variable decl. */ static void -go_global_decl (tree decl, bool early) +go_late_global_decl (tree decl) { - real_debug_hooks->global_decl (decl, early); + real_debug_hooks->late_global_decl (decl); go_decl (decl); } @@ -1240,7 +1246,8 @@ dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks) go_debug_hooks.define = go_define; go_debug_hooks.undef = go_undef; go_debug_hooks.function_decl = go_function_decl; - go_debug_hooks.global_decl = go_global_decl; + go_debug_hooks.early_global_decl = go_early_global_decl; + go_debug_hooks.late_global_decl = go_late_global_decl; go_debug_hooks.type_decl = go_type_decl; macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq, diff --git a/gcc/java/class.c b/gcc/java/class.c index 0d51165..dd1d53d 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -3267,17 +3267,4 @@ in_same_package (tree name1, tree name2) return (pkg1 == pkg2); } -/* lang_hooks.decls.final_write_globals: perform final processing on - global variables. */ - -void -java_write_globals (void) -{ - tree *vec = vec_safe_address (pending_static_fields); - int len = vec_safe_length (pending_static_fields); - write_global_declarations (); - emit_debug_global_declarations (vec, len); - vec_free (pending_static_fields); -} - #include "gt-java-class.h" diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index e832f44..cca5f70 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -1176,8 +1176,6 @@ int cxx_keyword_p (const char *name, int length); extern GTY(()) vec *pending_static_fields; -extern void java_write_globals (void); - #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL) /* Access flags etc for a method (a FUNCTION_DECL): */ diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c index 9c4a9cf..0abfff7 100644 --- a/gcc/java/jcf-parse.c +++ b/gcc/java/jcf-parse.c @@ -42,6 +42,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "bitmap.h" #include "target.h" #include "wide-int.h" +#include "toplev.h" #ifdef HAVE_LOCALE_H #include @@ -1980,6 +1981,13 @@ java_parse_file (void) /* Arrange for any necessary initialization to happen. */ java_emit_static_constructor (); gcc_assert (global_bindings_p ()); + + /* Do final processing on globals and emit early debug information. */ + tree *vec = vec_safe_address (pending_static_fields); + int len = vec_safe_length (pending_static_fields); + global_decl_processing_and_early_debug (); + emit_debug_global_declarations (vec, len, EMIT_DEBUG_EARLY); + vec_free (pending_static_fields); } diff --git a/gcc/java/lang.c b/gcc/java/lang.c index 8a68691..be6c4c7 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -142,8 +142,6 @@ struct GTY(()) language_function { #define LANG_HOOKS_DECL_PRINTABLE_NAME lang_printable_name #undef LANG_HOOKS_PRINT_ERROR_FUNCTION #define LANG_HOOKS_PRINT_ERROR_FUNCTION java_print_error_function -#undef LANG_HOOKS_WRITE_GLOBALS -#define LANG_HOOKS_WRITE_GLOBALS java_write_globals #undef LANG_HOOKS_TYPE_FOR_MODE #define LANG_HOOKS_TYPE_FOR_MODE java_type_for_mode diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index e77d2d9..7d3903f 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -204,7 +204,7 @@ extern tree lhd_make_node (enum tree_code); #define LANG_HOOKS_GETDECLS getdecls #define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P hook_bool_tree_false #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl -#define LANG_HOOKS_WRITE_GLOBALS write_global_declarations +#define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS NULL #define LANG_HOOKS_DECL_OK_FOR_SIBCALL lhd_decl_ok_for_sibcall #define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE hook_bool_const_tree_false #define LANG_HOOKS_OMP_PREDETERMINED_SHARING lhd_omp_predetermined_sharing @@ -228,7 +228,7 @@ extern tree lhd_make_node (enum tree_code); LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \ LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \ LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \ - LANG_HOOKS_WRITE_GLOBALS, \ + LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS, \ LANG_HOOKS_DECL_OK_FOR_SIBCALL, \ LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE, \ LANG_HOOKS_OMP_PREDETERMINED_SHARING, \ diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 8ff91ba..dfc3ab6 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -290,15 +290,16 @@ lhd_decl_ok_for_sibcall (const_tree decl ATTRIBUTE_UNUSED) return true; } -/* lang_hooks.decls.final_write_globals: perform final processing on - global variables. */ +/* Generic global declaration processing and early debug generation. + This is meant to be called by the front-ends at the end of parsing. + C/C++ do their own thing, but other front-ends may call this. */ + void -write_global_declarations (void) +global_decl_processing_and_early_debug (void) { tree globals, decl, *vec; int len, i; - timevar_start (TV_PHASE_DEFERRED); /* Really define vars that have had only a tentative definition. Really output inline functions that must actually be callable and have not been output so far. */ @@ -315,19 +316,9 @@ write_global_declarations (void) wrapup_global_declarations (vec, len); check_global_declarations (vec, len); - timevar_stop (TV_PHASE_DEFERRED); - - timevar_start (TV_PHASE_OPT_GEN); - /* This lang hook is dual-purposed, and also finalizes the - compilation unit. */ - symtab->finalize_compilation_unit (); - timevar_stop (TV_PHASE_OPT_GEN); - timevar_start (TV_PHASE_DBGINFO); - emit_debug_global_declarations (vec, len); - timevar_stop (TV_PHASE_DBGINFO); + emit_debug_global_declarations (vec, len, EMIT_DEBUG_EARLY); - /* Clean up. */ free (vec); } diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 72fa85e..40cfdbc 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -181,9 +181,11 @@ struct lang_hooks_for_decls We will already have checked that it has static binding. */ bool (*warn_unused_global) (const_tree); - /* Obtain a list of globals and do final output on them at end - of compilation */ - void (*final_write_globals) (void); + /* Perform any post compilation-proper parser cleanups and + processing. This is currently only needed for the C++ parser, + which hopefully can be cleaned up so this hook is no longer + necessary. */ + void (*post_compilation_parsing_cleanups) (void); /* True if this decl may be called via a sibcall. */ bool (*ok_for_sibcall) (const_tree); diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index 1f39949..88fd46c 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -1083,19 +1083,6 @@ lto_getdecls (void) return NULL_TREE; } -static void -lto_write_globals (void) -{ - if (flag_wpa) - return; - - /* Output debug info for global variables. */ - varpool_node *vnode; - FOR_EACH_DEFINED_VARIABLE (vnode) - if (!decl_function_context (vnode->decl)) - debug_hooks->global_decl (vnode->decl, /*early=*/false); -} - static tree lto_builtin_function (tree decl) { @@ -1275,8 +1262,6 @@ static void lto_init_ts (void) #define LANG_HOOKS_PUSHDECL lto_pushdecl #undef LANG_HOOKS_GETDECLS #define LANG_HOOKS_GETDECLS lto_getdecls -#undef LANG_HOOKS_WRITE_GLOBALS -#define LANG_HOOKS_WRITE_GLOBALS lto_write_globals #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE #define LANG_HOOKS_REGISTER_BUILTIN_TYPE lto_register_builtin_type #undef LANG_HOOKS_BUILTIN_FUNCTION diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index df59981..f79a1ce 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -417,8 +417,7 @@ objc_init (void) return true; } -/* This is called automatically (at the very end of compilation) by - c_write_global_declarations and cp_write_global_declarations. */ +/* This is called at the end of parsing by the C/C++ parsers. */ void objc_write_global_declarations (void) { diff --git a/gcc/sdbout.c b/gcc/sdbout.c index d81b184..a7d2f67 100644 --- a/gcc/sdbout.c +++ b/gcc/sdbout.c @@ -119,7 +119,8 @@ 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, bool); +static void sdbout_early_global_decl (tree); +static void sdbout_late_global_decl (tree); static void sdbout_begin_prologue (unsigned int, const char *); static void sdbout_end_prologue (unsigned int, const char *); static void sdbout_begin_function (tree); @@ -294,7 +295,8 @@ const struct gcc_debug_hooks sdb_debug_hooks = sdbout_begin_function, /* begin_function */ sdbout_end_function, /* end_function */ debug_nothing_tree, /* function_decl */ - sdbout_global_decl, /* global_decl */ + sdbout_early_global_decl, /* early_global_decl */ + sdbout_late_global_decl, /* late_global_decl */ sdbout_symbol, /* type_decl */ debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */ debug_nothing_tree, /* deferred_inline_function */ @@ -1417,11 +1419,17 @@ sdbout_reg_parms (tree parms) } } +static void +sdbout_early_global_decl (tree decl ATTRIBUTE_UNUSED) +{ + /* NYI for non-dwarf. */ +} + /* Output debug information for a global DECL. Called from toplev.c after compilation proper has finished. */ static void -sdbout_global_decl (tree decl, bool early ATTRIBUTE_UNUSED) +sdbout_late_global_decl (tree decl) { if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl) diff --git a/gcc/timevar.def b/gcc/timevar.def index a04d05c..d9d95de 100644 --- a/gcc/timevar.def +++ b/gcc/timevar.def @@ -31,11 +31,16 @@ /* The total execution time. */ DEFTIMEVAR (TV_TOTAL , "total time") -/* The compiler phases. These must be mutually exclusive. - Ideally, they would sum to near the total time. */ +/* The compiler phases. + + These must be mutually exclusive, and the NAME field must begin + with "phase". + + Also, their sum must be within a millionth of the total time (see + validate_phases). */ DEFTIMEVAR (TV_PHASE_SETUP , "phase setup") DEFTIMEVAR (TV_PHASE_PARSING , "phase parsing") -DEFTIMEVAR (TV_PHASE_DEFERRED , "phase lang. deferred") +DEFTIMEVAR (TV_PHASE_LATE_PARSING_CLEANUPS, "phase late parsing cleanups") DEFTIMEVAR (TV_PHASE_OPT_GEN , "phase opt and generate") DEFTIMEVAR (TV_PHASE_DBGINFO , "phase debug info") DEFTIMEVAR (TV_PHASE_CHECK_DBGINFO , "phase check & debug info") diff --git a/gcc/toplev.c b/gcc/toplev.c index ceefa1b..2347d6c 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -519,10 +519,13 @@ check_global_declarations (tree *v, int len) check_global_declaration_1 (v[i]); } -/* Emit debugging information for all global declarations in VEC. */ +/* Emit debugging information for all global declarations in VEC. + WHEN is either EMIT_DEBUG_EARLY or EMIT_DEBUG_LATE depending on if + we are generating early debug (at the end of parsing), or the late + (post compilation) version. */ void -emit_debug_global_declarations (tree *vec, int len) +emit_debug_global_declarations (tree *vec, int len, enum emit_debug when) { int i; @@ -532,7 +535,14 @@ emit_debug_global_declarations (tree *vec, int len) timevar_push (TV_SYMOUT); for (i = 0; i < len; i++) - debug_hooks->global_decl (vec[i], /*early=*/false); + { + if (when == EMIT_DEBUG_EARLY) + debug_hooks->early_global_decl (vec[i]); + else if (when == EMIT_DEBUG_LATE) + debug_hooks->late_global_decl (vec[i]); + else + gcc_unreachable (); + } timevar_pop (TV_SYMOUT); } @@ -545,8 +555,7 @@ compile_file (void) timevar_start (TV_PHASE_PARSING); timevar_push (TV_PARSE_GLOBAL); - /* Call the parser, which parses the entire file (calling - rest_of_compilation for each function). */ + /* Parse entire file and generate initial debug information. */ lang_hooks.parse_file (); timevar_pop (TV_PARSE_GLOBAL); @@ -560,12 +569,33 @@ compile_file (void) ggc_protect_identifiers = false; - /* This must also call finalize_compilation_unit. */ - lang_hooks.decls.final_write_globals (); + /* Run the actual compilation process. */ + if (!in_lto_p) + { + timevar_start (TV_PHASE_OPT_GEN); + symtab->finalize_compilation_unit (); + timevar_stop (TV_PHASE_OPT_GEN); + } + + /* Perform any post compilation-proper parser cleanups and + processing. This is currently only needed for the C++ parser, + which can be hopefully cleaned up so this hook is no longer + necessary. */ + if (lang_hooks.decls.post_compilation_parsing_cleanups) + lang_hooks.decls.post_compilation_parsing_cleanups (); if (seen_error ()) return; + /* After the parser has generated debugging information, augment + this information with any new location/etc information that may + have become available after the compilation proper. */ + timevar_start (TV_PHASE_DBGINFO); + symtab_node *node; + FOR_EACH_DEFINED_SYMBOL (node) + debug_hooks->late_global_decl (node->decl); + timevar_stop (TV_PHASE_DBGINFO); + timevar_start (TV_PHASE_LATE_ASM); /* Compilation unit is finalized. When producing non-fat LTO object, we are diff --git a/gcc/toplev.h b/gcc/toplev.h index 1b54578..ff1fd9d 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -42,8 +42,14 @@ extern bool wrapup_global_declaration_2 (tree); extern bool wrapup_global_declarations (tree *, int); extern void check_global_declaration_1 (tree); extern void check_global_declarations (tree *, int); -extern void emit_debug_global_declarations (tree *, int); -extern void write_global_declarations (void); + +enum emit_debug { + EMIT_DEBUG_EARLY, + EMIT_DEBUG_LATE +}; +extern void emit_debug_global_declarations (tree *, int, enum emit_debug); + +extern void global_decl_processing_and_early_debug (void); extern void dump_memory_report (bool); extern void dump_profile_report (void); diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index ad474a5..9100cd1 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -4494,9 +4494,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) return successfully_inlined; } -/* Expand call statements reachable from STMT_P. - We can only have CALL_EXPRs as the "toplevel" tree code or nested - in a MODIFY_EXPR. */ +/* Expand call statements in BB when profitable. */ static bool gimple_expand_calls_inline (basic_block bb, copy_body_data *id) diff --git a/gcc/tree.c b/gcc/tree.c index 8e9876e..9c7251c 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -5089,6 +5089,8 @@ free_lang_data_in_decl (tree decl) At this point, it is not needed anymore. */ DECL_SAVED_TREE (decl) = NULL_TREE; + /* ?? This should be OK to remove now that we are generating dwarf + early. */ /* Clear the abstract origin if it refers to a method. Otherwise dwarf2out.c will ICE as we clear TYPE_METHODS and thus the origin will not be output correctly. */ @@ -5630,7 +5632,11 @@ free_lang_data (void) unsigned i; /* If we are the LTO frontend we have freed lang-specific data already. */ - if (in_lto_p) + if (in_lto_p + /* FIXME: Eventually we need to remove this so the function + proceeds and we can be sure there is no language specific + data past cgraph. */ + || !flag_generate_lto) return 0; /* Allocate and assign alias sets to the standard integer types diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c index 2ad9e9b..b0c305f 100644 --- a/gcc/vmsdbgout.c +++ b/gcc/vmsdbgout.c @@ -163,7 +163,8 @@ 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, bool); +static void vmsdbgout_early_global_decl (tree); +static void vmsdbgout_late_global_decl (tree); static void vmsdbgout_type_decl (tree, int); static void vmsdbgout_abstract_function (tree); @@ -188,7 +189,8 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks vmsdbgout_begin_function, vmsdbgout_end_function, vmsdbgout_decl, - vmsdbgout_global_decl, + vmsdbgout_early_global_decl, + vmsdbgout_late_global_decl, vmsdbgout_type_decl, /* type_decl */ debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */ debug_nothing_tree, /* deferred_inline_function */ @@ -1510,10 +1512,18 @@ vmsdbgout_decl (tree decl) /* Not implemented in VMS Debug. */ static void -vmsdbgout_global_decl (tree decl, bool early) +vmsdbgout_early_global_decl (tree decl) +{ + /* NYI for non-dwarf. */ +} + +/* Not implemented in VMS Debug. */ + +static void +vmsdbgout_late_global_decl (tree decl) { if (write_symbols == VMS_AND_DWARF2_DEBUG) - (*dwarf2_debug_hooks.global_decl) (decl, early); + (*dwarf2_debug_hooks.late_global_decl) (decl); } /* Not implemented in VMS Debug. */