aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-12-08 09:05:32 -0800
committerNathan Sidwell <nathan@acm.org>2020-12-08 09:11:43 -0800
commitd04f3df82b737317c2759c314e28ee6243779252 (patch)
treee9a998b1d17a9b9cdb5b73ac46ad9105045b7ee7 /gcc/cp
parent005cff4e2ecbd5c4e2ef978fe4842fa3c8c79f47 (diff)
downloadgcc-d04f3df82b737317c2759c314e28ee6243779252.zip
gcc-d04f3df82b737317c2759c314e28ee6243779252.tar.gz
gcc-d04f3df82b737317c2759c314e28ee6243779252.tar.bz2
c++: Named module global initializers
C++ 20 modules adds some new rules about when the global initializers of imported modules run. They must run no later than before any initializers in the importer that appear after the import. To provide this, each named module emits an idempotent global initializer that calls the global initializer functions of its imports (these of course may call further import initializers). This is the machinery in our global-init emission to accomplish that, other than the actual emission of calls, which is in the module file. The naming of this global init is a new piece of the ABI. FWIW, the module's emitter does some optimization to avoid calling a direct import's initializer when it can determine thatr import is also indirect. gcc/cp/ * decl2.c (start_objects): Refactor and adjust for named module initializers. (finish_objects): Likewise. (generate_ctor_or_dtor_function): Likewise. * module.cc (module_initializer_kind) (module_add_import_initializers): Stubs.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/decl2.c126
-rw-r--r--gcc/cp/module.cc11
2 files changed, 92 insertions, 45 deletions
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 46069cb..e713033 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3636,35 +3636,45 @@ generate_tls_wrapper (tree fn)
static tree
start_objects (int method_type, int initp)
{
- tree body;
- tree fndecl;
- char type[14];
-
/* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
+ int module_init = 0;
+
+ if (initp == DEFAULT_INIT_PRIORITY && method_type == 'I')
+ module_init = module_initializer_kind ();
- if (initp != DEFAULT_INIT_PRIORITY)
+ tree name = NULL_TREE;
+ if (module_init > 0)
+ name = mangle_module_global_init (0);
+ else
{
- char joiner;
+ char type[14];
+ unsigned len = sprintf (type, "sub_%c", method_type);
+ if (initp != DEFAULT_INIT_PRIORITY)
+ {
+ char joiner = '_';
#ifdef JOINER
- joiner = JOINER;
-#else
- joiner = '_';
+ joiner = JOINER;
#endif
+ type[len++] = joiner;
+ sprintf (type + len, "%.5u", initp);
+ }
+ name = get_file_function_name (type);
+ }
- sprintf (type, "sub_%c%c%.5u", method_type, joiner, initp);
+ tree fntype = build_function_type (void_type_node, void_list_node);
+ tree fndecl = build_lang_decl (FUNCTION_DECL, name, fntype);
+ DECL_CONTEXT (fndecl) = FROB_CONTEXT (global_namespace);
+ if (module_init > 0)
+ {
+ SET_DECL_ASSEMBLER_NAME (fndecl, name);
+ TREE_PUBLIC (fndecl) = true;
+ determine_visibility (fndecl);
}
else
- sprintf (type, "sub_%c", method_type);
-
- fndecl = build_lang_decl (FUNCTION_DECL,
- get_file_function_name (type),
- build_function_type_list (void_type_node,
- NULL_TREE));
+ TREE_PUBLIC (fndecl) = 0;
start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
- TREE_PUBLIC (current_function_decl) = 0;
-
/* Mark as artificial because it's not explicitly in the user's
source code. */
DECL_ARTIFICIAL (current_function_decl) = 1;
@@ -3678,7 +3688,35 @@ start_objects (int method_type, int initp)
else
DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
- body = begin_compound_stmt (BCS_FN_BODY);
+ tree body = begin_compound_stmt (BCS_FN_BODY);
+
+ if (module_init > 0)
+ {
+ // 'static bool __in_chrg = false;
+ // if (__inchrg) return;
+ // __inchrg = true
+ tree var = build_lang_decl (VAR_DECL, in_charge_identifier,
+ boolean_type_node);
+ DECL_CONTEXT (var) = fndecl;
+ DECL_ARTIFICIAL (var) = true;
+ TREE_STATIC (var) = true;
+ pushdecl (var);
+ cp_finish_decl (var, NULL_TREE, false, NULL_TREE, 0);
+
+ tree if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (var, if_stmt);
+ finish_return_stmt (NULL_TREE);
+ finish_then_clause (if_stmt);
+ finish_if_stmt (if_stmt);
+
+ tree assign = build2 (MODIFY_EXPR, boolean_type_node,
+ var, boolean_true_node);
+ TREE_SIDE_EFFECTS (assign) = true;
+ finish_expr_stmt (assign);
+ }
+
+ if (module_init)
+ module_add_import_initializers ();
return body;
}
@@ -3689,11 +3727,9 @@ start_objects (int method_type, int initp)
static void
finish_objects (int method_type, int initp, tree body)
{
- tree fn;
-
/* Finish up. */
finish_compound_stmt (body);
- fn = finish_function (/*inline_p=*/false);
+ tree fn = finish_function (/*inline_p=*/false);
if (method_type == 'I')
{
@@ -4228,50 +4264,50 @@ static void
generate_ctor_or_dtor_function (bool constructor_p, int priority,
location_t *locus)
{
- char function_key;
- tree fndecl;
- tree body;
- size_t i;
-
input_location = *locus;
- /* ??? */
- /* Was: locus->line++; */
/* We use `I' to indicate initialization and `D' to indicate
destruction. */
- function_key = constructor_p ? 'I' : 'D';
+ char function_key = constructor_p ? 'I' : 'D';
/* We emit the function lazily, to avoid generating empty
global constructors and destructors. */
- body = NULL_TREE;
+ tree body = NULL_TREE;
- /* For Objective-C++, we may need to initialize metadata found in this module.
- This must be done _before_ any other static initializations. */
- if (c_dialect_objc () && (priority == DEFAULT_INIT_PRIORITY)
- && constructor_p && objc_static_init_needed_p ())
+ if (constructor_p && priority == DEFAULT_INIT_PRIORITY)
{
- body = start_objects (function_key, priority);
- objc_generate_static_init_call (NULL_TREE);
+ bool objc = c_dialect_objc () && objc_static_init_needed_p ();
+
+ /* We may have module initialization to emit and/or insert
+ before other intializations. */
+ if (module_initializer_kind () || objc)
+ body = start_objects (function_key, priority);
+
+ /* For Objective-C++, we may need to initialize metadata found
+ in this module. This must be done _before_ any other static
+ initializations. */
+ if (objc)
+ objc_generate_static_init_call (NULL_TREE);
}
/* Call the static storage duration function with appropriate
arguments. */
+ tree fndecl;
+ size_t i;
FOR_EACH_VEC_SAFE_ELT (ssdf_decls, i, fndecl)
{
/* Calls to pure or const functions will expand to nothing. */
if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
{
- tree call;
-
if (! body)
body = start_objects (function_key, priority);
- call = cp_build_function_call_nary (fndecl, tf_warning_or_error,
- build_int_cst (NULL_TREE,
- constructor_p),
- build_int_cst (NULL_TREE,
- priority),
- NULL_TREE);
+ tree call = cp_build_function_call_nary (fndecl, tf_warning_or_error,
+ build_int_cst (NULL_TREE,
+ constructor_p),
+ build_int_cst (NULL_TREE,
+ priority),
+ NULL_TREE);
finish_expr_stmt (call);
}
}
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 9a5d73af..705804a 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -83,6 +83,17 @@ mangle_module_fini ()
}
int
+module_initializer_kind ()
+{
+ return 0;
+}
+
+void
+module_add_import_initializers ()
+{
+}
+
+int
get_originating_module (tree, bool)
{
return 0;