From patchwork Mon Aug 15 20:42:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 56762 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 721053858298 for ; Mon, 15 Aug 2022 20:43:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 721053858298 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1660596187; bh=8T8yv/J/vYL7HOHSBtUA3NZigQS0479nZepgvrCfbr0=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=rEvXlK9gEZL0P3NYE4wgUqyEgqPk852kmk16RxvWhfhEDISo77HWDsz936BzGnUdB Cb4bPkzEbL1LGyIsyfnXhIYzxw+n7S0QcSsxQdHE4Ok4me+4LCzwv581X/zf+xGink x/wXxU7+yjcIrkZpX9CHcRh0Zcw/DT6y1K/0l+CQ= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [IPv6:2001:67c:2050:0:465::101]) by sourceware.org (Postfix) with ESMTPS id 7F34F3858C2F for ; Mon, 15 Aug 2022 20:42:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7F34F3858C2F Received: from smtp2.mailbox.org (smtp2.mailbox.org [IPv6:2001:67c:2050:b231:465::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4M65nR62rmz9sT1; Mon, 15 Aug 2022 22:42:35 +0200 (CEST) To: gcc-patches@gcc.gnu.org Subject: [committed] d: Defer compiling inline definitions until after the module has finished. Date: Mon, 15 Aug 2022 22:42:33 +0200 Message-Id: <20220815204233.2831073-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4M65nR62rmz9sT1 X-Spam-Status: No, score=-13.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch is a follow-up to r13-2002 and r12-8673 (PR d/106563), that instead pushes inline definitions onto a deferred list to be compiled after the current module has finished. This is to prevent the case of when generating the methods of a struct type, we don't accidentally emit an inline function that references it, as the outer struct itself would still be incomplete. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, committed to mainline, and backported to the releases/gcc-12 branch. Regards, Iain. --- gcc/d/ChangeLog: * d-tree.h (d_defer_declaration): Declare. * decl.cc (function_needs_inline_definition_p): Defer checking DECL_UNINLINABLE and DECL_DECLARED_INLINE_P. (maybe_build_decl_tree): Call d_defer_declaration instead of build_decl_tree. * modules.cc (deferred_inline_declarations): New variable. (build_module_tree): Set deferred_inline_declarations and a handle declarations pushed to it. (d_defer_declaration): New function. --- gcc/d/d-tree.h | 1 + gcc/d/decl.cc | 22 +++++++++++----------- gcc/d/modules.cc | 20 ++++++++++++++++++++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 809a242ea93..4885cfe2b15 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -673,6 +673,7 @@ extern tree maybe_expand_intrinsic (tree); extern void build_module_tree (Module *); extern tree d_module_context (void); extern void register_module_decl (Declaration *); +extern void d_defer_declaration (Declaration *); extern void d_finish_compilation (tree *, int); /* In runtime.cc. */ diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index 0131b01dcc9..e91aee30845 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -1046,18 +1046,10 @@ function_needs_inline_definition_p (FuncDeclaration *fd) if (!DECL_EXTERNAL (fd->csym)) return false; - /* Non-inlineable functions are always external. */ - if (DECL_UNINLINABLE (fd->csym)) - return false; - /* No function body available for inlining. */ if (!fd->fbody) return false; - /* Ignore functions that aren't decorated with `pragma(inline)'. */ - if (fd->inlining != PINLINE::always) - return false; - /* These functions are tied to the module they are defined in. */ if (fd->isFuncLiteralDeclaration () || fd->isUnitTestDeclaration () @@ -1070,6 +1062,14 @@ function_needs_inline_definition_p (FuncDeclaration *fd) if (function_defined_in_root_p (fd)) return false; + /* Non-inlineable functions are always external. */ + if (DECL_UNINLINABLE (fd->csym)) + return false; + + /* Ignore functions that aren't decorated with `pragma(inline)'. */ + if (!DECL_DECLARED_INLINE_P (fd->csym)) + return false; + /* Weak functions cannot be inlined. */ if (lookup_attribute ("weak", DECL_ATTRIBUTES (fd->csym))) return false; @@ -1081,8 +1081,8 @@ function_needs_inline_definition_p (FuncDeclaration *fd) return true; } -/* If the variable or function declaration in DECL needs to be defined, call - build_decl_tree on it now before returning its back-end symbol. */ +/* If the variable or function declaration in DECL needs to be defined, add it + to the list of deferred declarations to build later. */ static tree maybe_build_decl_tree (Declaration *decl) @@ -1103,7 +1103,7 @@ maybe_build_decl_tree (Declaration *decl) if (function_needs_inline_definition_p (fd)) { DECL_EXTERNAL (fd->csym) = 0; - build_decl_tree (fd); + d_defer_declaration (fd); } } diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc index edc79122365..0aac8fe3545 100644 --- a/gcc/d/modules.cc +++ b/gcc/d/modules.cc @@ -121,6 +121,9 @@ static module_info *current_testing_module; static Module *current_module_decl; +/* Any inline symbols that were deferred during codegen. */ +vec *deferred_inline_declarations; + /* Returns an internal function identified by IDENT. This is used by both module initialization and dso handlers. */ @@ -724,6 +727,9 @@ build_module_tree (Module *decl) current_testing_module = &mitest; current_module_decl = decl; + vec deferred_decls = vNULL; + deferred_inline_declarations = &deferred_decls; + /* Layout module members. */ if (decl->members) { @@ -811,9 +817,14 @@ build_module_tree (Module *decl) layout_moduleinfo (decl); } + /* Process all deferred functions after finishing module. */ + for (size_t i = 0; i < deferred_decls.length (); ++i) + build_decl_tree (deferred_decls[i]); + current_moduleinfo = NULL; current_testing_module = NULL; current_module_decl = NULL; + deferred_inline_declarations = NULL; } /* Returns the current function or module context for the purpose @@ -888,6 +899,15 @@ register_module_decl (Declaration *d) } } +/* Add DECL as a declaration to emit at the end of the current module. */ + +void +d_defer_declaration (Declaration *decl) +{ + gcc_assert (deferred_inline_declarations != NULL); + deferred_inline_declarations->safe_push (decl); +} + /* Wrapup all global declarations and start the final compilation. */ void