From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1873) id 06EF0385828B; Mon, 15 Aug 2022 19:37:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 06EF0385828B MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Iain Buclaw To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-2058] d: Defer compiling inline definitions until after the module has finished. X-Act-Checkin: gcc X-Git-Author: Iain Buclaw X-Git-Refname: refs/heads/master X-Git-Oldrev: e206fecaac29f559f4990312b875604eb1ce3ef3 X-Git-Newrev: 8db5b71e212debcc4f6a17f80191ca187c307fcb Message-Id: <20220815193744.06EF0385828B@sourceware.org> Date: Mon, 15 Aug 2022 19:37:44 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Aug 2022 19:37:44 -0000 https://gcc.gnu.org/g:8db5b71e212debcc4f6a17f80191ca187c307fcb commit r13-2058-g8db5b71e212debcc4f6a17f80191ca187c307fcb Author: Iain Buclaw Date: Mon Aug 15 19:00:43 2022 +0200 d: Defer compiling inline definitions until after the 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. 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. Diff: --- 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