Multipatch: * TR 29113: RANK() intrinsic * Patch from http://gcc.gnu.org/ml/fortran/2011-05/msg00123.html * minor libgfortran cleanup AND: * First part of a registering patch. TODO: - Make coarrays pointer - and assign malloced memory - Add token variable - LIB: Free memory in finalize diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 3b4967d..1f3be2d 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -472,6 +472,7 @@ enum gfc_isym_id GFC_ISYM_RANDOM_NUMBER, GFC_ISYM_RANDOM_SEED, GFC_ISYM_RANGE, + GFC_ISYM_RANK, GFC_ISYM_REAL, GFC_ISYM_RENAME, GFC_ISYM_REPEAT, diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c index c0eeb6d..dc9e756 100644 --- a/gcc/fortran/intrinsic.c +++ b/gcc/fortran/intrinsic.c @@ -2433,6 +2433,11 @@ add_functions (void) make_generic ("range", GFC_ISYM_RANGE, GFC_STD_F95); + add_sym_1 ("rank", GFC_ISYM_RANK, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di, + GFC_STD_F2008_TR, NULL, gfc_simplify_rank, NULL, + a, BT_REAL, dr, REQUIRED); + make_generic ("rank", GFC_ISYM_RANK, GFC_STD_F2008_TR); + add_sym_2 ("real", GFC_ISYM_REAL, CLASS_ELEMENTAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F77, gfc_check_real, gfc_simplify_real, gfc_resolve_real, a, BT_UNKNOWN, dr, REQUIRED, kind, BT_INTEGER, di, OPTIONAL); diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h index 033bae0..6d1c42b 100644 --- a/gcc/fortran/intrinsic.h +++ b/gcc/fortran/intrinsic.h @@ -345,6 +345,7 @@ gfc_expr *gfc_simplify_precision (gfc_expr *); gfc_expr *gfc_simplify_product (gfc_expr *, gfc_expr *, gfc_expr *); gfc_expr *gfc_simplify_radix (gfc_expr *); gfc_expr *gfc_simplify_range (gfc_expr *); +gfc_expr *gfc_simplify_rank (gfc_expr *); gfc_expr *gfc_simplify_real (gfc_expr *, gfc_expr *); gfc_expr *gfc_simplify_realpart (gfc_expr *); gfc_expr *gfc_simplify_repeat (gfc_expr *, gfc_expr *); diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index 804b31f..8b41e62 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -236,6 +236,7 @@ Some basic guidelines for editing this document: * @code{RANDOM_SEED}: RANDOM_SEED, Initialize a pseudo-random number sequence * @code{RAND}: RAND, Real pseudo-random number * @code{RANGE}: RANGE, Decimal exponent range +* @code{RANK} : RANK, Rank of a data object * @code{RAN}: RAN, Real pseudo-random number * @code{REAL}: REAL, Convert to real type * @code{RENAME}: RENAME, Rename a file @@ -10115,6 +10116,47 @@ See @code{PRECISION} for an example. +@node RANK +@section @code{RANK} --- Rank of a data object +@fnindex RANK +@cindex rank + +@table @asis +@item @emph{Description}: +@code{RANK(A)} returns the rank of a scalar or array data object. + +@item @emph{Standard}: +Technical Report (TR) 29113 + +@item @emph{Class}: +Inquiry function + +@item @emph{Syntax}: +@code{RESULT = RANGE(A)} + +@item @emph{Arguments}: +@multitable @columnfractions .15 .70 +@item @var{A} @tab can be of any type +@end multitable + +@item @emph{Return value}: +The return value is of type @code{INTEGER} and of the default integer +kind. For arrays, their rank is returned; for scalars zero is returned. + +@item @emph{Example}: +@smallexample +program test_real + integer :: a + real, allocatable :: b(:,::) + + print *, rank(a), rank(b) ! Prints: 0 3 +end program test_real +@end smallexample + +@end table + + + @node REAL @section @code{REAL} --- Convert to real type @fnindex REAL diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index 4c91563..79b383a 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -4822,6 +4822,13 @@ gfc_simplify_range (gfc_expr *e) gfc_expr * +gfc_simplify_rank (gfc_expr *e) +{ + return gfc_get_int_expr (gfc_default_integer_kind, &e->where, e->rank); +} + + +gfc_expr * gfc_simplify_real (gfc_expr *e, gfc_expr *k) { gfc_expr *result = NULL; diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 1a4ab39..78d65a6 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -2621,7 +2621,12 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym, gfc_se tmpse; if (ar->dimen == 0) - return; + { + gcc_assert (ar->codimen); + /* Use the actual tree type and not the wrapped coarray. */ + se->expr = fold_convert (TREE_TYPE (TREE_TYPE (se->expr)), se->expr); + return; + } /* Handle scalarized references separately. */ if (ar->type != AR_ELEMENT) diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index d771484..c5ab609 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -78,6 +78,11 @@ static gfc_namespace *module_namespace; static gfc_symbol* current_procedure_symbol = NULL; +/* For -fcoarray=lib's autoconstructor. */ +static bool has_coarray_vars; +static stmtblock_t caf_init_block; + + /* List of static constructor functions. */ tree gfc_static_ctors; @@ -114,6 +119,7 @@ tree gfor_fndecl_associated; /* 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; @@ -1403,7 +1409,8 @@ gfc_get_symbol_decl (gfc_symbol * sym) && !(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 @@ -3025,6 +3032,11 @@ gfc_build_builtin_function_decls (void) 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, pvoid_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); @@ -4066,6 +4078,9 @@ gfc_emit_parameter_debug_info (gfc_symbol *sym) 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, @@ -4200,6 +4215,9 @@ generate_local_decl (gfc_symbol * sym) { if (sym->attr.flavor == FL_VARIABLE) { + if (sym->attr.codimension && !sym->attr.dummy && !sym->attr.allocatable) + has_coarray_vars = true; + if (!sym->attr.dummy && !sym->ns->proc_name->attr.entry_master) generate_dependency_declarations (sym); @@ -4721,6 +4739,14 @@ create_main_function (tree fndecl) gfc_add_expr_to_block (&body, tmp); } + if (gfc_option.coarray == GFC_FCOARRAY_LIB) + { + tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all, + 2, null_pointer_node, + build_int_cst (integer_type_node, 0)); + gfc_add_expr_to_block (&body, tmp); + } + /* Call MAIN__(). */ tmp = build_call_expr_loc (input_location, fndecl, 0); @@ -4826,6 +4852,121 @@ gfc_generate_return (void) } +static void +generate_coarray_sym_init (gfc_symbol *sym) +{ + tree tmp, size, decl; + + if (sym->attr.dummy || sym->attr.allocatable || !sym->attr.codimension) + return; + + if (!sym->attr.referenced) + return; + + decl = sym->backend_decl; + gcc_assert (GFC_ARRAY_TYPE_P (TREE_TYPE (decl))); + + 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)); + } + + tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_register, 6, + size, + build_int_cst (integer_type_node, 0), /* type. */ + null_pointer_node, /* token. */ + null_pointer_node, /* stat. */ + null_pointer_node, /* errgmsg. */ + build_int_cst (integer_type_node, 0)); /* errmsg_len. */ + gfc_add_expr_to_block (&caf_init_block, tmp); + + /* "Static" initializer. */ + if (!sym->value) + return; + + tmp = gfc_trans_assignment (gfc_lval_expr_from_sym (sym), sym->value, true, false); + 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 old_context, fndecl, tmp, decl; + + old_context = current_function_decl; + + if (old_context) + { + push_function_context (); + saved_parent_function_decls = saved_function_decls; + saved_function_decls = NULL_TREE; + } + + 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); + TREE_USED (fndecl) = 1; + + 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, 1, 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 (old_context) + { + pop_function_context (); + saved_function_decls = saved_parent_function_decls; + } + current_function_decl = old_context; + + if (decl_function_context (fndecl)) + (void) cgraph_create_node (fndecl); + else + cgraph_finalize_function (fndecl, true); +} + + /* Generate code for a function. */ void @@ -4897,8 +5038,12 @@ gfc_generate_function_code (gfc_namespace * ns) 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) diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index 24fdcf3..1165926 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -1100,8 +1100,16 @@ gfc_get_element_type (tree type) { if (TREE_CODE (type) == POINTER_TYPE) type = TREE_TYPE (type); - gcc_assert (TREE_CODE (type) == ARRAY_TYPE); - element = TREE_TYPE (type); + if (GFC_TYPE_ARRAY_RANK (type) == 0) + { + gcc_assert (GFC_TYPE_ARRAY_CORANK (type) > 0); + element = type; + } + else + { + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); + element = TREE_TYPE (type); + } } else { @@ -1412,7 +1420,13 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed, /* We don't use build_array_type because this does not include include lang-specific information (i.e. the bounds of the array) when checking for duplicates. */ - type = make_node (ARRAY_TYPE); + if (as->rank) + type = make_node (ARRAY_TYPE); + else + { + type = build_variant_type_copy (etype); + TREE_TYPE (type) = etype; + } GFC_ARRAY_TYPE_P (type) = 1; TYPE_LANG_SPECIFIC (type) @@ -1526,6 +1540,23 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed, build_qualified_type (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), TYPE_QUAL_RESTRICT); + if (as->rank == 0) + { + if (packed != PACKED_STATIC) + type = build_pointer_type (type); + + if (restricted) + type = build_qualified_type (type, TYPE_QUAL_RESTRICT); + + if (packed != PACKED_STATIC) + { + GFC_ARRAY_TYPE_P (type) = 1; + TYPE_LANG_SPECIFIC (type) = TYPE_LANG_SPECIFIC (TREE_TYPE (type)); + } + + return type; + } + if (known_stride) { mpz_sub_ui (stride, stride, 1); diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index 1d25cb0..fcbb850 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -316,6 +316,13 @@ gfc_build_array_ref (tree base, tree offset, tree decl) tree type = TREE_TYPE (base); tree tmp; + if (GFC_ARRAY_TYPE_P (type) && GFC_TYPE_ARRAY_RANK (type) == 0) + { + gcc_assert (GFC_TYPE_ARRAY_CORANK (type) > 0); + + return fold_convert (TREE_TYPE (type), base); + } + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); type = TREE_TYPE (type); diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 2b06d80..e9b07b6 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -617,6 +617,7 @@ extern GTY(()) tree gfor_fndecl_associated; /* Coarray run-time library function decls. */ extern GTY(()) tree gfor_fndecl_caf_init; extern GTY(()) tree gfor_fndecl_caf_finalize; +extern GTY(()) tree gfor_fndecl_caf_register; extern GTY(()) tree gfor_fndecl_caf_critical; extern GTY(()) tree gfor_fndecl_caf_end_critical; extern GTY(()) tree gfor_fndecl_caf_sync_all; diff --git a/libgfortran/caf/mpi.c b/libgfortran/caf/mpi.c index 9b7bb33..8b1f424 100644 --- a/libgfortran/caf/mpi.c +++ b/libgfortran/caf/mpi.c @@ -80,7 +80,6 @@ _gfortran_caf_register (ptrdiff_t size, caf_register_t type __attribute__ ((unused)), void **token) { - *token = NULL; return malloc (size); } diff --git a/libgfortran/caf/single.c b/libgfortran/caf/single.c index c5c66b4..c9cbc7f 100644 --- a/libgfortran/caf/single.c +++ b/libgfortran/caf/single.c @@ -55,9 +55,8 @@ _gfortran_caf_finalize (void) void * _gfortran_caf_register (ptrdiff_t size, caf_register_t type __attribute__ ((unused)), - void **token) + void **token __attribute__ ((unused))) { - *token = NULL; return malloc (size); } diff --git a/libgfortran/runtime/stop.c b/libgfortran/runtime/stop.c index 4c3a0f9..912dd54 100644 --- a/libgfortran/runtime/stop.c +++ b/libgfortran/runtime/stop.c @@ -67,8 +67,7 @@ stop_string (const char *string, GFC_INTEGER_4 len) if (string) { estr_write ("STOP "); - ssize_t w = write (STDERR_FILENO, string, len); - (void) sizeof (w); /* Avoid compiler warning about not using w. */ + (void) write (STDERR_FILENO, string, len); estr_write ("\n"); } exit (0); @@ -88,8 +87,7 @@ void error_stop_string (const char *string, GFC_INTEGER_4 len) { estr_write ("ERROR STOP "); - ssize_t w = write (STDERR_FILENO, string, len); - (void) sizeof (w); /* Avoid compiler warning about not using w. */ + (void) write (STDERR_FILENO, string, len); estr_write ("\n"); exit (1);