static gfc_symbol* current_procedure_symbol = NULL;
+/* With -fcoarray=lib: For generating the registering call
+ of static coarrays. */
+static bool has_coarray_vars;
+static stmtblock_t caf_init_block;
+
+
/* List of static constructor functions. */
tree gfc_static_ctors;
/* Coarray run-time library function decls. */
tree gfor_fndecl_caf_init;
tree gfor_fndecl_caf_finalize;
+tree gfor_fndecl_caf_register;
tree gfor_fndecl_caf_critical;
tree gfor_fndecl_caf_end_critical;
tree gfor_fndecl_caf_sync_all;
SAVE_EXPLICIT. */
if (!sym->attr.use_assoc
&& (sym->attr.save != SAVE_NONE || sym->attr.data
- || (sym->value && sym->ns->proc_name->attr.is_main_program)))
+ || (sym->value && sym->ns->proc_name->attr.is_main_program)
+ || (gfc_option.coarray == GFC_FCOARRAY_LIB
+ && sym->attr.codimension && !sym->attr.allocatable)))
TREE_STATIC (decl) = 1;
if (sym->attr.volatile_)
nest = (procns->proc_name->backend_decl != current_function_decl)
&& !sym->attr.contained;
+ if (sym->attr.codimension && gfc_option.coarray == GFC_FCOARRAY_LIB
+ && GFC_TYPE_ARRAY_CAF_TOKEN (type) == NULL_TREE)
+ {
+ tree token;
+
+ token = gfc_create_var_np (pvoid_type_node, "caf_token");
+ GFC_TYPE_ARRAY_CAF_TOKEN (type) = token;
+ DECL_ARTIFICIAL (token) = 1;
+ TREE_STATIC (token) = 1;
+ gfc_add_decl_to_function (token);
+ }
+
for (dim = 0; dim < GFC_TYPE_ARRAY_RANK (type); dim++)
{
if (GFC_TYPE_ARRAY_LBOUND (type, dim) == NULL_TREE)
&& !(sym->attr.use_assoc && !intrinsic_array_parameter)
&& (sym->attr.save || sym->ns->proc_name->attr.is_main_program
|| gfc_option.flag_max_stack_var_size == 0
- || sym->attr.data || sym->ns->proc_name->attr.flavor == FL_MODULE))
+ || sym->attr.data || sym->ns->proc_name->attr.flavor == FL_MODULE)
+ && (gfc_option.coarray != GFC_FCOARRAY_LIB || !sym->attr.codimension))
{
/* Add static initializer. For procedures, it is only needed if
SAVE is specified otherwise they need to be reinitialized
gfor_fndecl_caf_finalize = gfc_build_library_function_decl (
get_identifier (PREFIX("caf_finalize")), void_type_node, 0);
+ gfor_fndecl_caf_register = gfc_build_library_function_decl_with_spec (
+ get_identifier (PREFIX("caf_register")), "...WWW", pvoid_type_node, 6,
+ size_type_node, integer_type_node, ppvoid_type_node, pint_type,
+ build_pointer_type (pchar_type_node), integer_type_node);
+
gfor_fndecl_caf_critical = gfc_build_library_function_decl (
get_identifier (PREFIX("caf_critical")), void_type_node, 0);
gfc_trans_deferred_array (sym, block);
}
}
- else
+ else if (gfc_option.coarray != GFC_FCOARRAY_LIB)
{
gfc_save_backend_locus (&loc);
gfc_set_backend_locus (&sym->declared_at);
rest_of_decl_compilation (length, 1, 0);
}
}
+
+ if (sym->attr.codimension && !sym->attr.dummy && !sym->attr.allocatable
+ && sym->attr.referenced && !sym->attr.use_assoc)
+ has_coarray_vars = true;
}
/* Emit debug information for USE statements. */
sym->attr.dimension, false))
return;
+ if (gfc_option.coarray == GFC_FCOARRAY_LIB && sym->attr.codimension)
+ return;
+
/* Create the decl for the variable or constant. */
decl = build_decl (input_location,
sym->attr.flavor == FL_PARAMETER ? CONST_DECL : VAR_DECL,
debug_hooks->global_decl (decl);
}
+
+static void
+generate_coarray_sym_init (gfc_symbol *sym)
+{
+ tree tmp, size, decl, token;
+
+ if (sym->attr.dummy || sym->attr.allocatable || !sym->attr.codimension
+ || sym->attr.use_assoc || !sym->attr.referenced)
+ return;
+
+ decl = sym->backend_decl;
+ TREE_USED(decl) = 1;
+ gcc_assert (GFC_ARRAY_TYPE_P (TREE_TYPE (decl)));
+
+ /* FIXME: Workaround for PR middle-end/49106, cf. also PR middle-end/49108
+ to make sure the variable is not optimized away. */
+ DECL_PRESERVE_P (DECL_CONTEXT (decl)) = 1;
+
+ size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (decl)));
+
+ if (GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)))
+ {
+ tmp = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (decl));
+ size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
+ fold_convert (size_type_node, tmp),
+ fold_convert (size_type_node, size));
+ }
+
+ gcc_assert (GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (decl)) != NULL_TREE);
+ token = gfc_build_addr_expr (ppvoid_type_node,
+ GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE(decl)));
+
+ tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_register, 6, size,
+ build_int_cst (integer_type_node, 0), /* type. */
+ token, null_pointer_node, /* token, stat. */
+ null_pointer_node, /* errgmsg, errmsg_len. */
+ build_int_cst (integer_type_node, 0));
+
+ gfc_add_modify (&caf_init_block, decl, fold_convert (TREE_TYPE (decl), tmp));
+
+
+ /* Handle "static" initializer. */
+ if (sym->value)
+ {
+ sym->attr.pointer = 1;
+ tmp = gfc_trans_assignment (gfc_lval_expr_from_sym (sym), sym->value,
+ true, false);
+ sym->attr.pointer = 0;
+ gfc_add_expr_to_block (&caf_init_block, tmp);
+ }
+}
+
+
+/* Generate constructor function to initialize static, nonallocatable
+ coarrays. */
+
+static void
+generate_coarray_init (gfc_namespace * ns __attribute((unused)))
+{
+ tree fndecl, tmp, decl, save_fn_decl;
+
+ save_fn_decl = current_function_decl;
+ push_function_context ();
+
+ tmp = build_function_type_list (void_type_node, NULL_TREE);
+ fndecl = build_decl (input_location, FUNCTION_DECL,
+ create_tmp_var_name ("_caf_init"), tmp);
+
+ DECL_STATIC_CONSTRUCTOR (fndecl) = 1;
+ SET_DECL_INIT_PRIORITY (fndecl, DEFAULT_INIT_PRIORITY);
+
+ decl = build_decl (input_location, RESULT_DECL, NULL_TREE, void_type_node);
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ DECL_CONTEXT (decl) = fndecl;
+ DECL_RESULT (fndecl) = decl;
+
+ pushdecl (fndecl);
+ current_function_decl = fndecl;
+ announce_function (fndecl);
+
+ rest_of_decl_compilation (fndecl, 0, 0);
+ make_decl_rtl (fndecl);
+ init_function_start (fndecl);
+
+ pushlevel (0);
+ gfc_init_block (&caf_init_block);
+
+ gfc_traverse_ns (ns, generate_coarray_sym_init);
+
+ DECL_SAVED_TREE (fndecl) = gfc_finish_block (&caf_init_block);
+ decl = getdecls ();
+
+ poplevel (1, 0, 1);
+ BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
+
+ DECL_SAVED_TREE (fndecl)
+ = build3_v (BIND_EXPR, decl, DECL_SAVED_TREE (fndecl),
+ DECL_INITIAL (fndecl));
+ dump_function (TDI_original, fndecl);
+
+ cfun->function_end_locus = input_location;
+ set_cfun (NULL);
+
+ if (decl_function_context (fndecl))
+ (void) cgraph_create_node (fndecl);
+ else
+ cgraph_finalize_function (fndecl, true);
+
+ pop_function_context ();
+ current_function_decl = save_fn_decl;
+}
+
+
/* Generate all the required code for module variables. */
void
/* Generate COMMON blocks. */
gfc_trans_common (ns);
+ has_coarray_vars = false;
+
/* Create decls for all the module variables. */
gfc_traverse_ns (ns, gfc_create_module_variable);
+ if (gfc_option.coarray == GFC_FCOARRAY_LIB && has_coarray_vars)
+ generate_coarray_init (ns);
+
cur_module = NULL;
gfc_trans_use_stmts (ns);
{
if (sym->attr.flavor == FL_VARIABLE)
{
+ if (sym->attr.codimension && !sym->attr.dummy && !sym->attr.allocatable
+ && sym->attr.referenced && !sym->attr.use_assoc)
+ has_coarray_vars = true;
+
if (!sym->attr.dummy && !sym->ns->proc_name->attr.entry_master)
generate_dependency_declarations (sym);
nonlocal_dummy_decls = NULL;
nonlocal_dummy_decl_pset = NULL;
+ has_coarray_vars = false;
generate_local_vars (ns);
+ if (gfc_option.coarray == GFC_FCOARRAY_LIB && has_coarray_vars)
+ generate_coarray_init (ns);
+
/* Keep the parent fake result declaration in module functions
or external procedures. */
if ((ns->parent && ns->parent->proc_name->attr.flavor == FL_MODULE)
}
current_function_decl = old_context;
- if (decl_function_context (fndecl))
+ if (decl_function_context (fndecl) && !gfc_option.coarray == GFC_FCOARRAY_LIB
+ && has_coarray_vars)
/* Register this function with cgraph just far enough to get it
- added to our parent's nested function list. */
+ added to our parent's nested function list.
+ If there are static coarrays in this function, the nested _caf_init
+ function has already called cgraph_create_node, which also created
+ the cgraph node for this function. */
(void) cgraph_create_node (fndecl);
else
cgraph_finalize_function (fndecl, true);
tree decl;
gcc_assert (saved_local_decls == NULL_TREE);
+ has_coarray_vars = false;
+
generate_local_vars (ns);
+ if (gfc_option.coarray == GFC_FCOARRAY_LIB && has_coarray_vars)
+ generate_coarray_init (ns);
+
decl = saved_local_decls;
while (decl)
{