public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* c++: Adjust module initializer calling emission
@ 2022-06-10 16:28 Nathan Sidwell
  0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2022-06-10 16:28 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 294 bytes --]


We special-case emitting the calls of module initializer functions. 
It's simpler to just emit a static fn do do that, and add it onto the 
front of the global init fn chain.  We can also move the calculation of 
the set of initializers to call to the point of use.

nathan

-- 
Nathan Sidwell

[-- Attachment #2: 0001-c-Adjust-module-initializer-calling-emission.patch --]
[-- Type: text/x-patch, Size: 11559 bytes --]

From 8834d2d35fcc229c00e2e06e8be8b052c803d8cd Mon Sep 17 00:00:00 2001
From: Nathan Sidwell <nathan@acm.org>
Date: Fri, 10 Jun 2022 05:22:21 -0700
Subject: [PATCH] c++: Adjust module initializer calling emission

We special-case emitting the calls of module initializer functions.  It's
simpler to just emit a static fn do do that, and add it onto the front of
the global init fn chain.  We can also move the calculation of the set of
initializers to call to the point of use.

	gcc/cp/
	* cp-tree.h (module_has_import_init): Rename to ...
	(module_determined_import_inits): ... here.
	* decl2.cc (start_objects): Do not handle module initializers
	here.
	(c_parse_final_cleanups): Generate a separate module
	initializer calling function and add it to the list.  Shrink
	the c-lang region.
	* module.cc (num_init_calls_needed): Delete.
	 (module_has_import_init): Rename to ...
	(module_determined_import_inits): ... here. Do the
	calculation here ...
	(finish_module_processing): ... rather than here.
	(module_add_import_initializers): Reformat.

	gcc/testsuite/
	* g++.dg/modules/init-3_a.C: New.
	* g++.dg/modules/init-3_b.C: New.
	* g++.dg/modules/init-3_c.C: New.
---
 gcc/cp/cp-tree.h                        |   2 +-
 gcc/cp/decl2.cc                         |  47 +++++-----
 gcc/cp/module.cc                        | 110 +++++++++++-------------
 gcc/testsuite/g++.dg/modules/init-3_a.C |  17 ++++
 gcc/testsuite/g++.dg/modules/init-3_b.C |   6 ++
 gcc/testsuite/g++.dg/modules/init-3_c.C |  17 ++++
 6 files changed, 117 insertions(+), 82 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/init-3_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/init-3_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/init-3_c.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a5d93282167..f1294dac7d5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7180,7 +7180,7 @@ extern module_state *get_module (tree name, module_state *parent = NULL,
 extern bool module_may_redeclare (tree decl);
 
 extern bool module_global_init_needed ();
-extern bool module_has_import_inits ();
+extern bool module_determine_import_inits ();
 extern void module_add_import_initializers ();
 
 /* Where the namespace-scope decl was originally declared.  */
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 9de9a7a4f8a..ff1c36745cf 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -3903,8 +3903,7 @@ start_objects (bool initp, unsigned priority, bool has_body)
 
   tree body = begin_compound_stmt (BCS_FN_BODY);
 
-  bool has_import_inits = default_init && module_has_import_inits ();
-  if (is_module_init && (has_import_inits || has_body))
+  if (is_module_init && has_body)
     {
       // If the function is going to be empty, don't emit idempotency.
       // 'static bool __in_chrg = false;
@@ -3930,9 +3929,6 @@ start_objects (bool initp, unsigned priority, bool has_body)
       finish_expr_stmt (assign);
     }
 
-  if (has_import_inits)
-    module_add_import_initializers ();
-
   return body;
 }
 
@@ -5195,6 +5191,12 @@ c_parse_final_cleanups (void)
 
   maybe_warn_sized_delete ();
 
+  // Place the init fns in the right order.  We need to do this now,
+  // so that any module init will go at the start.
+  if (static_init_fini_fns[true])
+    for (auto iter : *static_init_fini_fns[true])
+      iter.second = nreverse (iter.second);
+  
   /* Then, do the Objective-C stuff.  This is where all the
      Objective-C module stuff gets generated (symtab,
      class/protocol/selector lists etc).  This must be done after C++
@@ -5203,11 +5205,18 @@ c_parse_final_cleanups (void)
   if (c_dialect_objc ())
     objc_write_global_declarations ();
 
-  /* We give C linkage to static constructors and destructors.  */
-  push_lang_context (lang_name_c);
+  if (module_determine_import_inits ())
+    {
+      input_location = locus_at_end_of_parsing;
+      tree body = start_partial_init_fini_fn (true, DEFAULT_INIT_PRIORITY,
+					      ssdf_count++);
+      module_add_import_initializers ();
+      input_location = locus_at_end_of_parsing;
+      finish_partial_init_fini_fn (body);
+    }
 
   if ((c_dialect_objc () && objc_static_init_needed_p ())
-      || module_global_init_needed () || module_has_import_inits ())
+      || module_global_init_needed ())
     {
       // Make sure there's a default priority entry.
       if (!static_init_fini_fns[true])
@@ -5216,32 +5225,24 @@ c_parse_final_cleanups (void)
     } 
 
   /* Generate initialization and destruction functions for all
-     priorities for which they are required.  */
+     priorities for which they are required.  They have C-language
+     linkage.  */
+  push_lang_context (lang_name_c);
   for (unsigned initp = 2; initp--;)
     if (static_init_fini_fns[initp])
       {
 	for (auto iter : *static_init_fini_fns[initp])
-	  {
-	    tree fns = iter.second;
-	    // The list of functions was constructed in reverse
-	    // order, which we only want for dtors.
-	    if (initp)
-	      fns = nreverse (fns);
-	    generate_ctor_or_dtor_function (initp, iter.first, fns,
-					    locus_at_end_of_parsing);
-	  }
+	  generate_ctor_or_dtor_function (initp, iter.first, iter.second,
+					  locus_at_end_of_parsing);
 	static_init_fini_fns[initp] = nullptr;
       }
-  
+  pop_lang_context ();
+
   fini_modules ();
 
   /* Generate any missing aliases.  */
   maybe_apply_pending_pragma_weaks ();
 
-  /* We're done with static constructors, so we can go back to "C++"
-     linkage now.  */
-  pop_lang_context ();
-
   if (flag_vtable_verify)
     {
       vtv_recover_class_info ();
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 7e36996c0fc..2b1877ea82e 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -3783,9 +3783,6 @@ static unsigned loaded_clusters;
 /* What the current TU is.  */
 unsigned module_kind;
 
-/* Number of global init calls needed.  */
-unsigned num_init_calls_needed = 0;
-
 /* Global trees.  */
 static const std::pair<tree *, unsigned> global_tree_arys[] =
   {
@@ -19035,12 +19032,43 @@ module_global_init_needed ()
   return module_has_cmi_p () && !header_module_p ();
 }
 
-/* Return true IFF we have import global inits to call.  */
+/* Calculate which, if any, import initializers need calling.  */
 
 bool
-module_has_import_inits ()
+module_determine_import_inits ()
 {
-  return bool (num_init_calls_needed);
+  if (!modules || header_module_p ())
+    return false;
+
+  /* Determine call_init_p.  We need the same bitmap allocation
+     scheme as for the imports member.  */
+  function_depth++; /* Disable GC.  */
+  bitmap indirect_imports (BITMAP_GGC_ALLOC ());
+
+  bool any = false;
+
+  /* Because indirect imports are before their direct import, and
+     we're scanning the array backwards, we only need one pass!  */
+  for (unsigned ix = modules->length (); --ix;)
+    {
+      module_state *import = (*modules)[ix];
+
+      if (!import->is_header ()
+	  && !bitmap_bit_p (indirect_imports, ix))
+	{
+	  /* Everything this imports is therefore indirectly
+	     imported.  */
+	  bitmap_ior_into (indirect_imports, import->imports);
+	  /* We don't have to worry about the self-import bit,
+	     because of the single pass.  */
+
+	  import->call_init_p = true;
+	  any = true;
+	}
+    }
+  function_depth--;
+
+  return any;
 }
 
 /* Emit calls to each direct import's global initializer.  Including
@@ -19054,35 +19082,30 @@ module_has_import_inits ()
 void
 module_add_import_initializers ()
 {
-  unsigned calls = 0;
-  if (modules)
+  if (!modules || header_module_p ())
+    return;
+
+  tree fntype = build_function_type (void_type_node, void_list_node);
+  releasing_vec args;  // There are no args
+
+  for (unsigned ix = modules->length (); --ix;)
     {
-      tree fntype = build_function_type (void_type_node, void_list_node);
-      releasing_vec args;  // There are no args
-
-      for (unsigned ix = modules->length (); --ix;)
+      module_state *import = (*modules)[ix];
+      if (import->call_init_p)
 	{
-	  module_state *import = (*modules)[ix];
-	  if (import->call_init_p)
-	    {
-	      tree name = mangle_module_global_init (ix);
-	      tree fndecl = build_lang_decl (FUNCTION_DECL, name, fntype);
+	  tree name = mangle_module_global_init (ix);
+	  tree fndecl = build_lang_decl (FUNCTION_DECL, name, fntype);
 
-	      DECL_CONTEXT (fndecl) = FROB_CONTEXT (global_namespace);
-	      SET_DECL_ASSEMBLER_NAME (fndecl, name);
-	      TREE_PUBLIC (fndecl) = true;
-	      determine_visibility (fndecl);
+	  DECL_CONTEXT (fndecl) = FROB_CONTEXT (global_namespace);
+	  SET_DECL_ASSEMBLER_NAME (fndecl, name);
+	  TREE_PUBLIC (fndecl) = true;
+	  determine_visibility (fndecl);
 
-	      tree call = cp_build_function_call_vec (fndecl, &args,
-						      tf_warning_or_error);
-	      finish_expr_stmt (call);
-	      
-	      calls++;
-	    }
+	  tree call = cp_build_function_call_vec (fndecl, &args,
+						  tf_warning_or_error);
+	  finish_expr_stmt (call);
 	}
     }
-
-  gcc_checking_assert (calls == num_init_calls_needed);
 }
 
 /* NAME & LEN are a preprocessed header name, possibly including the
@@ -19951,35 +19974,6 @@ finish_module_processing (cpp_reader *reader)
 		       (available_clusters + !available_clusters));
       dump.pop (n);
     }
-
-  if (modules && !header_module_p ())
-    {
-      /* Determine call_init_p.  We need the same bitmap allocation
-         scheme as for the imports member.  */
-      function_depth++; /* Disable GC.  */
-      bitmap indirect_imports (BITMAP_GGC_ALLOC ());
-
-      /* Because indirect imports are before their direct import, and
-	 we're scanning the array backwards, we only need one pass!  */
-      for (unsigned ix = modules->length (); --ix;)
-	{
-	  module_state *import = (*modules)[ix];
-
-	  if (!import->is_header ()
-	      && !bitmap_bit_p (indirect_imports, ix))
-	    {
-	      /* Everything this imports is therefore indirectly
-		 imported.  */
-	      bitmap_ior_into (indirect_imports, import->imports);
-	      /* We don't have to worry about the self-import bit,
-		 because of the single pass.  */
-
-	      import->call_init_p = true;
-	      num_init_calls_needed++;
-	    }
-	}
-      function_depth--;
-    }
 }
 
 void
diff --git a/gcc/testsuite/g++.dg/modules/init-3_a.C b/gcc/testsuite/g++.dg/modules/init-3_a.C
new file mode 100644
index 00000000000..f0e27ec04cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/init-3_a.C
@@ -0,0 +1,17 @@
+// { dg-module-do run }
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+module;
+# 5 __FILE__ 1
+extern int counter;
+# 7 "" 2
+export module One;
+
+export class Dyn
+{
+  int i;
+public:
+  Dyn () : i (++counter) {}
+  operator int () const { return i; }
+};
+
+export Dyn one;
diff --git a/gcc/testsuite/g++.dg/modules/init-3_b.C b/gcc/testsuite/g++.dg/modules/init-3_b.C
new file mode 100644
index 00000000000..a4e0036e668
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/init-3_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+
+export module Two;
+import One;
+
+export Dyn two;
diff --git a/gcc/testsuite/g++.dg/modules/init-3_c.C b/gcc/testsuite/g++.dg/modules/init-3_c.C
new file mode 100644
index 00000000000..bb4635a6c90
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/init-3_c.C
@@ -0,0 +1,17 @@
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+
+import One;
+int counter = 0;
+Dyn three;
+import Two;
+
+int main ()
+{
+  if (one != 1)
+    return 1;
+  if (two != 2)
+    return 2;
+  if (three != 3)
+    return 3;
+  return 0;
+}
-- 
2.30.2


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-10 16:28 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-10 16:28 c++: Adjust module initializer calling emission Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).