diff mbox series

[committed] d: Defer compiling inline definitions until after the module has finished.

Message ID 20220815204233.2831073-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Defer compiling inline definitions until after the module has finished. | expand

Commit Message

Iain Buclaw Aug. 15, 2022, 8:42 p.m. UTC
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 mbox series

Patch

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<Declaration *> *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<Declaration *> 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