From patchwork Wed Sep 15 22:00:41 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 64915 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]) by ozlabs.org (Postfix) with SMTP id 36C82B6EF1 for ; Thu, 16 Sep 2010 08:00:25 +1000 (EST) Received: (qmail 27104 invoked by alias); 15 Sep 2010 22:00:20 -0000 Received: (qmail 27093 invoked by uid 22791); 15 Sep 2010 22:00:19 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (212.99.106.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 15 Sep 2010 22:00:14 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id C950CCB01E0; Thu, 16 Sep 2010 00:00:11 +0200 (CEST) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 2DF3G3eOoaMk; Thu, 16 Sep 2010 00:00:11 +0200 (CEST) Received: from [192.168.1.2] (bon31-9-83-155-120-49.fbx.proxad.net [83.155.120.49]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mel.act-europe.fr (Postfix) with ESMTP id 949A1CB01DB; Thu, 16 Sep 2010 00:00:07 +0200 (CEST) From: Eric Botcazou To: Jason Merrill Subject: Re: [PATCH] Fix debug info of nested inline functions Date: Thu, 16 Sep 2010 00:00:41 +0200 User-Agent: KMail/1.9.9 Cc: gcc-patches@gcc.gnu.org References: <201007280822.00800.ebotcazou@adacore.com> <201009101754.51460.ebotcazou@adacore.com> <4C8A6C85.4040700@redhat.com> In-Reply-To: <4C8A6C85.4040700@redhat.com> MIME-Version: 1.0 Message-Id: <201009160000.41986.ebotcazou@adacore.com> 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 > OK. I would expect DECL_ABSTRACT (current_function_decl) to be set > whenever DECL_ABSTRACT (decl) is set, but I guess it doesn't hurt to > check both. Yes, that works fine. > > This hunk is necessary to prevent abstracted nested functions from being > > emitted twice in the enclosing function if they are inlined there, as a > > concrete inline and as a concrete out-of-line instance. We wait until > > after actual instances, either inline or out-of-line, are encountered and > > attach the DIEs in dwarf2out_finish. > > OK, I see. I actually got back to the original big testcase I have and, upon re-analyzing it, found out that the first part of the condition is useless. Only the second part: + /* Do not emit concrete instances of abstracted nested functions without + actual instances. */ + else if (TREE_CODE (decl_or_origin) == FUNCTION_DECL + && die + && get_AT (die, DW_AT_inline)) + ; does prevent duplicated entries. > > Yes, the not always fulfilled 4. I mentioned in the message. How would > > you do that? If you look up the DIE of the enclosing function, you get > > the abstract instance. The parent of concrete instances doesn't seem to > > really matter to GDB as long as it isn't abstract. > > It seems like the later block that checks DECL_CONTEXT > (node->created_for) should handle the case of a concrete non-inlined > instance. Of a concrete out-of-inline instance of nested functions? Not in all cases: if the parent is also inlined/abstracted, the lookup will return the abstract instance of the parent. This will work if the parent is a regular function, in which case the unmodified code using DW_AT_abstract_origin already works. Index: dwarf2out.c =================================================================== --- dwarf2out.c (revision 164211) +++ dwarf2out.c (working copy) @@ -18668,7 +18668,13 @@ gen_subprogram_die (tree decl, dw_die_re tree fn_arg_types; tree outer_scope; dw_die_ref old_die = lookup_decl_die (decl); - int declaration = (current_function_decl != decl + /* Emit an abstract instance of nested functions within an abstract instance + of their parent. */ + int declaration = ((decl != current_function_decl + && !(DECL_INITIAL (decl) != NULL_TREE + && DECL_ABSTRACT (decl) + && current_function_decl + && DECL_ABSTRACT (current_function_decl))) || class_or_namespace_scope_p (context_die)); premark_used_types (); @@ -19446,6 +19452,8 @@ gen_inlined_subroutine_die (tree stmt, d gcc_assert (! BLOCK_ABSTRACT (stmt)); decl = block_ultimate_origin (stmt); + if (DECL_IGNORED_P (decl)) + return; /* 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 @@ -20224,8 +20232,25 @@ gen_block_die (tree stmt, dw_die_ref con decls_for_scope (stmt, context_die, depth); } +/* Return true if an abstract instance of function DECL can be generated in + the debug information. */ + +static bool +function_possibly_abstracted_p (tree decl) +{ + while (decl) + { + if (cgraph_function_possibly_inlined_p (decl)) + return true; + decl = decl_function_context (decl); + } + + return false; +} + /* Process variable DECL (or variable with origin ORIGIN) within block STMT and add it to CONTEXT_DIE. */ + static void process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die) { @@ -20243,8 +20268,15 @@ process_scope_var (tree stmt, tree decl, if (die != NULL && die->die_parent == NULL) add_child_die (context_die, die); else if (TREE_CODE (decl_or_origin) == IMPORTED_DECL) - dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin), + dwarf2out_imported_module_or_decl_1 (decl_or_origin, + DECL_NAME (decl_or_origin), stmt, context_die); + /* Do not emit concrete instances of abstracted nested functions without + actual instances. */ + else if (TREE_CODE (decl_or_origin) == FUNCTION_DECL + && die + && get_AT (die, DW_AT_inline)) + ; else gen_decl_die (decl, origin, context_die); } @@ -20584,11 +20616,11 @@ gen_decl_die (tree decl, tree origin, dw ? DECL_ORIGIN (origin) : DECL_ABSTRACT_ORIGIN (decl)); - /* If we're emitting an out-of-line copy of an inline function, + /* If we're emitting an out-of-line copy of an abstracted function, emit info for the abstract instance and set up to refer to it. */ - else if (cgraph_function_possibly_inlined_p (decl) - && ! DECL_ABSTRACT (decl) - && ! class_or_namespace_scope_p (context_die) + else if (!DECL_ABSTRACT (decl) + && function_possibly_abstracted_p (decl) + && !class_or_namespace_scope_p (context_die) /* dwarf2out_abstract_function won't emit a die if this is just a declaration. We must avoid setting DECL_ABSTRACT_ORIGIN in that case, because that works only if we have a die. */ @@ -22361,7 +22393,18 @@ dwarf2out_finish (const char *filename) dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin); if (origin) - add_child_die (origin->die_parent, die); + { + /* Find the first non-abstract parent instance. */ + do + origin = origin->die_parent; + while (origin + && (origin->die_tag != DW_TAG_subprogram + || get_AT (origin, DW_AT_inline))); + if (origin) + add_child_die (origin, die); + else + add_child_die (comp_unit_die, die); + } else if (die == comp_unit_die) ; else if (seen_error ())