From patchwork Fri Jan 16 02:58:35 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 429670 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 7168214015A for ; Fri, 16 Jan 2015 13:59:04 +1100 (AEDT) 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:content-type; q=dns; s=default; b=opz8PyICr6SVFEos7bEL+sz/TznO56TRfMPUR4CU5Bo Eg6I+9ueLG/4czCfMg09KC8fuJPjWO57FGXkbAUWT7fupc+XRk7GxTm1PqLYQSlP Ff7ZCx50tE7b7yBuGd8P+yD2LQcnhpxA6CT+09iqAAgZ0V4o4GTXuPdpPrXQRL1I = 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:content-type; s=default; bh=ZfVx0KcDiEBI3agJ9reIZ8K8MnY=; b=SVkxRfd+HS9Inu6Nv sadWMewRhfs3G+g1z78pUqIz3TXawGUkllv7FWMZaKWGb1Lhnmvug/ISfq2/xCbz q3/M2Na6BeZFsRguI0+ehMl1R+J1A1Ba5GItGI1CMXrmv+nD118DxBgtTq8qameB h/YTBbw1n1spTKJ8IuIFH07r8I= Received: (qmail 17594 invoked by alias); 16 Jan 2015 02:58:55 -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 17579 invoked by uid 89); 16 Jan 2015 02:58:50 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD 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, 16 Jan 2015 02:58:41 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t0G2wdHu020294 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 15 Jan 2015 21:58:40 -0500 Received: from reynosa.quesejoda.com (vpn-50-241.rdu2.redhat.com [10.10.50.241]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t0G2wZm6026860; Thu, 15 Jan 2015 21:58:37 -0500 Message-ID: <54B87E5B.1090502@redhat.com> Date: Thu, 15 Jan 2015 18:58:35 -0800 From: Aldy Hernandez User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: jason merrill CC: Richard Biener , gcc-patches Subject: [debug-early] C++ clones and limbo DIEs Hi Jason. Hi Richard. While adjusting the limbdo_die_list for early debug I noticed we weren't early generating C++ constructors/destructors. This got me on a detour of sorts. I noticed dwarf2out's gen_member_die() disallows generation of clones earlier, by design: /* Don't include clones in the member list. */ if (DECL_ABSTRACT_ORIGIN (member)) continue; I played around trying to disable this "feature", but my approach ran into various walls, and I decided instead to attack it from the front-end side. The attached patch generates early DIEs for the C++ clones in the C++ parser. I'd be (un)happy to revisit the dwarf2out approach if it's deemed more appropriate. Now back to limbdo_die_list... My approach is to flush the limbo list, generically, after the front-ends have finished, by adding a new "early_finish" debug hook. This gets rid of any permanence into LTO time. Then I flush it out again, if the middle end (or LTO, etc) has added any limbo DIEs. I wish we didn't need to flush the limbo list past the compilation proper, but some things like Cilk+ generate function trees way late in the game, so we end up generating limbo DIEs past where I'd like to. Please see the comment in the source code. All in all, this patch should get rid of any middle-end dependence on the early debug generated limbo DIEs. Are you happy with this? I'd like to get your input before committing to this approach. Thanks. Aldy commit cd20df2a48ce4f0d4e64626d61f8f61a810cf742 Author: Aldy Hernandez Date: Wed Jan 14 13:33:40 2015 -0800 * cp/decl2.c (c_parse_final_cleanups): Emit early debug information for clones. * dbxout.c (dbx_debug_hooks): Add early_finish field. (xcoff_debug_hooks): Same. * sdbout.c (sdb_debug_hooks): Same. * vmsdbgout.c (vmsdbg_debug_hooks): Same. * debug.c (do_nothing_debug_hooks): Same. * debug.h (struct gcc_debug_hooks): Same. * dwarf2out.c (dwarf2_debug_hooks): Same. (dwarf2out_finish): Move limbo list handling to... (dwarf2out_early_finish): ...here. * toplev.c (compile_file): Call debug_hooks->early_finish. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 691688b..b9a407a 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4737,6 +4737,13 @@ c_parse_final_cleanups (void) generate initial debug information. */ timevar_stop (TV_PHASE_PARSING); timevar_start (TV_PHASE_DBGINFO); + + /* Emit debug information for clones. */ + symtab_node *node; + FOR_EACH_DEFINED_SYMBOL (node) + if (DECL_ABSTRACT_ORIGIN (node->decl)) + debug_hooks->early_global_decl (DECL_ABSTRACT_ORIGIN (node->decl)); + walk_namespaces (emit_debug_for_namespace, 0); if (vec_safe_length (pending_statics) != 0) { diff --git a/gcc/dbxout.c b/gcc/dbxout.c index 430a2eb..202ef8a 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -359,6 +359,7 @@ const struct gcc_debug_hooks dbx_debug_hooks = dbxout_init, dbxout_finish, debug_nothing_void, + debug_nothing_void, debug_nothing_int_charstar, debug_nothing_int_charstar, dbxout_start_source_file, @@ -400,6 +401,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks = dbxout_init, dbxout_finish, debug_nothing_void, + debug_nothing_void, debug_nothing_int_charstar, debug_nothing_int_charstar, dbxout_start_source_file, diff --git a/gcc/debug.c b/gcc/debug.c index 449d3a1..d0e00c0 100644 --- a/gcc/debug.c +++ b/gcc/debug.c @@ -27,6 +27,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks = { debug_nothing_charstar, debug_nothing_charstar, + debug_nothing_void, /* early_finish */ debug_nothing_void, debug_nothing_int_charstar, debug_nothing_int_charstar, diff --git a/gcc/debug.h b/gcc/debug.h index f9485bc..a8d3f23 100644 --- a/gcc/debug.h +++ b/gcc/debug.h @@ -30,6 +30,9 @@ struct gcc_debug_hooks /* Output debug symbols. */ void (* finish) (const char *main_filename); + /* Run cleanups necessary after early debug generation. */ + void (* early_finish) (void); + /* Called from cgraph_optimize before starting to assemble functions/variables/toplevel asms. */ void (* assembly_start) (void); diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index e3ccda2..80d43af 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2424,6 +2424,7 @@ build_cfa_aligned_loc (dw_cfa_location *cfa, static void dwarf2out_init (const char *); static void dwarf2out_finish (const char *); +static void dwarf2out_early_finish (void); static void dwarf2out_assembly_start (void); static void dwarf2out_define (unsigned int, const char *); static void dwarf2out_undef (unsigned int, const char *); @@ -2451,6 +2452,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = { dwarf2out_init, dwarf2out_finish, + dwarf2out_early_finish, dwarf2out_assembly_start, dwarf2out_define, dwarf2out_undef, @@ -24739,10 +24741,27 @@ optimize_location_lists (dw_die_ref die) static void dwarf2out_finish (const char *filename) { - limbo_die_node *node, *next_node; comdat_type_node *ctnode; dw_die_ref main_comp_unit_die; + /* Technically limbo_die_list should either be empty because + dwarf2out_early_finish took care of everything, or should _only_ + have inline instances that will be created late (which is OK, + because they'll be pointing to the early generated abstract). + + However, functions can be created after the parsers are done + (e.g. create_cilk_helper_decl), which will populate the + limbo_die_list again. Eventually all late function creation + should be banned, or these new functions should be created with a + proper context_die, thus avoiding limbo. For now, it doesn't + hurt, since late creation should have all the location + information needed (and if it doesn't, we don't care-- the code + is undebuggable). + + If there was anything created late, flush it out. */ + if (limbo_die_list) + dwarf2out_early_finish (); + /* PCH might result in DW_AT_producer string being restored from the header compilation, so always fill it with empty string initially and overwrite only here. */ @@ -24767,55 +24786,6 @@ dwarf2out_finish (const char *filename) add_comp_dir_attribute (comp_unit_die ()); } - /* Traverse the limbo die list, and add parent/child links. The only - dies without parents that should be here are concrete instances of - inline functions, and the comp_unit_die. We can ignore the comp_unit_die. - For concrete instances, we can get the parent die from the abstract - instance. */ - for (node = limbo_die_list; node; node = next_node) - { - dw_die_ref die = node->die; - next_node = node->next; - - if (die->die_parent == NULL) - { - dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin); - - if (origin && origin->die_parent) - add_child_die (origin->die_parent, die); - else if (is_cu_die (die)) - ; - else if (seen_error ()) - /* It's OK to be confused by errors in the input. */ - add_child_die (comp_unit_die (), die); - else - { - /* In certain situations, the lexical block containing a - nested function can be optimized away, which results - in the nested function die being orphaned. Likewise - with the return type of that nested function. Force - this to be a child of the containing function. - - It may happen that even the containing function got fully - inlined and optimized out. In that case we are lost and - assign the empty child. This should not be big issue as - the function is likely unreachable too. */ - gcc_assert (node->created_for); - - if (DECL_P (node->created_for)) - origin = get_context_die (DECL_CONTEXT (node->created_for)); - else if (TYPE_P (node->created_for)) - origin = scope_die_for (node->created_for, comp_unit_die ()); - else - origin = comp_unit_die (); - - add_child_die (origin, die); - } - } - } - - limbo_die_list = NULL; - #if ENABLE_ASSERT_CHECKING { dw_die_ref die = comp_unit_die (), c; @@ -24860,9 +24830,10 @@ dwarf2out_finish (const char *filename) if (flag_eliminate_dwarf2_dups) break_out_includes (comp_unit_die ()); - /* Traverse the DIE's and add add sibling attributes to those DIE's + /* Traverse the DIE's and add sibling attributes to those DIE's that have children. */ add_sibling_attributes (comp_unit_die ()); + limbo_die_node *node; for (node = limbo_die_list; node; node = node->next) add_sibling_attributes (node->die); for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next) @@ -25124,6 +25095,66 @@ dwarf2out_finish (const char *filename) output_indirect_strings (); } +/* Perform any cleanups needed after the early debug generation pass + has run. */ + +static void +dwarf2out_early_finish (void) +{ + /* Traverse the limbo die list, and add parent/child links. The only + dies without parents that should be here are concrete instances of + inline functions, and the comp_unit_die. We can ignore the comp_unit_die. + For concrete instances, we can get the parent die from the abstract + instance. + + The point here is to flush out the limbo list so that it is empty + and we don't need to stream it for LTO. */ + limbo_die_node *node, *next_node; + for (node = limbo_die_list; node; node = next_node) + { + dw_die_ref die = node->die; + next_node = node->next; + + if (die->die_parent == NULL) + { + dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin); + + if (origin && origin->die_parent) + add_child_die (origin->die_parent, die); + else if (is_cu_die (die)) + ; + else if (seen_error ()) + /* It's OK to be confused by errors in the input. */ + add_child_die (comp_unit_die (), die); + else + { + /* In certain situations, the lexical block containing a + nested function can be optimized away, which results + in the nested function die being orphaned. Likewise + with the return type of that nested function. Force + this to be a child of the containing function. + + It may happen that even the containing function got fully + inlined and optimized out. In that case we are lost and + assign the empty child. This should not be big issue as + the function is likely unreachable too. */ + gcc_assert (node->created_for); + + if (DECL_P (node->created_for)) + origin = get_context_die (DECL_CONTEXT (node->created_for)); + else if (TYPE_P (node->created_for)) + origin = scope_die_for (node->created_for, comp_unit_die ()); + else + origin = comp_unit_die (); + + add_child_die (origin, die); + } + } + } + + limbo_die_list = NULL; +} + /* Reset all state within dwarf2out.c so that we can rerun the compiler within the same process. For use by toplev::finalize. */ diff --git a/gcc/sdbout.c b/gcc/sdbout.c index d7b2d6b..43b8cf2 100644 --- a/gcc/sdbout.c +++ b/gcc/sdbout.c @@ -279,6 +279,7 @@ const struct gcc_debug_hooks sdb_debug_hooks = { sdbout_init, /* init */ sdbout_finish, /* finish */ + debug_nothing_void, /* early_finish */ debug_nothing_void, /* assembly_start */ debug_nothing_int_charstar, /* define */ debug_nothing_int_charstar, /* undef */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 42a2cdc..12fa509 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -586,6 +586,10 @@ compile_file (void) if (flag_syntax_only || flag_wpa) return; + /* Clean up anything that needs cleaning up after initial debug + generation. */ + (*debug_hooks->early_finish) (); + ggc_protect_identifiers = false; /* Run the actual compilation process. */ diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c index 5cb66bc..6da48eb 100644 --- a/gcc/vmsdbgout.c +++ b/gcc/vmsdbgout.c @@ -179,6 +179,7 @@ static void vmsdbgout_abstract_function (tree); const struct gcc_debug_hooks vmsdbg_debug_hooks = {vmsdbgout_init, vmsdbgout_finish, + debug_nothing_void, vmsdbgout_assembly_start, vmsdbgout_define, vmsdbgout_undef,