libcaf.h: Add caf_reference_type.
libgfortran/ChangeLog: 2016-09-19 Andre Vehreschild <vehre@gcc.gnu.org> * caf/libcaf.h: Add caf_reference_type. * caf/mpi.c: Adapted signature of caf_register(). * caf/single.c (struct caf_single_token): Added to keep the pointer to the memory registered and array descriptor. (caf_internal_error): Added convenience interface. (_gfortran_caf_register): Adapted to work with caf_single_token and return memory in the array descriptor. (_gfortran_caf_deregister): Same. (assign_char1_from_char4): Fixed style. (convert_type): Fixed incorrect conversion. (_gfortran_caf_get): Adapted to work with caf_single_token. (_gfortran_caf_send): Same. (_gfortran_caf_sendget): Same. (copy_data): Added to stop repeating it in all _by_ref functions. (get_for_ref): Recursive getting of coarray data using a chain of references. (_gfortran_caf_get_by_ref): Driver for computing the memory needed for the get and checking properties of the operation. (send_by_ref): Same as get_for_ref but for sending data. (_gfortran_caf_send_by_ref): Same like caf_get_by_ref but for sending. (_gfortran_caf_sendget_by_ref): Uses get_by_ref and send_by_ref to implement sendget for reference chains. (_gfortran_caf_atomic_define): Adapted to work with caf_single_token. (_gfortran_caf_atomic_ref): Likewise. (_gfortran_caf_atomic_cas): Likewise. (_gfortran_caf_atomic_op): Likewise. (_gfortran_caf_event_post): Likewise. (_gfortran_caf_event_wait): Likewise. (_gfortran_caf_event_query): Likewise. (_gfortran_caf_lock): Likewise. (_gfortran_caf_unlock): Likewise. gcc/testsuite/ChangeLog: 2016-09-19 Andre Vehreschild <vehre@gcc.gnu.org> * gfortran.dg/coarray/alloc_comp_4.f90: New test. * gfortran.dg/coarray_38.f90: * gfortran.dg/coarray_alloc_comp_1.f08: New test. * gfortran.dg/coarray_alloc_comp_2.f08: New test. * gfortran.dg/coarray_allocate_7.f08: New test. * gfortran.dg/coarray_allocate_8.f08: New test. * gfortran.dg/coarray_allocate_9.f08: New test. * gfortran.dg/coarray_lib_alloc_1.f90: Adapted scan-tree-dumps to expect new caf_register. * gfortran.dg/coarray_lib_alloc_2.f90: Same. * gfortran.dg/coarray_lib_alloc_3.f90: Same. * gfortran.dg/coarray_lib_comm_1.f90: Adapted scan-tree-dumps to expect get_by_refs. * gfortran.dg/coarray_lib_token_3.f90: Same as for coarray_lib_alloc2. * gfortran.dg/coarray_lock_7.f90: Same. * gfortran.dg/coarray_poly_5.f90: Same. * gfortran.dg/coarray_poly_6.f90: Same. * gfortran.dg/coarray_poly_7.f90: Same. * gfortran.dg/coarray_poly_8.f90: Same. * gfortran.dg/coindexed_1.f90: Changed errors expected. gcc/fortran/ChangeLog: 2016-09-19 Andre Vehreschild <vehre@gcc.gnu.org> * expr.c (gfc_check_assign): Added flag to control whether datatype conversion is allowed. * gfortran.h: Added caf-token-tree to gfc_component. Changed prototypes mostly to add whether datatype conversion is allowed. * gfortran.texi: Added documentation for the caf_reference_t and the caf_*_by_ref function. * primary.c (caf_variable_attr): Similar to gfc_variable_attr but focused on the needs of coarrays. (gfc_caf_attr): Same. * resolve.c (resolve_ordinary_assign): Set the conversion allowed flag when not in a coarray. * trans-array.c (gfc_array_init_size): Moved setting of array descriptor's datatype before the alloc, because caf_register needs it. (gfc_array_allocate): Changed notion of whether an array is a coarray. (gfc_array_deallocate): Same. (gfc_alloc_allocatable_for_assignment): Added setting of coarray's array descriptor datatype before the register. And using deregister/ register to mimmick a realloc for coarrays. * trans-decl.c (gfc_build_builtin_function_decls): Corrected signatures of old caf-functions and added signature definitions of the _by_ref ones. (generate_coarray_sym_init): Adapted to new caf_register signature. * trans-expr.c (gfc_conv_scalar_to_descriptor): Make sure a constant is translated to an lvalue expression before use in an array descriptor. (gfc_get_ultimate_alloc_ptr_comps_caf_token): New function. Get the last allocatable component's coarray token. (gfc_get_tree_for_caf_expr): For top-level object get the coarray token and check for unsupported features. (gfc_get_caf_token_offset): Getting the offset might procude new statements, which now are stored in the pre and post of the current se. (gfc_caf_get_image_index): For this image return a call to caf_this_image. (expr_may_alias_variables): Check that the result is set for testing its properties. (alloc_scalar_allocatable_for_assignment): Added auto allocation of coarray components. (gfc_trans_assignment_1): Rewrite an assign to a coarray object to be a sendget. * trans-intrinsic.c (conv_caf_vector_subscript_elem): Corrected wrong comment. (compute_component_offset): Compute the correct offset a structure member. (conv_expr_ref_to_caf_ref): Convert to a chain of refs into caf_references. (gfc_conv_intrinsic_caf_get): Call caf_get_by_ref instead of caf_get. (conv_caf_send): Call caf_*_by_ref for coarrays that need reallocation. (gfc_conv_intrinsic_function): Adapted to new signuature of the caf drivers. (conv_intrinsic_atomic_op): Add pre and post statements correctly. (conv_intrinsic_atomic_ref): Same. (conv_intrinsic_atomic_cas): Same. (conv_intrinsic_event_query): Same. * trans-stmt.c (gfc_trans_lock_unlock): Same. (gfc_trans_event_post_wait): Same. (gfc_trans_allocate): Support allocation of allocatable coarrays. (gfc_trans_deallocate): And there deallocation. * trans-types.c (gfc_typenode_for_spec): Added flag to control whether a component is part of coarray. When so, then add space to store a coarray token. (gfc_build_array_type): Same. (gfc_get_array_descriptor_base): Same. (gfc_get_array_type_bounds): Same. (gfc_sym_type): Same. (gfc_get_derived_type): Same. (gfc_get_caf_reference_type): Declare the caf_reference_type. * trans-types.h: Prototype changes only. * trans.c (gfc_allocate_using_lib): Use the updated caf_register signature. (gfc_allocate_allocatable): Same. (gfc_deallocate_with_status): Same. * trans.h: Defined the runtime types for caf_reference_t and the enums. From-SVN: r240231
This commit is contained in:
parent
e79e6763c6
commit
3c9f5092c6
@ -1,3 +1,80 @@
|
||||
2016-09-19 Andre Vehreschild <vehre@gcc.gnu.org>
|
||||
|
||||
PR fortran/71952
|
||||
* expr.c (gfc_check_assign): Added flag to control whether datatype
|
||||
conversion is allowed.
|
||||
* gfortran.h: Added caf-token-tree to gfc_component. Changed
|
||||
prototypes mostly to add whether datatype conversion is allowed.
|
||||
* gfortran.texi: Added documentation for the caf_reference_t and the
|
||||
caf_*_by_ref function.
|
||||
* primary.c (caf_variable_attr): Similar to gfc_variable_attr but
|
||||
focused on the needs of coarrays.
|
||||
(gfc_caf_attr): Same.
|
||||
* resolve.c (resolve_ordinary_assign): Set the conversion allowed
|
||||
flag when not in a coarray.
|
||||
* trans-array.c (gfc_array_init_size): Moved setting of array
|
||||
descriptor's datatype before the alloc, because caf_register needs it.
|
||||
(gfc_array_allocate): Changed notion of whether an array is a coarray.
|
||||
(gfc_array_deallocate): Same.
|
||||
(gfc_alloc_allocatable_for_assignment): Added setting of coarray's
|
||||
array descriptor datatype before the register. And using deregister/
|
||||
register to mimmick a realloc for coarrays.
|
||||
* trans-decl.c (gfc_build_builtin_function_decls): Corrected signatures
|
||||
of old caf-functions and added signature definitions of the _by_ref
|
||||
ones.
|
||||
(generate_coarray_sym_init): Adapted to new caf_register signature.
|
||||
* trans-expr.c (gfc_conv_scalar_to_descriptor): Make sure a constant
|
||||
is translated to an lvalue expression before use in an array
|
||||
descriptor.
|
||||
(gfc_get_ultimate_alloc_ptr_comps_caf_token): New function. Get the
|
||||
last allocatable component's coarray token.
|
||||
(gfc_get_tree_for_caf_expr): For top-level object get the coarray
|
||||
token and check for unsupported features.
|
||||
(gfc_get_caf_token_offset): Getting the offset might procude new
|
||||
statements, which now are stored in the pre and post of the current se.
|
||||
(gfc_caf_get_image_index): For this image return a call to
|
||||
caf_this_image.
|
||||
(expr_may_alias_variables): Check that the result is set for testing
|
||||
its properties.
|
||||
(alloc_scalar_allocatable_for_assignment): Added auto allocation of
|
||||
coarray components.
|
||||
(gfc_trans_assignment_1): Rewrite an assign to a coarray object to
|
||||
be a sendget.
|
||||
* trans-intrinsic.c (conv_caf_vector_subscript_elem): Corrected
|
||||
wrong comment.
|
||||
(compute_component_offset): Compute the correct offset a structure
|
||||
member.
|
||||
(conv_expr_ref_to_caf_ref): Convert to a chain of refs into
|
||||
caf_references.
|
||||
(gfc_conv_intrinsic_caf_get): Call caf_get_by_ref instead of caf_get.
|
||||
(conv_caf_send): Call caf_*_by_ref for coarrays that need
|
||||
reallocation.
|
||||
(gfc_conv_intrinsic_function): Adapted to new signuature of the caf
|
||||
drivers.
|
||||
(conv_intrinsic_atomic_op): Add pre and post statements correctly.
|
||||
(conv_intrinsic_atomic_ref): Same.
|
||||
(conv_intrinsic_atomic_cas): Same.
|
||||
(conv_intrinsic_event_query): Same.
|
||||
* trans-stmt.c (gfc_trans_lock_unlock): Same.
|
||||
(gfc_trans_event_post_wait): Same.
|
||||
(gfc_trans_allocate): Support allocation of allocatable coarrays.
|
||||
(gfc_trans_deallocate): And there deallocation.
|
||||
* trans-types.c (gfc_typenode_for_spec): Added flag to control whether
|
||||
a component is part of coarray. When so, then add space to store a
|
||||
coarray token.
|
||||
(gfc_build_array_type): Same.
|
||||
(gfc_get_array_descriptor_base): Same.
|
||||
(gfc_get_array_type_bounds): Same.
|
||||
(gfc_sym_type): Same.
|
||||
(gfc_get_derived_type): Same.
|
||||
(gfc_get_caf_reference_type): Declare the caf_reference_type.
|
||||
* trans-types.h: Prototype changes only.
|
||||
* trans.c (gfc_allocate_using_lib): Use the updated caf_register
|
||||
signature.
|
||||
(gfc_allocate_allocatable): Same.
|
||||
(gfc_deallocate_with_status): Same.
|
||||
* trans.h: Defined the runtime types for caf_reference_t and the enums.
|
||||
|
||||
2016-09-19 Fritz Reese <fritzoreese@gmail.com>
|
||||
|
||||
PR fortran/77584
|
||||
|
@ -3128,10 +3128,14 @@ gfc_check_conformance (gfc_expr *op1, gfc_expr *op2, const char *optype_msgid, .
|
||||
|
||||
|
||||
/* Given an assignable expression and an arbitrary expression, make
|
||||
sure that the assignment can take place. */
|
||||
sure that the assignment can take place. Only add a call to the intrinsic
|
||||
conversion routines, when allow_convert is set. When this assign is a
|
||||
coarray call, then the convert is done by the coarray routine implictly and
|
||||
adding the intrinsic conversion would do harm in most cases. */
|
||||
|
||||
bool
|
||||
gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform)
|
||||
gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform,
|
||||
bool allow_convert)
|
||||
{
|
||||
gfc_symbol *sym;
|
||||
gfc_ref *ref;
|
||||
@ -3309,12 +3313,15 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform)
|
||||
kind values can be converted into one another. */
|
||||
if (lvalue->ts.type == BT_CHARACTER && rvalue->ts.type == BT_CHARACTER)
|
||||
{
|
||||
if (lvalue->ts.kind != rvalue->ts.kind)
|
||||
if (lvalue->ts.kind != rvalue->ts.kind && allow_convert)
|
||||
gfc_convert_chartype (rvalue, &lvalue->ts);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!allow_convert)
|
||||
return true;
|
||||
|
||||
return gfc_convert_type (rvalue, &lvalue->ts, 1);
|
||||
}
|
||||
|
||||
|
@ -1043,6 +1043,8 @@ typedef struct gfc_component
|
||||
|
||||
/* Needed for procedure pointer components. */
|
||||
struct gfc_typebound_proc *tb;
|
||||
/* When allocatable/pointer and in a coarray the associated token. */
|
||||
tree caf_token;
|
||||
}
|
||||
gfc_component;
|
||||
|
||||
@ -2768,7 +2770,7 @@ int gfc_validate_kind (bt, int, bool);
|
||||
int gfc_get_int_kind_from_width_isofortranenv (int size);
|
||||
int gfc_get_real_kind_from_width_isofortranenv (int size);
|
||||
tree gfc_get_union_type (gfc_symbol *);
|
||||
tree gfc_get_derived_type (gfc_symbol * derived);
|
||||
tree gfc_get_derived_type (gfc_symbol * derived, bool in_coarray = false);
|
||||
extern int gfc_index_integer_kind;
|
||||
extern int gfc_default_integer_kind;
|
||||
extern int gfc_max_integer_kind;
|
||||
@ -3047,7 +3049,7 @@ int gfc_numeric_ts (gfc_typespec *);
|
||||
int gfc_kind_max (gfc_expr *, gfc_expr *);
|
||||
|
||||
bool gfc_check_conformance (gfc_expr *, gfc_expr *, const char *, ...) ATTRIBUTE_PRINTF_3;
|
||||
bool gfc_check_assign (gfc_expr *, gfc_expr *, int);
|
||||
bool gfc_check_assign (gfc_expr *, gfc_expr *, int, bool c = true);
|
||||
bool gfc_check_pointer_assign (gfc_expr *, gfc_expr *);
|
||||
bool gfc_check_assign_symbol (gfc_symbol *, gfc_component *, gfc_expr *);
|
||||
|
||||
@ -3212,6 +3214,7 @@ const char *gfc_dt_upper_string (const char *);
|
||||
/* primary.c */
|
||||
symbol_attribute gfc_variable_attr (gfc_expr *, gfc_typespec *);
|
||||
symbol_attribute gfc_expr_attr (gfc_expr *);
|
||||
symbol_attribute gfc_caf_attr (gfc_expr *, bool in_allocate = false);
|
||||
match gfc_match_rvalue (gfc_expr **);
|
||||
match gfc_match_varspec (gfc_expr*, int, bool, bool);
|
||||
int gfc_check_digit (char, int);
|
||||
|
@ -3571,6 +3571,7 @@ of such a type
|
||||
@menu
|
||||
* caf_token_t::
|
||||
* caf_register_t::
|
||||
* caf_reference_t::
|
||||
@end menu
|
||||
|
||||
@node caf_token_t
|
||||
@ -3597,6 +3598,114 @@ typedef enum caf_register_t {
|
||||
caf_register_t;
|
||||
@end verbatim
|
||||
|
||||
@node caf_reference_t
|
||||
@subsection @code{caf_reference_t}
|
||||
|
||||
The structure used for implementing arbitrary reference chains.
|
||||
A @code{CAF_REFERENCE_T} allows to specify a component reference or any kind
|
||||
of array reference of any rank supported by gfortran. For array references all
|
||||
kinds as known by the compiler/Fortran standard are supported indicated by
|
||||
a @code{MODE}.
|
||||
|
||||
@verbatim
|
||||
typedef enum caf_ref_type_t {
|
||||
/* Reference a component of a derived type, either regular one or an
|
||||
allocatable or pointer type. For regular ones idx in caf_reference_t is
|
||||
set to -1. */
|
||||
CAF_REF_COMPONENT,
|
||||
/* Reference an allocatable array. */
|
||||
CAF_REF_ARRAY,
|
||||
/* Reference a non-allocatable/non-pointer array. I.e., the coarray object
|
||||
has no array descriptor associated and the addressing is done
|
||||
completely using the ref. */
|
||||
CAF_REF_STATIC_ARRAY
|
||||
} caf_ref_type_t;
|
||||
@end verbatim
|
||||
|
||||
@verbatim
|
||||
typedef enum caf_array_ref_t {
|
||||
/* No array ref. This terminates the array ref. */
|
||||
CAF_ARR_REF_NONE = 0,
|
||||
/* Reference array elements given by a vector. Only for this mode
|
||||
caf_reference_t.u.a.dim[i].v is valid. */
|
||||
CAF_ARR_REF_VECTOR,
|
||||
/* A full array ref (:). */
|
||||
CAF_ARR_REF_FULL,
|
||||
/* Reference a range on elements given by start, end and stride. */
|
||||
CAF_ARR_REF_RANGE,
|
||||
/* Only a single item is referenced given in the start member. */
|
||||
CAF_ARR_REF_SINGLE,
|
||||
/* An array ref of the kind (i:), where i is an arbitrary valid index in the
|
||||
array. The index i is given in the start member. */
|
||||
CAF_ARR_REF_OPEN_END,
|
||||
/* An array ref of the kind (:i), where the lower bound of the array ref
|
||||
is given by the remote side. The index i is given in the end member. */
|
||||
CAF_ARR_REF_OPEN_START
|
||||
} caf_array_ref_t;
|
||||
@end verbatim
|
||||
|
||||
@verbatim
|
||||
/* References to remote components of a derived type. */
|
||||
typedef struct caf_reference_t {
|
||||
/* A pointer to the next ref or NULL. */
|
||||
struct caf_reference_t *next;
|
||||
/* The type of the reference. */
|
||||
/* caf_ref_type_t, replaced by int to allow specification in fortran FE. */
|
||||
int type;
|
||||
/* The size of an item referenced in bytes. I.e. in an array ref this is
|
||||
the factor to advance the array pointer with to get to the next item.
|
||||
For component refs this gives just the size of the element referenced. */
|
||||
size_t item_size;
|
||||
union {
|
||||
struct {
|
||||
/* The offset (in bytes) of the component in the derived type.
|
||||
Unused for allocatable or pointer components. */
|
||||
ptrdiff_t offset;
|
||||
/* The offset (in bytes) to the caf_token associated with this
|
||||
component. NULL, when not allocatable/pointer ref. */
|
||||
ptrdiff_t caf_token_offset;
|
||||
} c;
|
||||
struct {
|
||||
/* The mode of the array ref. See CAF_ARR_REF_*. */
|
||||
/* caf_array_ref_t, replaced by unsigend char to allow specification in
|
||||
fortran FE. */
|
||||
unsigned char mode[GFC_MAX_DIMENSIONS];
|
||||
/* The type of a static array. Unset for array's with descriptors. */
|
||||
int static_array_type;
|
||||
/* Subscript refs (s) or vector refs (v). */
|
||||
union {
|
||||
struct {
|
||||
/* The start and end boundary of the ref and the stride. */
|
||||
index_type start, end, stride;
|
||||
} s;
|
||||
struct {
|
||||
/* nvec entries of kind giving the elements to reference. */
|
||||
void *vector;
|
||||
/* The number of entries in vector. */
|
||||
size_t nvec;
|
||||
/* The integer kind used for the elements in vector. */
|
||||
int kind;
|
||||
} v;
|
||||
} dim[GFC_MAX_DIMENSIONS];
|
||||
} a;
|
||||
} u;
|
||||
} caf_reference_t;
|
||||
@end verbatim
|
||||
|
||||
The references make up a single linked list of reference operations. The
|
||||
@code{NEXT} member links to the next reference or NULL to indicate the end of
|
||||
the chain. Component and array refs can be arbitrarly mixed as long as they
|
||||
comply to the Fortran standard.
|
||||
|
||||
@emph{NOTES}
|
||||
The member @code{STATIC_ARRAY_TYPE} is used only when the @code{TYPE} is
|
||||
@code{CAF_REF_STATIC_ARRAY}. The member gives the type of the data referenced.
|
||||
Because no array descriptor is available for a descriptor-less array and
|
||||
type conversion still needs to take place the type is transported here.
|
||||
|
||||
At the moment @code{CAF_ARR_REF_VECTOR} is not implemented in the front end for
|
||||
descriptor-less arrays. The library caf_single has untested support for it.
|
||||
|
||||
|
||||
@node Function ABI Documentation
|
||||
@section Function ABI Documentation
|
||||
@ -3611,6 +3720,9 @@ caf_register_t;
|
||||
* _gfortran_caf_send:: Sending data from a local image to a remote image
|
||||
* _gfortran_caf_get:: Getting data from a remote image
|
||||
* _gfortran_caf_sendget:: Sending data between remote images
|
||||
* _gfortran_caf_send_by_ref:: Sending data from a local image to a remote image using enhanced references
|
||||
* _gfortran_caf_get_by_ref:: Getting data from a remote image using enhanced references
|
||||
* _gfortran_caf_sendget_by_ref:: Sending data between remote images using enhanced references
|
||||
* _gfortran_caf_lock:: Locking a lock variable
|
||||
* _gfortran_caf_unlock:: Unlocking a lock variable
|
||||
* _gfortran_caf_event_post:: Post an event
|
||||
@ -3742,19 +3854,24 @@ the the compiler passes @code{distance=0} and @code{failed=-1} to the function.
|
||||
|
||||
@node _gfortran_caf_register
|
||||
@subsection @code{_gfortran_caf_register} --- Registering coarrays
|
||||
@cindex Coarray, _gfortran_caf_deregister
|
||||
@cindex Coarray, _gfortran_caf_register
|
||||
|
||||
@table @asis
|
||||
@item @emph{Description}:
|
||||
Allocates memory for a coarray and creates a token to identify the coarray. The
|
||||
function is called for both coarrays with @code{SAVE} attribute and using an
|
||||
explicit @code{ALLOCATE} statement. If an error occurs and @var{STAT} is a
|
||||
Registers memory for a coarray and creates a token to identify the coarray. The
|
||||
routine is called for both coarrays with @code{SAVE} attribute and using an
|
||||
explicit @code{ALLOCATE} statement. If an error occurs and @var{STAT} is a
|
||||
@code{NULL} pointer, the function shall abort with printing an error message
|
||||
and starting the error termination. If no error occurs and @var{STAT} is
|
||||
present, it shall be set to zero. Otherwise, it shall be set to a positive
|
||||
present, it shall be set to zero. Otherwise, it shall be set to a positive
|
||||
value and, if not-@code{NULL}, @var{ERRMSG} shall be set to a string describing
|
||||
the failure. The function shall return a pointer to the requested memory
|
||||
for the local image as a call to @code{malloc} would do.
|
||||
the failure. The routine shall register the memory provided in the
|
||||
@code{DATA}-component of the array descriptor @var{DESC}, when that component
|
||||
is non-@code{NULL}, else it shall allocate sufficient memory and provide a
|
||||
pointer to it in the @code{DATA}-component of @var{DESC}. The array descriptor
|
||||
has rank zero, when a scalar object is to be registered and the array
|
||||
descriptor may be invalid after the call to @code{_gfortran_caf_register}.
|
||||
When an array is to be allocated the descriptor persists.
|
||||
|
||||
For @code{CAF_REGTYPE_COARRAY_STATIC} and @code{CAF_REGTYPE_COARRAY_ALLOC},
|
||||
the passed size is the byte size requested. For @code{CAF_REGTYPE_LOCK_STATIC},
|
||||
@ -3763,8 +3880,8 @@ size or one for a scalar.
|
||||
|
||||
|
||||
@item @emph{Syntax}:
|
||||
@code{void *caf_register (size_t size, caf_register_t type, caf_token_t *token,
|
||||
int *stat, char *errmsg, int errmsg_len)}
|
||||
@code{void caf_register (size_t size, caf_register_t type, caf_token_t *token,
|
||||
gfc_descriptor_t *desc, int *stat, char *errmsg, int errmsg_len)}
|
||||
|
||||
@item @emph{Arguments}:
|
||||
@multitable @columnfractions .15 .70
|
||||
@ -3772,6 +3889,7 @@ int *stat, char *errmsg, int errmsg_len)}
|
||||
allocated; for lock types and event types, the number of elements.
|
||||
@item @var{type} @tab one of the caf_register_t types.
|
||||
@item @var{token} @tab intent(out) An opaque pointer identifying the coarray.
|
||||
@item @var{desc} @tab intent(inout) The (pseudo) array descriptor.
|
||||
@item @var{stat} @tab intent(out) For allocatable coarrays, stores the STAT=;
|
||||
may be NULL
|
||||
@item @var{errmsg} @tab intent(out) When an error occurs, this will be set to
|
||||
@ -3787,12 +3905,12 @@ GCC does such that also nonallocatable coarrays the memory is allocated and no
|
||||
static memory is used. The token permits to identify the coarray; to the
|
||||
processor, the token is a nonaliasing pointer. The library can, for instance,
|
||||
store the base address of the coarray in the token, some handle or a more
|
||||
complicated struct.
|
||||
complicated struct. The library may also store the array descriptor
|
||||
@var{DESC} when its rank is non-zero.
|
||||
|
||||
For normal coarrays, the returned pointer is used for accesses on the local
|
||||
image. For lock types, the value shall only used for checking the allocation
|
||||
For lock types, the value shall only used for checking the allocation
|
||||
status. Note that for critical blocks, the locking is only required on one
|
||||
image; in the locking statement, the processor shall always pass always an
|
||||
image; in the locking statement, the processor shall always pass an
|
||||
image index of one for critical-block lock variables
|
||||
(@code{CAF_REGTYPE_CRITICAL}). For lock types and critical-block variables,
|
||||
the initial value shall be unlocked (or, respecitively, not in critical
|
||||
@ -3800,7 +3918,6 @@ section) such as the value false; for event types, the initial state should
|
||||
be no event, e.g. zero.
|
||||
@end table
|
||||
|
||||
|
||||
@node _gfortran_caf_deregister
|
||||
@subsection @code{_gfortran_caf_deregister} --- Deregistering coarrays
|
||||
@cindex Coarray, _gfortran_caf_deregister
|
||||
@ -3809,14 +3926,17 @@ be no event, e.g. zero.
|
||||
@item @emph{Description}:
|
||||
Called to free the memory of a coarray; the processor calls this function for
|
||||
automatic and explicit deallocation. In case of an error, this function shall
|
||||
fail with an error message, unless the @var{STAT} variable is not null.
|
||||
fail with an error message, unless the @var{STAT} variable is not null. The
|
||||
library is only expected to free memory it allocated itself during a call to
|
||||
@code{_gfortran_caf_register}.
|
||||
|
||||
@item @emph{Syntax}:
|
||||
@code{void caf_deregister (const caf_token_t *token, int *stat, char *errmsg,
|
||||
@code{void caf_deregister (caf_token_t *token, int *stat, char *errmsg,
|
||||
int errmsg_len)}
|
||||
|
||||
@item @emph{Arguments}:
|
||||
@multitable @columnfractions .15 .70
|
||||
@item @var{token} @tab the token to free.
|
||||
@item @var{stat} @tab intent(out) Stores the STAT=; may be NULL
|
||||
@item @var{errmsg} @tab intent(out) When an error occurs, this will be set
|
||||
to an error message; may be NULL
|
||||
@ -3997,6 +4117,186 @@ the library has to handle numeric-type conversion and for strings, padding and
|
||||
different character kinds.
|
||||
@end table
|
||||
|
||||
@node _gfortran_caf_send_by_ref
|
||||
@subsection @code{_gfortran_caf_send_by_ref} --- Sending data from a local image to a remote image with enhanced referencing options
|
||||
@cindex Coarray, _gfortran_caf_send_by_ref
|
||||
|
||||
@table @asis
|
||||
@item @emph{Description}:
|
||||
Called to send a scalar, an array section or whole array from a local to a
|
||||
remote image identified by the image_index.
|
||||
|
||||
@item @emph{Syntax}:
|
||||
@code{void _gfortran_caf_send_by_ref (caf_token_t token, int image_index,
|
||||
gfc_descriptor_t *src, caf_reference_t *refs, int dst_kind, int src_kind,
|
||||
bool may_require_tmp, bool dst_reallocatable, int *stat)}
|
||||
|
||||
@item @emph{Arguments}:
|
||||
@multitable @columnfractions .15 .70
|
||||
@item @var{token} @tab intent(in) An opaque pointer identifying the coarray.
|
||||
@item @var{image_index} @tab The ID of the remote image; must be a positive
|
||||
number.
|
||||
@item @var{src} @tab intent(in) Array descriptor of the local array to be
|
||||
transferred to the remote image
|
||||
@item @var{refs} @tab intent(in) the references on the remote array to store
|
||||
the data given by src. Guaranteed to have at least one entry.
|
||||
@item @var{dst_kind} @tab Kind of the destination argument
|
||||
@item @var{src_kind} @tab Kind of the source argument
|
||||
@item @var{may_require_tmp} @tab The variable is false it is known at compile
|
||||
time that the @var{dest} and @var{src} either cannot overlap or overlap (fully
|
||||
or partially) such that walking @var{src} and @var{dest} in element wise
|
||||
element order (honoring the stride value) will not lead to wrong results.
|
||||
Otherwise, the value is true.
|
||||
@item @var{dst_reallocatable} @tab set when the destination is of allocatable
|
||||
or pointer type and the refs will allow reallocation, i.e., the ref is a full
|
||||
array or component ref.
|
||||
@item @var{stat} @tab intent(out) when non-@code{NULL} give the result of the
|
||||
operation, i.e., zero on success and non-zero on error. When @code{NULL} and
|
||||
error occurs, then an error message is printed and the program is terminated.
|
||||
@end multitable
|
||||
|
||||
@item @emph{NOTES}
|
||||
It is permitted to have image_id equal the current image; the memory of the
|
||||
send-to and the send-from might (partially) overlap in that case. The
|
||||
implementation has to take care that it handles this case, e.g. using
|
||||
@code{memmove} which handles (partially) overlapping memory. If
|
||||
@var{may_require_tmp} is true, the library might additionally create a
|
||||
temporary variable, unless additional checks show that this is not required
|
||||
(e.g. because walking backward is possible or because both arrays are
|
||||
contiguous and @code{memmove} takes care of overlap issues).
|
||||
|
||||
Note that the assignment of a scalar to an array is permitted. In addition,
|
||||
the library has to handle numeric-type conversion and for strings, padding
|
||||
and different character kinds.
|
||||
|
||||
Because of the more complicated references possible some operations may be
|
||||
unsupported by certain libraries. The library is expected to issue a precise
|
||||
error message why the operation is not permitted.
|
||||
@end table
|
||||
|
||||
|
||||
@node _gfortran_caf_get_by_ref
|
||||
@subsection @code{_gfortran_caf_get_by_ref} --- Getting data from a remote image using enhanced references
|
||||
@cindex Coarray, _gfortran_caf_get_by_ref
|
||||
|
||||
@table @asis
|
||||
@item @emph{Description}:
|
||||
Called to get a scalar, an array section or whole array from a a remote image
|
||||
identified by the image_index.
|
||||
|
||||
@item @emph{Syntax}:
|
||||
@code{void _gfortran_caf_get_by_ref (caf_token_t token, int image_index,
|
||||
caf_reference_t *refs, gfc_descriptor_t *dst, int dst_kind, int src_kind,
|
||||
bool may_require_tmp, bool dst_reallocatable, int *stat)}
|
||||
|
||||
@item @emph{Arguments}:
|
||||
@multitable @columnfractions .15 .70
|
||||
@item @var{token} @tab intent(in) An opaque pointer identifying the coarray.
|
||||
@item @var{image_index} @tab The ID of the remote image; must be a positive
|
||||
number.
|
||||
@item @var{refs} @tab intent(in) the references to apply to the remote structure
|
||||
to get the data.
|
||||
@item @var{dst} @tab intent(in) Array descriptor of the local array to store
|
||||
the data transferred from the remote image. May be reallocated where needed
|
||||
and when @var{DST_REALLOCATABLE} allows it.
|
||||
@item @var{dst_kind} @tab Kind of the destination argument
|
||||
@item @var{src_kind} @tab Kind of the source argument
|
||||
@item @var{may_require_tmp} @tab The variable is false it is known at compile
|
||||
time that the @var{dest} and @var{src} either cannot overlap or overlap (fully
|
||||
or partially) such that walking @var{src} and @var{dest} in element wise
|
||||
element order (honoring the stride value) will not lead to wrong results.
|
||||
Otherwise, the value is true.
|
||||
@item @var{dst_reallocatable} @tab set when @var{DST} is of allocatable
|
||||
or pointer type and its refs allow reallocation, i.e., the full array or a
|
||||
component is referenced.
|
||||
@item @var{stat} @tab intent(out) when non-@code{NULL} give the result of the
|
||||
operation, i.e., zero on success and non-zero on error. When @code{NULL} and
|
||||
error occurs, then an error message is printed and the program is terminated.
|
||||
@end multitable
|
||||
|
||||
@item @emph{NOTES}
|
||||
It is permitted to have image_id equal the current image; the memory of the
|
||||
send-to and the send-from might (partially) overlap in that case. The
|
||||
implementation has to take care that it handles this case, e.g. using
|
||||
@code{memmove} which handles (partially) overlapping memory. If
|
||||
@var{may_require_tmp} is true, the library might additionally create a
|
||||
temporary variable, unless additional checks show that this is not required
|
||||
(e.g. because walking backward is possible or because both arrays are
|
||||
contiguous and @code{memmove} takes care of overlap issues).
|
||||
|
||||
Note that the library has to handle numeric-type conversion and for strings,
|
||||
padding and different character kinds.
|
||||
|
||||
Because of the more complicated references possible some operations may be
|
||||
unsupported by certain libraries. The library is expected to issue a precise
|
||||
error message why the operation is not permitted.
|
||||
@end table
|
||||
|
||||
|
||||
@node _gfortran_caf_sendget_by_ref
|
||||
@subsection @code{_gfortran_caf_sendget_by_ref} --- Sending data between remote images using enhanced references on both sides
|
||||
@cindex Coarray, _gfortran_caf_sendget_by_ref
|
||||
|
||||
@table @asis
|
||||
@item @emph{Description}:
|
||||
Called to send a scalar, an array section or whole array from a remote image
|
||||
identified by the src_image_index to a remote image identified by the
|
||||
dst_image_index.
|
||||
|
||||
@item @emph{Syntax}:
|
||||
@code{void _gfortran_caf_sendget_by_ref (caf_token_t dst_token,
|
||||
int dst_image_index, caf_reference_t *dst_refs,
|
||||
caf_token_t src_token, int src_image_index, caf_reference_t *src_refs,
|
||||
int dst_kind, int src_kind, bool may_require_tmp, int *dst_stat, int *src_stat)}
|
||||
|
||||
@item @emph{Arguments}:
|
||||
@multitable @columnfractions .15 .70
|
||||
@item @var{dst_token} @tab intent(in) An opaque pointer identifying the
|
||||
destination coarray.
|
||||
@item @var{dst_image_index} @tab The ID of the destination remote image; must
|
||||
be a positive number.
|
||||
@item @var{dst_refs} @tab intent(in) the references on the remote array to store
|
||||
the data given by src. Guaranteed to have at least one entry.
|
||||
@item @var{src_token} @tab An opaque pointer identifying the source coarray.
|
||||
@item @var{src_image_index} @tab The ID of the source remote image; must be a
|
||||
positive number.
|
||||
@item @var{src_refs} @tab intent(in) the references to apply to the remote
|
||||
structure to get the data.
|
||||
@item @var{dst_kind} @tab Kind of the destination argument
|
||||
@item @var{src_kind} @tab Kind of the source argument
|
||||
@item @var{may_require_tmp} @tab The variable is false it is known at compile
|
||||
time that the @var{dest} and @var{src} either cannot overlap or overlap (fully
|
||||
or partially) such that walking @var{src} and @var{dest} in element wise
|
||||
element order (honoring the stride value) will not lead to wrong results.
|
||||
Otherwise, the value is true.
|
||||
@item @var{dst_stat} @tab intent(out) when non-@code{NULL} give the result of
|
||||
the send-operation, i.e., zero on success and non-zero on error. When
|
||||
@code{NULL} and an error occurs, then an error message is printed and the
|
||||
program is terminated.
|
||||
@item @var{src_stat} @tab intent(out) when non-@code{NULL} give the result of
|
||||
the get-operation, i.e., zero on success and non-zero on error. When
|
||||
@code{NULL} and an error occurs, then an error message is printed and the
|
||||
program is terminated.
|
||||
@end multitable
|
||||
|
||||
@item @emph{NOTES}
|
||||
It is permitted to have image_ids equal; the memory of the send-to and the
|
||||
send-from might (partially) overlap in that case. The implementation has to
|
||||
take care that it handles this case, e.g. using @code{memmove} which handles
|
||||
(partially) overlapping memory. If @var{may_require_tmp} is true, the library
|
||||
might additionally create a temporary variable, unless additional checks show
|
||||
that this is not required (e.g. because walking backward is possible or because
|
||||
both arrays are contiguous and @code{memmove} takes care of overlap issues).
|
||||
|
||||
Note that the assignment of a scalar to an array is permitted. In addition,
|
||||
the library has to handle numeric-type conversion and for strings, padding and
|
||||
different character kinds.
|
||||
|
||||
Because of the more complicated references possible some operations may be
|
||||
unsupported by certain libraries. The library is expected to issue a precise
|
||||
error message why the operation is not permitted.
|
||||
@end table
|
||||
|
||||
|
||||
@node _gfortran_caf_lock
|
||||
@subsection @code{_gfortran_caf_lock} --- Locking a lock variable
|
||||
|
@ -2376,6 +2376,163 @@ gfc_expr_attr (gfc_expr *e)
|
||||
}
|
||||
|
||||
|
||||
/* Given an expression, figure out what the ultimate expression
|
||||
attribute is. This routine is similar to gfc_variable_attr with
|
||||
parts of gfc_expr_attr, but focuses more on the needs of
|
||||
coarrays. For coarrays a codimension attribute is kind of
|
||||
"infectious" being propagated once set and never cleared. */
|
||||
|
||||
static symbol_attribute
|
||||
caf_variable_attr (gfc_expr *expr, bool in_allocate)
|
||||
{
|
||||
int dimension, codimension, pointer, allocatable, target, coarray_comp,
|
||||
alloc_comp;
|
||||
symbol_attribute attr;
|
||||
gfc_ref *ref;
|
||||
gfc_symbol *sym;
|
||||
gfc_component *comp;
|
||||
|
||||
if (expr->expr_type != EXPR_VARIABLE && expr->expr_type != EXPR_FUNCTION)
|
||||
gfc_internal_error ("gfc_caf_attr(): Expression isn't a variable");
|
||||
|
||||
sym = expr->symtree->n.sym;
|
||||
gfc_clear_attr (&attr);
|
||||
|
||||
if (sym->ts.type == BT_CLASS && sym->attr.class_ok)
|
||||
{
|
||||
dimension = CLASS_DATA (sym)->attr.dimension;
|
||||
codimension = CLASS_DATA (sym)->attr.codimension;
|
||||
pointer = CLASS_DATA (sym)->attr.class_pointer;
|
||||
allocatable = CLASS_DATA (sym)->attr.allocatable;
|
||||
coarray_comp = CLASS_DATA (sym)->attr.coarray_comp;
|
||||
alloc_comp = CLASS_DATA (sym)->ts.u.derived->attr.alloc_comp;
|
||||
}
|
||||
else
|
||||
{
|
||||
dimension = sym->attr.dimension;
|
||||
codimension = sym->attr.codimension;
|
||||
pointer = sym->attr.pointer;
|
||||
allocatable = sym->attr.allocatable;
|
||||
coarray_comp = sym->attr.coarray_comp;
|
||||
alloc_comp = sym->ts.type == BT_DERIVED
|
||||
? sym->ts.u.derived->attr.alloc_comp : 0;
|
||||
}
|
||||
|
||||
target = attr.target;
|
||||
if (pointer || attr.proc_pointer)
|
||||
target = 1;
|
||||
|
||||
for (ref = expr->ref; ref; ref = ref->next)
|
||||
switch (ref->type)
|
||||
{
|
||||
case REF_ARRAY:
|
||||
|
||||
switch (ref->u.ar.type)
|
||||
{
|
||||
case AR_FULL:
|
||||
case AR_SECTION:
|
||||
dimension = 1;
|
||||
break;
|
||||
|
||||
case AR_ELEMENT:
|
||||
/* Handle coarrays. */
|
||||
if (ref->u.ar.dimen > 0 && !in_allocate)
|
||||
allocatable = pointer = 0;
|
||||
break;
|
||||
|
||||
case AR_UNKNOWN:
|
||||
/* If any of start, end or stride is not integer, there will
|
||||
already have been an error issued. */
|
||||
int errors;
|
||||
gfc_get_errors (NULL, &errors);
|
||||
if (errors == 0)
|
||||
gfc_internal_error ("gfc_caf_attr(): Bad array reference");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case REF_COMPONENT:
|
||||
comp = ref->u.c.component;
|
||||
|
||||
if (comp->ts.type == BT_CLASS)
|
||||
{
|
||||
codimension |= CLASS_DATA (comp)->attr.codimension;
|
||||
pointer = CLASS_DATA (comp)->attr.class_pointer;
|
||||
allocatable = CLASS_DATA (comp)->attr.allocatable;
|
||||
coarray_comp |= CLASS_DATA (comp)->attr.coarray_comp;
|
||||
}
|
||||
else
|
||||
{
|
||||
codimension |= comp->attr.codimension;
|
||||
pointer = comp->attr.pointer;
|
||||
allocatable = comp->attr.allocatable;
|
||||
coarray_comp |= comp->attr.coarray_comp;
|
||||
}
|
||||
|
||||
if (pointer || attr.proc_pointer)
|
||||
target = 1;
|
||||
|
||||
break;
|
||||
|
||||
case REF_SUBSTRING:
|
||||
allocatable = pointer = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
attr.dimension = dimension;
|
||||
attr.codimension = codimension;
|
||||
attr.pointer = pointer;
|
||||
attr.allocatable = allocatable;
|
||||
attr.target = target;
|
||||
attr.save = sym->attr.save;
|
||||
attr.coarray_comp = coarray_comp;
|
||||
attr.alloc_comp = alloc_comp;
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
|
||||
symbol_attribute
|
||||
gfc_caf_attr (gfc_expr *e, bool in_allocate)
|
||||
{
|
||||
symbol_attribute attr;
|
||||
|
||||
switch (e->expr_type)
|
||||
{
|
||||
case EXPR_VARIABLE:
|
||||
attr = caf_variable_attr (e, in_allocate);
|
||||
break;
|
||||
|
||||
case EXPR_FUNCTION:
|
||||
gfc_clear_attr (&attr);
|
||||
|
||||
if (e->value.function.esym && e->value.function.esym->result)
|
||||
{
|
||||
gfc_symbol *sym = e->value.function.esym->result;
|
||||
attr = sym->attr;
|
||||
if (sym->ts.type == BT_CLASS)
|
||||
{
|
||||
attr.dimension = CLASS_DATA (sym)->attr.dimension;
|
||||
attr.pointer = CLASS_DATA (sym)->attr.class_pointer;
|
||||
attr.allocatable = CLASS_DATA (sym)->attr.allocatable;
|
||||
attr.alloc_comp = CLASS_DATA (sym)->ts.u.derived->attr.alloc_comp;
|
||||
}
|
||||
}
|
||||
else if (e->symtree)
|
||||
attr = caf_variable_attr (e, in_allocate);
|
||||
else
|
||||
gfc_clear_attr (&attr);
|
||||
break;
|
||||
|
||||
default:
|
||||
gfc_clear_attr (&attr);
|
||||
break;
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
|
||||
/* Match a structure constructor. The initial symbol has already been
|
||||
seen. */
|
||||
|
||||
|
@ -9839,27 +9839,29 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
|
||||
return false;
|
||||
}
|
||||
|
||||
gfc_check_assign (lhs, rhs, 1);
|
||||
|
||||
/* Assign the 'data' of a class object to a derived type. */
|
||||
if (lhs->ts.type == BT_DERIVED
|
||||
&& rhs->ts.type == BT_CLASS)
|
||||
gfc_add_data_component (rhs);
|
||||
|
||||
bool caf_convert_to_send = flag_coarray == GFC_FCOARRAY_LIB
|
||||
&& (lhs_coindexed
|
||||
|| (code->expr2->expr_type == EXPR_FUNCTION
|
||||
&& code->expr2->value.function.isym
|
||||
&& code->expr2->value.function.isym->id == GFC_ISYM_CAF_GET
|
||||
&& (code->expr1->rank == 0 || code->expr2->rank != 0)
|
||||
&& !gfc_expr_attr (rhs).allocatable
|
||||
&& !gfc_has_vector_subscript (rhs)));
|
||||
|
||||
gfc_check_assign (lhs, rhs, 1, !caf_convert_to_send);
|
||||
|
||||
/* Insert a GFC_ISYM_CAF_SEND intrinsic, when the LHS is a coindexed variable.
|
||||
Additionally, insert this code when the RHS is a CAF as we then use the
|
||||
GFC_ISYM_CAF_SEND intrinsic just to avoid a temporary; but do not do so if
|
||||
the LHS is (re)allocatable or has a vector subscript. If the LHS is a
|
||||
noncoindexed array and the RHS is a coindexed scalar, use the normal code
|
||||
path. */
|
||||
if (flag_coarray == GFC_FCOARRAY_LIB
|
||||
&& (lhs_coindexed
|
||||
|| (code->expr2->expr_type == EXPR_FUNCTION
|
||||
&& code->expr2->value.function.isym
|
||||
&& code->expr2->value.function.isym->id == GFC_ISYM_CAF_GET
|
||||
&& (code->expr1->rank == 0 || code->expr2->rank != 0)
|
||||
&& !gfc_expr_attr (rhs).allocatable
|
||||
&& !gfc_has_vector_subscript (rhs))))
|
||||
if (caf_convert_to_send)
|
||||
{
|
||||
if (code->expr2->expr_type == EXPR_FUNCTION
|
||||
&& code->expr2->value.function.isym
|
||||
|
@ -5083,19 +5083,19 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
|
||||
stride = gfc_index_one_node;
|
||||
offset = gfc_index_zero_node;
|
||||
|
||||
/* Set the dtype. */
|
||||
/* Set the dtype before the alloc, because registration of coarrays needs
|
||||
it initialized. */
|
||||
if (expr->ts.type == BT_CHARACTER && expr->ts.deferred
|
||||
&& TREE_CODE (expr->ts.u.cl->backend_decl) == VAR_DECL)
|
||||
{
|
||||
type = gfc_typenode_for_spec (&expr->ts);
|
||||
tmp = gfc_conv_descriptor_dtype (descriptor);
|
||||
gfc_add_modify (descriptor_block, tmp,
|
||||
gfc_get_dtype_rank_type (rank, type));
|
||||
gfc_add_modify (pblock, tmp, gfc_get_dtype_rank_type (rank, type));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = gfc_conv_descriptor_dtype (descriptor);
|
||||
gfc_add_modify (descriptor_block, tmp, gfc_get_dtype (type));
|
||||
gfc_add_modify (pblock, tmp, gfc_get_dtype (type));
|
||||
}
|
||||
|
||||
or_expr = boolean_false_node;
|
||||
@ -5404,7 +5404,8 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
|
||||
stmtblock_t elseblock;
|
||||
gfc_expr **lower;
|
||||
gfc_expr **upper;
|
||||
gfc_ref *ref, *prev_ref = NULL;
|
||||
gfc_ref *ref, *prev_ref = NULL, *coref;
|
||||
gfc_se caf_se;
|
||||
bool allocatable, coarray, dimension, alloc_w_e3_arr_spec = false;
|
||||
|
||||
ref = expr->ref;
|
||||
@ -5418,16 +5419,25 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
|
||||
if (!prev_ref)
|
||||
{
|
||||
allocatable = expr->symtree->n.sym->attr.allocatable;
|
||||
coarray = expr->symtree->n.sym->attr.codimension;
|
||||
dimension = expr->symtree->n.sym->attr.dimension;
|
||||
}
|
||||
else
|
||||
{
|
||||
allocatable = prev_ref->u.c.component->attr.allocatable;
|
||||
coarray = prev_ref->u.c.component->attr.codimension;
|
||||
dimension = prev_ref->u.c.component->attr.dimension;
|
||||
}
|
||||
|
||||
/* For allocatable/pointer arrays in derived types, one of the refs has to be
|
||||
a coarray. In this case it does not matter whether we are on this_image
|
||||
or not. */
|
||||
coarray = false;
|
||||
for (coref = expr->ref; coref; coref = coref->next)
|
||||
if (coref->type == REF_ARRAY && coref->u.ar.codimen > 0)
|
||||
{
|
||||
coarray = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dimension)
|
||||
gcc_assert (coarray);
|
||||
|
||||
@ -5482,6 +5492,9 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
|
||||
overflow = integer_zero_node;
|
||||
|
||||
gfc_init_block (&set_descriptor_block);
|
||||
/* Take the corank only from the actual ref and not from the coref. The
|
||||
later will mislead the generation of the array dimensions for allocatable/
|
||||
pointer components in derived types. */
|
||||
size = gfc_array_init_size (se->expr, alloc_w_e3_arr_spec ? expr->rank
|
||||
: ref->u.ar.as->rank,
|
||||
coarray ? ref->u.ar.as->corank : 0,
|
||||
@ -5517,6 +5530,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
|
||||
}
|
||||
}
|
||||
|
||||
gfc_init_se (&caf_se, NULL);
|
||||
gfc_start_block (&elseblock);
|
||||
|
||||
/* Allocate memory to store the data. */
|
||||
@ -5527,16 +5541,22 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
|
||||
STRIP_NOPS (pointer);
|
||||
|
||||
if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
|
||||
token = gfc_build_addr_expr (NULL_TREE,
|
||||
gfc_conv_descriptor_token (se->expr));
|
||||
{
|
||||
tmp = gfc_get_tree_for_caf_expr (expr);
|
||||
gfc_get_caf_token_offset (&caf_se, &token, NULL, tmp, NULL_TREE, expr);
|
||||
gfc_add_block_to_block (&elseblock, &caf_se.pre);
|
||||
token = gfc_build_addr_expr (NULL_TREE, token);
|
||||
}
|
||||
|
||||
/* The allocatable variant takes the old pointer as first argument. */
|
||||
if (allocatable)
|
||||
gfc_allocate_allocatable (&elseblock, pointer, size, token,
|
||||
status, errmsg, errlen, label_finish, expr);
|
||||
status, errmsg, errlen, label_finish, expr,
|
||||
coref != NULL ? coref->u.ar.as->corank : 0);
|
||||
else
|
||||
gfc_allocate_using_malloc (&elseblock, pointer, size, status);
|
||||
|
||||
gfc_add_block_to_block (&elseblock, &caf_se.post);
|
||||
if (dimension)
|
||||
{
|
||||
cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
|
||||
@ -5592,7 +5612,7 @@ gfc_array_deallocate (tree descriptor, tree pstat, tree errmsg, tree errlen,
|
||||
tree var;
|
||||
tree tmp;
|
||||
stmtblock_t block;
|
||||
bool coarray = gfc_is_coarray (expr);
|
||||
bool coarray = gfc_caf_attr (expr).codimension;
|
||||
|
||||
gfc_start_block (&block);
|
||||
|
||||
@ -8659,6 +8679,10 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
|
||||
int n;
|
||||
int dim;
|
||||
gfc_array_spec * as;
|
||||
bool coarray = (flag_coarray == GFC_FCOARRAY_LIB
|
||||
&& gfc_caf_attr (expr1, true).codimension);
|
||||
tree token;
|
||||
gfc_se caf_se;
|
||||
|
||||
/* x = f(...) with x allocatable. In this case, expr1 is the rhs.
|
||||
Find the lhs expression in the loop chain and set expr1 and
|
||||
@ -8973,11 +8997,30 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
|
||||
gfc_add_modify (&fblock, tmp,
|
||||
gfc_get_dtype_rank_type (expr1->rank,type));
|
||||
}
|
||||
else if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
|
||||
{
|
||||
gfc_add_modify (&fblock, gfc_conv_descriptor_dtype (desc),
|
||||
gfc_get_dtype (TREE_TYPE (desc)));
|
||||
}
|
||||
|
||||
/* Realloc expression. Note that the scalarizer uses desc.data
|
||||
in the array reference - (*desc.data)[<element>]. */
|
||||
gfc_init_block (&realloc_block);
|
||||
gfc_init_se (&caf_se, NULL);
|
||||
|
||||
if (coarray)
|
||||
{
|
||||
token = gfc_get_ultimate_alloc_ptr_comps_caf_token (&caf_se, expr1);
|
||||
if (token == NULL_TREE)
|
||||
{
|
||||
tmp = gfc_get_tree_for_caf_expr (expr1);
|
||||
gfc_get_caf_token_offset (&caf_se, &token, NULL, tmp, NULL_TREE,
|
||||
expr1);
|
||||
token = gfc_build_addr_expr (NULL_TREE, token);
|
||||
}
|
||||
|
||||
gfc_add_block_to_block (&realloc_block, &caf_se.pre);
|
||||
}
|
||||
if ((expr1->ts.type == BT_DERIVED)
|
||||
&& expr1->ts.u.derived->attr.alloc_comp)
|
||||
{
|
||||
@ -8986,12 +9029,32 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
|
||||
gfc_add_expr_to_block (&realloc_block, tmp);
|
||||
}
|
||||
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
builtin_decl_explicit (BUILT_IN_REALLOC), 2,
|
||||
fold_convert (pvoid_type_node, array1),
|
||||
size2);
|
||||
gfc_conv_descriptor_data_set (&realloc_block,
|
||||
desc, tmp);
|
||||
if (!coarray)
|
||||
{
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
builtin_decl_explicit (BUILT_IN_REALLOC), 2,
|
||||
fold_convert (pvoid_type_node, array1),
|
||||
size2);
|
||||
gfc_conv_descriptor_data_set (&realloc_block,
|
||||
desc, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
gfor_fndecl_caf_deregister,
|
||||
4, token, null_pointer_node,
|
||||
null_pointer_node, integer_zero_node);
|
||||
gfc_add_expr_to_block (&realloc_block, tmp);
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
gfor_fndecl_caf_register,
|
||||
7, size2,
|
||||
build_int_cst (integer_type_node,
|
||||
GFC_CAF_COARRAY_ALLOC),
|
||||
token, gfc_build_addr_expr (NULL_TREE, desc),
|
||||
null_pointer_node, null_pointer_node,
|
||||
integer_zero_node);
|
||||
gfc_add_expr_to_block (&realloc_block, tmp);
|
||||
}
|
||||
|
||||
if ((expr1->ts.type == BT_DERIVED)
|
||||
&& expr1->ts.u.derived->attr.alloc_comp)
|
||||
@ -9001,6 +9064,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
|
||||
gfc_add_expr_to_block (&realloc_block, tmp);
|
||||
}
|
||||
|
||||
gfc_add_block_to_block (&realloc_block, &caf_se.post);
|
||||
realloc_expr = gfc_finish_block (&realloc_block);
|
||||
|
||||
/* Only reallocate if sizes are different. */
|
||||
@ -9011,16 +9075,33 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
|
||||
|
||||
/* Malloc expression. */
|
||||
gfc_init_block (&alloc_block);
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
builtin_decl_explicit (BUILT_IN_MALLOC),
|
||||
1, size2);
|
||||
gfc_conv_descriptor_data_set (&alloc_block,
|
||||
desc, tmp);
|
||||
if (!coarray)
|
||||
{
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
builtin_decl_explicit (BUILT_IN_MALLOC),
|
||||
1, size2);
|
||||
gfc_conv_descriptor_data_set (&alloc_block,
|
||||
desc, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
gfor_fndecl_caf_register,
|
||||
7, size2,
|
||||
build_int_cst (integer_type_node,
|
||||
GFC_CAF_COARRAY_ALLOC),
|
||||
token, gfc_build_addr_expr (NULL_TREE, desc),
|
||||
null_pointer_node, null_pointer_node,
|
||||
integer_zero_node);
|
||||
gfc_add_expr_to_block (&alloc_block, tmp);
|
||||
}
|
||||
|
||||
|
||||
/* We already set the dtype in the case of deferred character
|
||||
length arrays. */
|
||||
if (!(GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
|
||||
&& expr1->ts.type == BT_CHARACTER && expr1->ts.deferred))
|
||||
&& ((expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
|
||||
|| coarray)))
|
||||
{
|
||||
tmp = gfc_conv_descriptor_dtype (desc);
|
||||
gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
|
||||
|
@ -135,6 +135,9 @@ tree gfor_fndecl_caf_deregister;
|
||||
tree gfor_fndecl_caf_get;
|
||||
tree gfor_fndecl_caf_send;
|
||||
tree gfor_fndecl_caf_sendget;
|
||||
tree gfor_fndecl_caf_get_by_ref;
|
||||
tree gfor_fndecl_caf_send_by_ref;
|
||||
tree gfor_fndecl_caf_sendget_by_ref;
|
||||
tree gfor_fndecl_caf_sync_all;
|
||||
tree gfor_fndecl_caf_sync_memory;
|
||||
tree gfor_fndecl_caf_sync_images;
|
||||
@ -3560,12 +3563,12 @@ gfc_build_builtin_function_decls (void)
|
||||
2, integer_type_node, integer_type_node);
|
||||
|
||||
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,
|
||||
pchar_type_node, integer_type_node);
|
||||
get_identifier (PREFIX("caf_register")), "RRWWWWR", void_type_node, 7,
|
||||
size_type_node, integer_type_node, ppvoid_type_node, pvoid_type_node,
|
||||
pint_type, pchar_type_node, integer_type_node);
|
||||
|
||||
gfor_fndecl_caf_deregister = gfc_build_library_function_decl_with_spec (
|
||||
get_identifier (PREFIX("caf_deregister")), ".WWW", void_type_node, 4,
|
||||
get_identifier (PREFIX("caf_deregister")), "WWWR", void_type_node, 4,
|
||||
ppvoid_type_node, pint_type, pchar_type_node, integer_type_node);
|
||||
|
||||
gfor_fndecl_caf_get = gfc_build_library_function_decl_with_spec (
|
||||
@ -3581,11 +3584,31 @@ gfc_build_builtin_function_decls (void)
|
||||
boolean_type_node, pint_type);
|
||||
|
||||
gfor_fndecl_caf_sendget = gfc_build_library_function_decl_with_spec (
|
||||
get_identifier (PREFIX("caf_sendget")), ".R.RRRR.RRR", void_type_node,
|
||||
13, pvoid_type_node, size_type_node, integer_type_node, pvoid_type_node,
|
||||
pvoid_type_node, pvoid_type_node, size_type_node, integer_type_node,
|
||||
pvoid_type_node, pvoid_type_node, integer_type_node, integer_type_node,
|
||||
boolean_type_node);
|
||||
get_identifier (PREFIX("caf_sendget")), ".R.RRRR.RRRRRR",
|
||||
void_type_node, 14, pvoid_type_node, size_type_node, integer_type_node,
|
||||
pvoid_type_node, pvoid_type_node, pvoid_type_node, size_type_node,
|
||||
integer_type_node, pvoid_type_node, pvoid_type_node, integer_type_node,
|
||||
integer_type_node, boolean_type_node, integer_type_node);
|
||||
|
||||
gfor_fndecl_caf_get_by_ref = gfc_build_library_function_decl_with_spec (
|
||||
get_identifier (PREFIX("caf_get_by_ref")), ".RWRRRRRW", void_type_node,
|
||||
9, pvoid_type_node, integer_type_node, pvoid_type_node, pvoid_type_node,
|
||||
integer_type_node, integer_type_node, boolean_type_node,
|
||||
boolean_type_node, pint_type);
|
||||
|
||||
gfor_fndecl_caf_send_by_ref = gfc_build_library_function_decl_with_spec (
|
||||
get_identifier (PREFIX("caf_send_by_ref")), ".RRRRRRRW", void_type_node,
|
||||
9, pvoid_type_node, integer_type_node, pvoid_type_node, pvoid_type_node,
|
||||
integer_type_node, integer_type_node, boolean_type_node,
|
||||
boolean_type_node, pint_type);
|
||||
|
||||
gfor_fndecl_caf_sendget_by_ref
|
||||
= gfc_build_library_function_decl_with_spec (
|
||||
get_identifier (PREFIX("caf_sendget_by_ref")), ".RR.RRRRRWW",
|
||||
void_type_node, 11, pvoid_type_node, integer_type_node,
|
||||
pvoid_type_node, pvoid_type_node, integer_type_node,
|
||||
pvoid_type_node, integer_type_node, integer_type_node,
|
||||
boolean_type_node, pint_type, pint_type);
|
||||
|
||||
gfor_fndecl_caf_sync_all = gfc_build_library_function_decl_with_spec (
|
||||
get_identifier (PREFIX("caf_sync_all")), ".WW", void_type_node,
|
||||
@ -5002,9 +5025,11 @@ gfc_emit_parameter_debug_info (gfc_symbol *sym)
|
||||
static void
|
||||
generate_coarray_sym_init (gfc_symbol *sym)
|
||||
{
|
||||
tree tmp, size, decl, token;
|
||||
tree tmp, size, decl, token, desc;
|
||||
bool is_lock_type, is_event_type;
|
||||
int reg_type;
|
||||
gfc_se se;
|
||||
symbol_attribute attr;
|
||||
|
||||
if (sym->attr.dummy || sym->attr.allocatable || !sym->attr.codimension
|
||||
|| sym->attr.use_assoc || !sym->attr.referenced
|
||||
@ -5055,12 +5080,20 @@ generate_coarray_sym_init (gfc_symbol *sym)
|
||||
reg_type = GFC_CAF_EVENT_STATIC;
|
||||
else
|
||||
reg_type = GFC_CAF_COARRAY_STATIC;
|
||||
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_register, 6, size,
|
||||
|
||||
gfc_init_se (&se, NULL);
|
||||
desc = gfc_conv_scalar_to_descriptor (&se, decl, attr);
|
||||
gfc_add_block_to_block (&caf_init_block, &se.pre);
|
||||
|
||||
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_register, 7, size,
|
||||
build_int_cst (integer_type_node, reg_type),
|
||||
token, null_pointer_node, /* token, stat. */
|
||||
token, gfc_build_addr_expr (pvoid_type_node, desc),
|
||||
null_pointer_node, /* 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));
|
||||
gfc_add_expr_to_block (&caf_init_block, tmp);
|
||||
gfc_add_modify (&caf_init_block, decl, fold_convert (TREE_TYPE (decl),
|
||||
gfc_conv_descriptor_data_get (desc)));
|
||||
|
||||
/* Handle "static" initializer. */
|
||||
if (sym->value)
|
||||
|
@ -72,6 +72,13 @@ gfc_conv_scalar_to_descriptor (gfc_se *se, tree scalar, symbol_attribute attr)
|
||||
desc = gfc_create_var (type, "desc");
|
||||
DECL_ARTIFICIAL (desc) = 1;
|
||||
|
||||
if (CONSTANT_CLASS_P (scalar))
|
||||
{
|
||||
tree tmp;
|
||||
tmp = gfc_create_var (TREE_TYPE (scalar), "scalar");
|
||||
gfc_add_modify (&se->pre, tmp, scalar);
|
||||
scalar = tmp;
|
||||
}
|
||||
if (!POINTER_TYPE_P (TREE_TYPE (scalar)))
|
||||
scalar = gfc_build_addr_expr (NULL_TREE, scalar);
|
||||
gfc_add_modify (&se->pre, gfc_conv_descriptor_dtype (desc),
|
||||
@ -88,6 +95,56 @@ gfc_conv_scalar_to_descriptor (gfc_se *se, tree scalar, symbol_attribute attr)
|
||||
}
|
||||
|
||||
|
||||
/* Get the coarray token from the ultimate array or component ref.
|
||||
Returns a NULL_TREE, when the ref object is not allocatable or pointer. */
|
||||
|
||||
tree
|
||||
gfc_get_ultimate_alloc_ptr_comps_caf_token (gfc_se *outerse, gfc_expr *expr)
|
||||
{
|
||||
gfc_symbol *sym = expr->symtree->n.sym;
|
||||
bool is_coarray = sym->attr.codimension;
|
||||
gfc_expr *caf_expr = gfc_copy_expr (expr);
|
||||
gfc_ref *ref = caf_expr->ref, *last_caf_ref = NULL;
|
||||
|
||||
while (ref)
|
||||
{
|
||||
if (ref->type == REF_COMPONENT
|
||||
&& (ref->u.c.component->attr.allocatable
|
||||
|| ref->u.c.component->attr.pointer)
|
||||
&& (is_coarray || ref->u.c.component->attr.codimension))
|
||||
last_caf_ref = ref;
|
||||
ref = ref->next;
|
||||
}
|
||||
|
||||
if (last_caf_ref == NULL)
|
||||
return NULL_TREE;
|
||||
|
||||
tree comp = last_caf_ref->u.c.component->caf_token, caf;
|
||||
gfc_se se;
|
||||
bool comp_ref = !last_caf_ref->u.c.component->attr.dimension;
|
||||
if (comp == NULL_TREE && comp_ref)
|
||||
return NULL_TREE;
|
||||
gfc_init_se (&se, outerse);
|
||||
gfc_free_ref_list (last_caf_ref->next);
|
||||
last_caf_ref->next = NULL;
|
||||
caf_expr->rank = comp_ref ? 0 : last_caf_ref->u.c.component->as->rank;
|
||||
se.want_pointer = comp_ref;
|
||||
gfc_conv_expr (&se, caf_expr);
|
||||
gfc_add_block_to_block (&outerse->pre, &se.pre);
|
||||
|
||||
if (TREE_CODE (se.expr) == COMPONENT_REF && comp_ref)
|
||||
se.expr = TREE_OPERAND (se.expr, 0);
|
||||
gfc_free_expr (caf_expr);
|
||||
|
||||
if (comp_ref)
|
||||
caf = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (comp), se.expr, comp, NULL_TREE);
|
||||
else
|
||||
caf = gfc_conv_descriptor_token (se.expr);
|
||||
return gfc_build_addr_expr (NULL_TREE, caf);
|
||||
}
|
||||
|
||||
|
||||
/* This is the seed for an eventual trans-class.c
|
||||
|
||||
The following parameters should not be used directly since they might
|
||||
@ -1827,69 +1884,51 @@ gfc_get_tree_for_caf_expr (gfc_expr *expr)
|
||||
{
|
||||
tree caf_decl;
|
||||
bool found = false;
|
||||
gfc_ref *ref, *comp_ref = NULL;
|
||||
gfc_ref *ref;
|
||||
|
||||
gcc_assert (expr && expr->expr_type == EXPR_VARIABLE);
|
||||
|
||||
/* Not-implemented diagnostic. */
|
||||
if (expr->symtree->n.sym->ts.type == BT_CLASS
|
||||
&& UNLIMITED_POLY (expr->symtree->n.sym)
|
||||
&& CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
|
||||
gfc_error ("Sorry, coindexed access to an unlimited polymorphic object at "
|
||||
"%L is not supported", &expr->where);
|
||||
|
||||
for (ref = expr->ref; ref; ref = ref->next)
|
||||
if (ref->type == REF_COMPONENT)
|
||||
{
|
||||
comp_ref = ref;
|
||||
if ((ref->u.c.component->ts.type == BT_CLASS
|
||||
&& !CLASS_DATA (ref->u.c.component)->attr.codimension
|
||||
&& (CLASS_DATA (ref->u.c.component)->attr.pointer
|
||||
|| CLASS_DATA (ref->u.c.component)->attr.allocatable))
|
||||
|| (ref->u.c.component->ts.type != BT_CLASS
|
||||
&& !ref->u.c.component->attr.codimension
|
||||
&& (ref->u.c.component->attr.pointer
|
||||
|| ref->u.c.component->attr.allocatable)))
|
||||
gfc_error ("Sorry, coindexed access to a pointer or allocatable "
|
||||
"component of the coindexed coarray at %L is not yet "
|
||||
"supported", &expr->where);
|
||||
if (ref->u.c.component->ts.type == BT_CLASS
|
||||
&& UNLIMITED_POLY (ref->u.c.component)
|
||||
&& CLASS_DATA (ref->u.c.component)->attr.codimension)
|
||||
gfc_error ("Sorry, coindexed access to an unlimited polymorphic "
|
||||
"component at %L is not supported", &expr->where);
|
||||
}
|
||||
if ((!comp_ref
|
||||
&& ((expr->symtree->n.sym->ts.type == BT_CLASS
|
||||
&& CLASS_DATA (expr->symtree->n.sym)->attr.alloc_comp)
|
||||
|| (expr->symtree->n.sym->ts.type == BT_DERIVED
|
||||
&& expr->symtree->n.sym->ts.u.derived->attr.alloc_comp)))
|
||||
|| (comp_ref
|
||||
&& ((comp_ref->u.c.component->ts.type == BT_CLASS
|
||||
&& CLASS_DATA (comp_ref->u.c.component)->attr.alloc_comp)
|
||||
|| (comp_ref->u.c.component->ts.type == BT_DERIVED
|
||||
&& comp_ref->u.c.component->ts.u.derived->attr.alloc_comp))))
|
||||
gfc_error ("Sorry, coindexed coarray at %L with allocatable component is "
|
||||
"not yet supported", &expr->where);
|
||||
|
||||
if (expr->rank)
|
||||
{
|
||||
/* Without the new array descriptor, access like "caf[i]%a(:)%b" is in
|
||||
general not possible as the required stride multiplier might be not
|
||||
a multiple of c_sizeof(b). In case of noncoindexed access, the
|
||||
scalarizer often takes care of it - for coarrays, it always fails. */
|
||||
for (ref = expr->ref; ref; ref = ref->next)
|
||||
if (ref->type == REF_COMPONENT
|
||||
&& ((ref->u.c.component->ts.type == BT_CLASS
|
||||
&& CLASS_DATA (ref->u.c.component)->attr.codimension)
|
||||
|| (ref->u.c.component->ts.type != BT_CLASS
|
||||
&& ref->u.c.component->attr.codimension)))
|
||||
break;
|
||||
if (ref == NULL)
|
||||
ref = expr->ref;
|
||||
for ( ; ref; ref = ref->next)
|
||||
if (ref->type == REF_ARRAY && ref->u.ar.dimen)
|
||||
break;
|
||||
for ( ; ref; ref = ref->next)
|
||||
if (ref->type == REF_COMPONENT)
|
||||
gfc_error ("Sorry, coindexed access at %L to a scalar component "
|
||||
"with an array partref is not yet supported",
|
||||
&expr->where);
|
||||
}
|
||||
|
||||
caf_decl = expr->symtree->n.sym->backend_decl;
|
||||
gcc_assert (caf_decl);
|
||||
if (expr->symtree->n.sym->ts.type == BT_CLASS)
|
||||
caf_decl = gfc_class_data_get (caf_decl);
|
||||
{
|
||||
if (expr->ref && expr->ref->type == REF_ARRAY)
|
||||
{
|
||||
caf_decl = gfc_class_data_get (caf_decl);
|
||||
if (CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
|
||||
return caf_decl;
|
||||
}
|
||||
for (ref = expr->ref; ref; ref = ref->next)
|
||||
{
|
||||
if (ref->type == REF_COMPONENT
|
||||
&& strcmp (ref->u.c.component->name, "_data") != 0)
|
||||
{
|
||||
caf_decl = gfc_class_data_get (caf_decl);
|
||||
if (CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
|
||||
return caf_decl;
|
||||
break;
|
||||
}
|
||||
else if (ref->type == REF_ARRAY && ref->u.ar.dimen)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (expr->symtree->n.sym->attr.codimension)
|
||||
return caf_decl;
|
||||
|
||||
@ -1907,7 +1946,14 @@ gfc_get_tree_for_caf_expr (gfc_expr *expr)
|
||||
TREE_TYPE (comp->backend_decl), caf_decl,
|
||||
comp->backend_decl, NULL_TREE);
|
||||
if (comp->ts.type == BT_CLASS)
|
||||
caf_decl = gfc_class_data_get (caf_decl);
|
||||
{
|
||||
caf_decl = gfc_class_data_get (caf_decl);
|
||||
if (CLASS_DATA (comp)->attr.codimension)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (comp->attr.codimension)
|
||||
{
|
||||
found = true;
|
||||
@ -1922,8 +1968,8 @@ gfc_get_tree_for_caf_expr (gfc_expr *expr)
|
||||
/* Obtain the Coarray token - and optionally also the offset. */
|
||||
|
||||
void
|
||||
gfc_get_caf_token_offset (tree *token, tree *offset, tree caf_decl, tree se_expr,
|
||||
gfc_expr *expr)
|
||||
gfc_get_caf_token_offset (gfc_se *se, tree *token, tree *offset, tree caf_decl,
|
||||
tree se_expr, gfc_expr *expr)
|
||||
{
|
||||
tree tmp;
|
||||
|
||||
@ -1978,7 +2024,47 @@ gfc_get_caf_token_offset (tree *token, tree *offset, tree caf_decl, tree se_expr
|
||||
*offset = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
|
||||
*offset, fold_convert (gfc_array_index_type, tmp));
|
||||
|
||||
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_decl)))
|
||||
if (expr->symtree->n.sym->ts.type == BT_DERIVED
|
||||
&& expr->symtree->n.sym->attr.codimension
|
||||
&& expr->symtree->n.sym->ts.u.derived->attr.alloc_comp)
|
||||
{
|
||||
gfc_expr *base_expr = gfc_copy_expr (expr);
|
||||
gfc_ref *ref = base_expr->ref;
|
||||
gfc_se base_se;
|
||||
|
||||
// Iterate through the refs until the last one.
|
||||
while (ref->next)
|
||||
ref = ref->next;
|
||||
|
||||
if (ref->type == REF_ARRAY
|
||||
&& ref->u.ar.type != AR_FULL)
|
||||
{
|
||||
const int ranksum = ref->u.ar.dimen + ref->u.ar.codimen;
|
||||
int i;
|
||||
for (i = 0; i < ranksum; ++i)
|
||||
{
|
||||
ref->u.ar.start[i] = NULL;
|
||||
ref->u.ar.end[i] = NULL;
|
||||
}
|
||||
ref->u.ar.type = AR_FULL;
|
||||
}
|
||||
gfc_init_se (&base_se, NULL);
|
||||
if (gfc_caf_attr (base_expr).dimension)
|
||||
{
|
||||
gfc_conv_expr_descriptor (&base_se, base_expr);
|
||||
tmp = gfc_conv_descriptor_data_get (base_se.expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
gfc_conv_expr (&base_se, base_expr);
|
||||
tmp = base_se.expr;
|
||||
}
|
||||
|
||||
gfc_free_expr (base_expr);
|
||||
gfc_add_block_to_block (&se->pre, &base_se.pre);
|
||||
gfc_add_block_to_block (&se->post, &base_se.post);
|
||||
}
|
||||
else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_decl)))
|
||||
tmp = gfc_conv_descriptor_data_get (caf_decl);
|
||||
else
|
||||
{
|
||||
@ -2009,6 +2095,12 @@ gfc_caf_get_image_index (stmtblock_t *block, gfc_expr *e, tree desc)
|
||||
break;
|
||||
gcc_assert (ref != NULL);
|
||||
|
||||
if (ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE)
|
||||
{
|
||||
return build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
|
||||
integer_zero_node);
|
||||
}
|
||||
|
||||
img_idx = integer_zero_node;
|
||||
extent = integer_one_node;
|
||||
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
|
||||
@ -4647,10 +4739,11 @@ expr_may_alias_variables (gfc_expr *e, bool array_may_alias)
|
||||
{
|
||||
gfc_symbol *proc_ifc = gfc_get_proc_ifc_for_expr (e);
|
||||
|
||||
if ((proc_ifc->result->ts.type == BT_CLASS
|
||||
&& proc_ifc->result->ts.u.derived->attr.is_class
|
||||
&& CLASS_DATA (proc_ifc->result)->attr.class_pointer)
|
||||
|| proc_ifc->result->attr.pointer)
|
||||
if (proc_ifc->result != NULL
|
||||
&& ((proc_ifc->result->ts.type == BT_CLASS
|
||||
&& proc_ifc->result->ts.u.derived->attr.is_class
|
||||
&& CLASS_DATA (proc_ifc->result)->attr.class_pointer)
|
||||
|| proc_ifc->result->attr.pointer))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
@ -9064,7 +9157,25 @@ alloc_scalar_allocatable_for_assignment (stmtblock_t *block,
|
||||
size_in_bytes = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
|
||||
size_in_bytes, size_one_node);
|
||||
|
||||
if (expr1->ts.type == BT_DERIVED && expr1->ts.u.derived->attr.alloc_comp)
|
||||
if (gfc_caf_attr (expr1).codimension && flag_coarray == GFC_FCOARRAY_LIB)
|
||||
{
|
||||
tree caf_decl, token;
|
||||
gfc_se caf_se;
|
||||
symbol_attribute attr;
|
||||
|
||||
gfc_clear_attr (&attr);
|
||||
gfc_init_se (&caf_se, NULL);
|
||||
|
||||
caf_decl = gfc_get_tree_for_caf_expr (expr1);
|
||||
gfc_get_caf_token_offset (&caf_se, &token, NULL, caf_decl, NULL_TREE,
|
||||
NULL);
|
||||
gfc_add_block_to_block (block, &caf_se.pre);
|
||||
gfc_allocate_allocatable (block, lse.expr, size_in_bytes,
|
||||
gfc_build_addr_expr (NULL_TREE, token),
|
||||
NULL_TREE, NULL_TREE, NULL_TREE, jump_label1,
|
||||
expr1, 1);
|
||||
}
|
||||
else if (expr1->ts.type == BT_DERIVED && expr1->ts.u.derived->attr.alloc_comp)
|
||||
{
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
builtin_decl_explicit (BUILT_IN_CALLOC),
|
||||
@ -9242,6 +9353,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
|
||||
tree string_length;
|
||||
int n;
|
||||
bool maybe_workshare = false;
|
||||
symbol_attribute lhs_caf_attr, rhs_caf_attr;
|
||||
|
||||
/* Assignment of the form lhs = rhs. */
|
||||
gfc_start_block (&block);
|
||||
@ -9262,6 +9374,9 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
|
||||
|| gfc_is_alloc_class_scalar_function (expr2)))
|
||||
expr2->must_finalize = 1;
|
||||
|
||||
lhs_caf_attr = gfc_caf_attr (expr1);
|
||||
rhs_caf_attr = gfc_caf_attr (expr2);
|
||||
|
||||
if (lss != gfc_ss_terminator)
|
||||
{
|
||||
/* The assignment needs scalarization. */
|
||||
@ -9440,10 +9555,26 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
|
||||
gfc_add_block_to_block (&loop.post, &rse.post);
|
||||
}
|
||||
|
||||
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
|
||||
gfc_expr_is_variable (expr2) || scalar_to_array
|
||||
|| expr2->expr_type == EXPR_ARRAY,
|
||||
!(l_is_temp || init_flag) && dealloc);
|
||||
if (flag_coarray == GFC_FCOARRAY_LIB
|
||||
&& lhs_caf_attr.codimension && rhs_caf_attr.codimension
|
||||
&& lhs_caf_attr.alloc_comp && rhs_caf_attr.alloc_comp)
|
||||
{
|
||||
gfc_code code;
|
||||
gfc_actual_arglist a1, a2;
|
||||
a1.expr = expr1;
|
||||
a1.next = &a2;
|
||||
a2.expr = expr2;
|
||||
a2.next = NULL;
|
||||
code.ext.actual = &a1;
|
||||
code.resolved_isym = gfc_intrinsic_subroutine_by_id (GFC_ISYM_CAF_SEND);
|
||||
tmp = gfc_conv_intrinsic_subroutine (&code);
|
||||
}
|
||||
else
|
||||
tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
|
||||
gfc_expr_is_variable (expr2)
|
||||
|| scalar_to_array
|
||||
|| expr2->expr_type == EXPR_ARRAY,
|
||||
!(l_is_temp || init_flag) && dealloc);
|
||||
gfc_add_expr_to_block (&body, tmp);
|
||||
|
||||
if (lss == gfc_ss_terminator)
|
||||
@ -9490,11 +9621,9 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
|
||||
|
||||
/* F2003: Allocate or reallocate lhs of allocatable array. */
|
||||
if (flag_realloc_lhs
|
||||
&& gfc_is_reallocatable_lhs (expr1)
|
||||
&& !gfc_expr_attr (expr1).codimension
|
||||
&& !gfc_is_coindexed (expr1)
|
||||
&& expr2->rank
|
||||
&& !is_runtime_conformable (expr1, expr2))
|
||||
&& gfc_is_reallocatable_lhs (expr1)
|
||||
&& expr2->rank
|
||||
&& !is_runtime_conformable (expr1, expr2))
|
||||
{
|
||||
realloc_lhs_warning (expr1->ts.type, true, &expr1->where);
|
||||
ompws_flags &= ~OMPWS_SCALARIZER_WS;
|
||||
|
@ -982,7 +982,7 @@ conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
|
||||
|
||||
if (vector != NULL_TREE)
|
||||
{
|
||||
/* Set dim.lower/upper/stride. */
|
||||
/* Set vector and kind. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (type), 0);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
|
||||
desc, field, NULL_TREE);
|
||||
@ -994,7 +994,7 @@ conv_caf_vector_subscript_elem (stmtblock_t *block, int i, tree desc,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set vector and kind. */
|
||||
/* Set dim.lower/upper/stride. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (type), 0);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
|
||||
desc, field, NULL_TREE);
|
||||
@ -1094,16 +1094,481 @@ conv_caf_vector_subscript (stmtblock_t *block, tree desc, gfc_array_ref *ar)
|
||||
}
|
||||
|
||||
|
||||
static tree
|
||||
compute_component_offset (tree field, tree type)
|
||||
{
|
||||
tree tmp;
|
||||
if (DECL_FIELD_BIT_OFFSET (field) != NULL_TREE
|
||||
&& !integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
|
||||
{
|
||||
tmp = fold_build2 (TRUNC_DIV_EXPR, type,
|
||||
DECL_FIELD_BIT_OFFSET (field),
|
||||
bitsize_unit_node);
|
||||
return fold_build2 (PLUS_EXPR, type, DECL_FIELD_OFFSET (field), tmp);
|
||||
}
|
||||
else
|
||||
return DECL_FIELD_OFFSET (field);
|
||||
}
|
||||
|
||||
|
||||
static tree
|
||||
conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr)
|
||||
{
|
||||
gfc_ref *ref = expr->ref;
|
||||
tree caf_ref = NULL_TREE, prev_caf_ref = NULL_TREE, reference_type, tmp, tmp2,
|
||||
field, last_type, inner_struct, mode, mode_rhs, dim_array, dim, dim_type,
|
||||
start, end, stride, vector, nvec;
|
||||
gfc_se se;
|
||||
bool ref_static_array = false;
|
||||
tree last_component_ref_tree = NULL_TREE;
|
||||
int i, last_type_n;
|
||||
|
||||
if (expr->symtree)
|
||||
{
|
||||
last_component_ref_tree = expr->symtree->n.sym->backend_decl;
|
||||
ref_static_array = !expr->symtree->n.sym->attr.allocatable;
|
||||
}
|
||||
|
||||
/* Prevent uninit-warning. */
|
||||
reference_type = NULL_TREE;
|
||||
last_type = gfc_typenode_for_spec (&expr->symtree->n.sym->ts);
|
||||
last_type_n = expr->symtree->n.sym->ts.type;
|
||||
while (ref)
|
||||
{
|
||||
if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0
|
||||
&& ref->u.ar.dimen == 0)
|
||||
{
|
||||
/* Skip pure coindexes. */
|
||||
ref = ref->next;
|
||||
continue;
|
||||
}
|
||||
tmp = gfc_create_var (gfc_get_caf_reference_type (), "caf_ref");
|
||||
reference_type = TREE_TYPE (tmp);
|
||||
|
||||
if (caf_ref == NULL_TREE)
|
||||
caf_ref = tmp;
|
||||
|
||||
/* Construct the chain of refs. */
|
||||
if (prev_caf_ref != NULL_TREE)
|
||||
{
|
||||
field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
|
||||
tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), prev_caf_ref, field,
|
||||
NULL_TREE);
|
||||
gfc_add_modify (block, tmp2, gfc_build_addr_expr (TREE_TYPE (field),
|
||||
tmp));
|
||||
}
|
||||
prev_caf_ref = tmp;
|
||||
|
||||
switch (ref->type)
|
||||
{
|
||||
case REF_COMPONENT:
|
||||
last_type = gfc_typenode_for_spec (&ref->u.c.component->ts);
|
||||
last_type_n = ref->u.c.component->ts.type;
|
||||
/* Set the type of the ref. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), prev_caf_ref, field,
|
||||
NULL_TREE);
|
||||
gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
|
||||
GFC_CAF_REF_COMPONENT));
|
||||
|
||||
/* Ref the c in union u. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), prev_caf_ref, field,
|
||||
NULL_TREE);
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 0);
|
||||
inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), tmp, field,
|
||||
NULL_TREE);
|
||||
|
||||
/* Set the offset. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), inner_struct, field,
|
||||
NULL_TREE);
|
||||
/* Computing the offset is somewhat harder. The bit_offset has to be
|
||||
taken into account. When the bit_offset in the field_decl is non-
|
||||
null, divide it by the bitsize_unit and add it to the regular
|
||||
offset. */
|
||||
tmp2 = compute_component_offset (ref->u.c.component->backend_decl,
|
||||
TREE_TYPE (tmp));
|
||||
gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
|
||||
|
||||
/* Set caf_token_offset. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 1);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), inner_struct, field,
|
||||
NULL_TREE);
|
||||
if (ref->u.c.component->attr.allocatable
|
||||
&& ref->u.c.component->attr.dimension)
|
||||
{
|
||||
tree arr_desc_token_offset;
|
||||
/* Get the token from the descriptor. */
|
||||
arr_desc_token_offset = gfc_advance_chain (
|
||||
TYPE_FIELDS (TREE_TYPE (ref->u.c.component->backend_decl)),
|
||||
4 /* CAF_TOKEN_FIELD */);
|
||||
arr_desc_token_offset
|
||||
= compute_component_offset (arr_desc_token_offset,
|
||||
TREE_TYPE (tmp));
|
||||
tmp2 = fold_build2_loc (input_location, PLUS_EXPR,
|
||||
TREE_TYPE (tmp2), tmp2,
|
||||
arr_desc_token_offset);
|
||||
}
|
||||
else if (ref->u.c.component->caf_token)
|
||||
tmp2 = compute_component_offset (ref->u.c.component->caf_token,
|
||||
TREE_TYPE (tmp));
|
||||
else
|
||||
tmp2 = integer_zero_node;
|
||||
gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
|
||||
|
||||
/* Remember whether this ref was to a non-allocatable/non-pointer
|
||||
component so the next array ref can be tailored correctly. */
|
||||
ref_static_array = !ref->u.c.component->attr.allocatable;
|
||||
last_component_ref_tree = ref_static_array
|
||||
? ref->u.c.component->backend_decl : NULL_TREE;
|
||||
break;
|
||||
case REF_ARRAY:
|
||||
if (ref_static_array && ref->u.ar.as->type == AS_DEFERRED)
|
||||
ref_static_array = false;
|
||||
/* Set the type of the ref. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (reference_type), 1);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), prev_caf_ref, field,
|
||||
NULL_TREE);
|
||||
gfc_add_modify (block, tmp, build_int_cst (integer_type_node,
|
||||
ref_static_array
|
||||
? GFC_CAF_REF_STATIC_ARRAY
|
||||
: GFC_CAF_REF_ARRAY));
|
||||
|
||||
/* Ref the a in union u. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (reference_type), 3);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), prev_caf_ref, field,
|
||||
NULL_TREE);
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (field)), 1);
|
||||
inner_struct = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), tmp, field,
|
||||
NULL_TREE);
|
||||
|
||||
/* Set the static_array_type in a for static arrays. */
|
||||
if (ref_static_array)
|
||||
{
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)),
|
||||
1);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), inner_struct, field,
|
||||
NULL_TREE);
|
||||
gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (tmp),
|
||||
last_type_n));
|
||||
}
|
||||
/* Ref the mode in the inner_struct. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 0);
|
||||
mode = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), inner_struct, field,
|
||||
NULL_TREE);
|
||||
/* Ref the dim in the inner_struct. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (inner_struct)), 2);
|
||||
dim_array = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), inner_struct, field,
|
||||
NULL_TREE);
|
||||
for (i = 0; i < ref->u.ar.dimen; ++i)
|
||||
{
|
||||
/* Ref dim i. */
|
||||
dim = gfc_build_array_ref (dim_array, gfc_rank_cst[i], NULL_TREE);
|
||||
dim_type = TREE_TYPE (dim);
|
||||
mode_rhs = start = end = stride = NULL_TREE;
|
||||
switch (ref->u.ar.dimen_type[i])
|
||||
{
|
||||
case DIMEN_RANGE:
|
||||
if (ref->u.ar.end[i])
|
||||
{
|
||||
gfc_init_se (&se, NULL);
|
||||
gfc_conv_expr (&se, ref->u.ar.end[i]);
|
||||
gfc_add_block_to_block (block, &se.pre);
|
||||
if (ref_static_array)
|
||||
{
|
||||
/* Make the index zero-based, when reffing a static
|
||||
array. */
|
||||
end = se.expr;
|
||||
gfc_init_se (&se, NULL);
|
||||
gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
|
||||
gfc_add_block_to_block (block, &se.pre);
|
||||
se.expr = fold_build2 (MINUS_EXPR,
|
||||
gfc_array_index_type,
|
||||
end, fold_convert (
|
||||
gfc_array_index_type,
|
||||
se.expr));
|
||||
}
|
||||
end = gfc_evaluate_now (fold_convert (
|
||||
gfc_array_index_type,
|
||||
se.expr),
|
||||
block);
|
||||
}
|
||||
else if (ref_static_array)
|
||||
end = fold_build2 (MINUS_EXPR,
|
||||
gfc_array_index_type,
|
||||
gfc_conv_array_ubound (
|
||||
last_component_ref_tree, i),
|
||||
gfc_conv_array_lbound (
|
||||
last_component_ref_tree, i));
|
||||
else
|
||||
{
|
||||
end = NULL_TREE;
|
||||
mode_rhs = build_int_cst (unsigned_char_type_node,
|
||||
GFC_CAF_ARR_REF_OPEN_END);
|
||||
}
|
||||
if (ref->u.ar.stride[i])
|
||||
{
|
||||
gfc_init_se (&se, NULL);
|
||||
gfc_conv_expr (&se, ref->u.ar.stride[i]);
|
||||
gfc_add_block_to_block (block, &se.pre);
|
||||
stride = gfc_evaluate_now (fold_convert (
|
||||
gfc_array_index_type,
|
||||
se.expr),
|
||||
block);
|
||||
if (ref_static_array)
|
||||
{
|
||||
/* Make the index zero-based, when reffing a static
|
||||
array. */
|
||||
stride = fold_build2 (MULT_EXPR,
|
||||
gfc_array_index_type,
|
||||
gfc_conv_array_stride (
|
||||
last_component_ref_tree,
|
||||
i),
|
||||
stride);
|
||||
gcc_assert (end != NULL_TREE);
|
||||
/* Multiply with the product of array's stride and
|
||||
the step of the ref to a virtual upper bound.
|
||||
We can not compute the actual upper bound here or
|
||||
the caflib would compute the extend
|
||||
incorrectly. */
|
||||
end = fold_build2 (MULT_EXPR, gfc_array_index_type,
|
||||
end, gfc_conv_array_stride (
|
||||
last_component_ref_tree,
|
||||
i));
|
||||
end = gfc_evaluate_now (end, block);
|
||||
stride = gfc_evaluate_now (stride, block);
|
||||
}
|
||||
}
|
||||
else if (ref_static_array)
|
||||
{
|
||||
stride = gfc_conv_array_stride (last_component_ref_tree,
|
||||
i);
|
||||
end = fold_build2 (MULT_EXPR, gfc_array_index_type,
|
||||
end, stride);
|
||||
end = gfc_evaluate_now (end, block);
|
||||
}
|
||||
else
|
||||
/* Always set a ref stride of one to make caflib's
|
||||
handling easier. */
|
||||
stride = gfc_index_one_node;
|
||||
|
||||
/* Intentionally fall through. */
|
||||
case DIMEN_ELEMENT:
|
||||
if (ref->u.ar.start[i])
|
||||
{
|
||||
gfc_init_se (&se, NULL);
|
||||
gfc_conv_expr (&se, ref->u.ar.start[i]);
|
||||
gfc_add_block_to_block (block, &se.pre);
|
||||
if (ref_static_array)
|
||||
{
|
||||
/* Make the index zero-based, when reffing a static
|
||||
array. */
|
||||
start = fold_convert (gfc_array_index_type, se.expr);
|
||||
gfc_init_se (&se, NULL);
|
||||
gfc_conv_expr (&se, ref->u.ar.as->lower[i]);
|
||||
gfc_add_block_to_block (block, &se.pre);
|
||||
se.expr = fold_build2 (MINUS_EXPR,
|
||||
gfc_array_index_type,
|
||||
start, fold_convert (
|
||||
gfc_array_index_type,
|
||||
se.expr));
|
||||
/* Multiply with the stride. */
|
||||
se.expr = fold_build2 (MULT_EXPR,
|
||||
gfc_array_index_type,
|
||||
se.expr,
|
||||
gfc_conv_array_stride (
|
||||
last_component_ref_tree,
|
||||
i));
|
||||
}
|
||||
start = gfc_evaluate_now (fold_convert (
|
||||
gfc_array_index_type,
|
||||
se.expr),
|
||||
block);
|
||||
if (mode_rhs == NULL_TREE)
|
||||
mode_rhs = build_int_cst (unsigned_char_type_node,
|
||||
ref->u.ar.dimen_type[i]
|
||||
== DIMEN_ELEMENT
|
||||
? GFC_CAF_ARR_REF_SINGLE
|
||||
: GFC_CAF_ARR_REF_RANGE);
|
||||
}
|
||||
else if (ref_static_array)
|
||||
{
|
||||
start = integer_zero_node;
|
||||
mode_rhs = build_int_cst (unsigned_char_type_node,
|
||||
ref->u.ar.start[i] == NULL
|
||||
? GFC_CAF_ARR_REF_FULL
|
||||
: GFC_CAF_ARR_REF_RANGE);
|
||||
}
|
||||
else if (end == NULL_TREE)
|
||||
mode_rhs = build_int_cst (unsigned_char_type_node,
|
||||
GFC_CAF_ARR_REF_FULL);
|
||||
else
|
||||
mode_rhs = build_int_cst (unsigned_char_type_node,
|
||||
GFC_CAF_ARR_REF_OPEN_START);
|
||||
|
||||
/* Ref the s in dim. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (dim_type), 0);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), dim, field,
|
||||
NULL_TREE);
|
||||
|
||||
/* Set start in s. */
|
||||
if (start != NULL_TREE)
|
||||
{
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
|
||||
0);
|
||||
tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), tmp, field,
|
||||
NULL_TREE);
|
||||
gfc_add_modify (block, tmp2,
|
||||
fold_convert (TREE_TYPE (tmp2), start));
|
||||
}
|
||||
|
||||
/* Set end in s. */
|
||||
if (end != NULL_TREE)
|
||||
{
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
|
||||
1);
|
||||
tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), tmp, field,
|
||||
NULL_TREE);
|
||||
gfc_add_modify (block, tmp2,
|
||||
fold_convert (TREE_TYPE (tmp2), end));
|
||||
}
|
||||
|
||||
/* Set end in s. */
|
||||
if (stride != NULL_TREE)
|
||||
{
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)),
|
||||
2);
|
||||
tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), tmp, field,
|
||||
NULL_TREE);
|
||||
gfc_add_modify (block, tmp2,
|
||||
fold_convert (TREE_TYPE (tmp2), stride));
|
||||
}
|
||||
break;
|
||||
case DIMEN_VECTOR:
|
||||
/* TODO: In case of static array. */
|
||||
gcc_assert (!ref_static_array);
|
||||
mode_rhs = build_int_cst (unsigned_char_type_node,
|
||||
GFC_CAF_ARR_REF_VECTOR);
|
||||
gfc_init_se (&se, NULL);
|
||||
se.descriptor_only = 1;
|
||||
gfc_conv_expr_descriptor (&se, ref->u.ar.start[i]);
|
||||
gfc_add_block_to_block (block, &se.pre);
|
||||
vector = se.expr;
|
||||
tmp = gfc_conv_descriptor_lbound_get (vector,
|
||||
gfc_rank_cst[0]);
|
||||
tmp2 = gfc_conv_descriptor_ubound_get (vector,
|
||||
gfc_rank_cst[0]);
|
||||
nvec = gfc_conv_array_extent_dim (tmp, tmp2, NULL);
|
||||
tmp = gfc_conv_descriptor_stride_get (vector,
|
||||
gfc_rank_cst[0]);
|
||||
nvec = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
|
||||
TREE_TYPE (nvec), nvec, tmp);
|
||||
vector = gfc_conv_descriptor_data_get (vector);
|
||||
|
||||
/* Ref the v in dim. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (dim_type), 1);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), dim, field,
|
||||
NULL_TREE);
|
||||
|
||||
/* Set vector in v. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 0);
|
||||
tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), tmp, field,
|
||||
NULL_TREE);
|
||||
gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
|
||||
vector));
|
||||
|
||||
/* Set nvec in v. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 1);
|
||||
tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), tmp, field,
|
||||
NULL_TREE);
|
||||
gfc_add_modify (block, tmp2, fold_convert (TREE_TYPE (tmp2),
|
||||
nvec));
|
||||
|
||||
/* Set kind in v. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), 2);
|
||||
tmp2 = fold_build3_loc (input_location, COMPONENT_REF,
|
||||
TREE_TYPE (field), tmp, field,
|
||||
NULL_TREE);
|
||||
gfc_add_modify (block, tmp2, build_int_cst (integer_type_node,
|
||||
ref->u.ar.start[i]->ts.kind));
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
/* Set the mode for dim i. */
|
||||
tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
|
||||
gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (tmp),
|
||||
mode_rhs));
|
||||
}
|
||||
|
||||
/* Set the mode for dim i+1 to GFC_ARR_REF_NONE. */
|
||||
if (i < GFC_MAX_DIMENSIONS)
|
||||
{
|
||||
tmp = gfc_build_array_ref (mode, gfc_rank_cst[i], NULL_TREE);
|
||||
gfc_add_modify (block, tmp,
|
||||
build_int_cst (unsigned_char_type_node,
|
||||
GFC_CAF_ARR_REF_NONE));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Set the size of the current type. */
|
||||
field = gfc_advance_chain (TYPE_FIELDS (reference_type), 2);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
|
||||
prev_caf_ref, field, NULL_TREE);
|
||||
gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
|
||||
TYPE_SIZE_UNIT (last_type)));
|
||||
|
||||
ref = ref->next;
|
||||
}
|
||||
|
||||
if (prev_caf_ref != NULL_TREE)
|
||||
{
|
||||
field = gfc_advance_chain (TYPE_FIELDS (reference_type), 0);
|
||||
tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
|
||||
prev_caf_ref, field, NULL_TREE);
|
||||
gfc_add_modify (block, tmp, fold_convert (TREE_TYPE (field),
|
||||
null_pointer_node));
|
||||
}
|
||||
return caf_ref != NULL_TREE ? gfc_build_addr_expr (NULL_TREE, caf_ref)
|
||||
: NULL_TREE;
|
||||
}
|
||||
|
||||
/* Get data from a remote coarray. */
|
||||
|
||||
static void
|
||||
gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
|
||||
tree may_require_tmp)
|
||||
tree may_require_tmp, bool may_realloc,
|
||||
symbol_attribute *caf_attr)
|
||||
{
|
||||
gfc_expr *array_expr, *tmp_stat;
|
||||
gfc_se argse;
|
||||
tree caf_decl, token, offset, image_index, tmp;
|
||||
tree res_var, dst_var, type, kind, vec, stat;
|
||||
tree caf_reference;
|
||||
symbol_attribute caf_attr_store;
|
||||
|
||||
gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
|
||||
|
||||
@ -1118,6 +1583,12 @@ gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
|
||||
array_expr = (lhs == NULL_TREE) ? expr->value.function.actual->expr : expr;
|
||||
type = gfc_typenode_for_spec (&array_expr->ts);
|
||||
|
||||
if (caf_attr == NULL)
|
||||
{
|
||||
caf_attr_store = gfc_caf_attr (array_expr);
|
||||
caf_attr = &caf_attr_store;
|
||||
}
|
||||
|
||||
res_var = lhs;
|
||||
dst_var = lhs;
|
||||
|
||||
@ -1136,6 +1607,108 @@ gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
|
||||
else
|
||||
stat = null_pointer_node;
|
||||
|
||||
/* Always use the new get_by_ref (). When no allocatable components are
|
||||
present and the lhs does not reallocation then the "old" get () might
|
||||
suffice. */
|
||||
if (true) //caf_attr->alloc_comp && !may_realloc)
|
||||
{
|
||||
/* Get using caf_get_by_ref. */
|
||||
caf_reference = conv_expr_ref_to_caf_ref (&se->pre, array_expr);
|
||||
|
||||
if (caf_reference != NULL_TREE)
|
||||
{
|
||||
if (lhs == NULL_TREE)
|
||||
{
|
||||
if (array_expr->ts.type == BT_CHARACTER)
|
||||
gfc_init_se (&argse, NULL);
|
||||
if (array_expr->rank == 0)
|
||||
{
|
||||
symbol_attribute attr;
|
||||
gfc_clear_attr (&attr);
|
||||
if (array_expr->ts.type == BT_CHARACTER)
|
||||
{
|
||||
res_var = gfc_conv_string_tmp (se,
|
||||
build_pointer_type (type),
|
||||
array_expr->ts.u.cl->backend_decl);
|
||||
argse.string_length = array_expr->ts.u.cl->backend_decl;
|
||||
}
|
||||
else
|
||||
res_var = gfc_create_var (type, "caf_res");
|
||||
dst_var = gfc_conv_scalar_to_descriptor (se, res_var, attr);
|
||||
dst_var = gfc_build_addr_expr (NULL_TREE, dst_var);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create temporary. */
|
||||
if (array_expr->ts.type == BT_CHARACTER)
|
||||
gfc_conv_expr_descriptor (&argse, array_expr);
|
||||
may_realloc = gfc_trans_create_temp_array (&se->pre,
|
||||
&se->post,
|
||||
se->ss, type,
|
||||
NULL_TREE, false,
|
||||
false, false,
|
||||
&array_expr->where)
|
||||
== NULL_TREE;
|
||||
res_var = se->ss->info->data.array.descriptor;
|
||||
dst_var = gfc_build_addr_expr (NULL_TREE, res_var);
|
||||
if (may_realloc)
|
||||
{
|
||||
tmp = gfc_conv_descriptor_data_get (res_var);
|
||||
tmp = gfc_deallocate_with_status (tmp, NULL_TREE,
|
||||
NULL_TREE, NULL_TREE,
|
||||
NULL_TREE, true,
|
||||
NULL, false);
|
||||
gfc_add_expr_to_block (&se->post, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kind = build_int_cst (integer_type_node, expr->ts.kind);
|
||||
if (lhs_kind == NULL_TREE)
|
||||
lhs_kind = kind;
|
||||
|
||||
caf_decl = gfc_get_tree_for_caf_expr (array_expr);
|
||||
if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
|
||||
caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
|
||||
image_index = gfc_caf_get_image_index (&se->pre, array_expr,
|
||||
caf_decl);
|
||||
gfc_get_caf_token_offset (se, &token, NULL, caf_decl, NULL,
|
||||
array_expr);
|
||||
|
||||
/* No overlap possible as we have generated a temporary. */
|
||||
if (lhs == NULL_TREE)
|
||||
may_require_tmp = boolean_false_node;
|
||||
|
||||
/* It guarantees memory consistency within the same segment. */
|
||||
tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
|
||||
tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
|
||||
gfc_build_string_const (1, ""), NULL_TREE,
|
||||
NULL_TREE, tree_cons (NULL_TREE, tmp, NULL_TREE),
|
||||
NULL_TREE);
|
||||
ASM_VOLATILE_P (tmp) = 1;
|
||||
gfc_add_expr_to_block (&se->pre, tmp);
|
||||
|
||||
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get_by_ref,
|
||||
9, token, image_index, dst_var,
|
||||
caf_reference, lhs_kind, kind,
|
||||
may_require_tmp,
|
||||
may_realloc ? boolean_true_node :
|
||||
boolean_false_node,
|
||||
stat);
|
||||
|
||||
gfc_add_expr_to_block (&se->pre, tmp);
|
||||
|
||||
if (se->ss)
|
||||
gfc_advance_se_ss_chain (se);
|
||||
|
||||
se->expr = res_var;
|
||||
if (array_expr->ts.type == BT_CHARACTER)
|
||||
se->string_length = argse.string_length;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gfc_init_se (&argse, NULL);
|
||||
if (array_expr->rank == 0)
|
||||
{
|
||||
@ -1176,9 +1749,9 @@ gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
|
||||
}
|
||||
gfc_conv_expr_descriptor (&argse, array_expr);
|
||||
/* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
|
||||
has the wrong type if component references are done. */
|
||||
has the wrong type if component references are done. */
|
||||
gfc_add_modify (&argse.pre, gfc_conv_descriptor_dtype (argse.expr),
|
||||
gfc_get_dtype_rank_type (has_vector ? ar2.dimen
|
||||
gfc_get_dtype_rank_type (has_vector ? ar2.dimen
|
||||
: array_expr->rank,
|
||||
type));
|
||||
if (has_vector)
|
||||
@ -1193,10 +1766,10 @@ gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
|
||||
for (int n = 0; n < se->ss->loop->dimen; n++)
|
||||
if (se->loop->to[n] == NULL_TREE)
|
||||
{
|
||||
se->loop->from[n] =
|
||||
gfc_conv_descriptor_lbound_get (argse.expr, gfc_rank_cst[n]);
|
||||
se->loop->to[n] =
|
||||
gfc_conv_descriptor_ubound_get (argse.expr, gfc_rank_cst[n]);
|
||||
se->loop->from[n] = gfc_conv_descriptor_lbound_get (argse.expr,
|
||||
gfc_rank_cst[n]);
|
||||
se->loop->to[n] = gfc_conv_descriptor_ubound_get (argse.expr,
|
||||
gfc_rank_cst[n]);
|
||||
}
|
||||
gfc_trans_create_temp_array (&argse.pre, &argse.post, se->ss, type,
|
||||
NULL_TREE, false, true, false,
|
||||
@ -1218,14 +1791,15 @@ gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
|
||||
if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
|
||||
caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
|
||||
image_index = gfc_caf_get_image_index (&se->pre, array_expr, caf_decl);
|
||||
gfc_get_caf_token_offset (&token, &offset, caf_decl, argse.expr, array_expr);
|
||||
gfc_get_caf_token_offset (se, &token, &offset, caf_decl, argse.expr,
|
||||
array_expr);
|
||||
|
||||
/* No overlap possible as we have generated a temporary. */
|
||||
if (lhs == NULL_TREE)
|
||||
may_require_tmp = boolean_false_node;
|
||||
|
||||
/* It guarantees memory consistency within the same segment */
|
||||
tmp = gfc_build_string_const (strlen ("memory") + 1, "memory"),
|
||||
/* It guarantees memory consistency within the same segment. */
|
||||
tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
|
||||
tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
|
||||
gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
|
||||
tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
|
||||
@ -1235,6 +1809,7 @@ gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
|
||||
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_get, 10,
|
||||
token, offset, image_index, argse.expr, vec,
|
||||
dst_var, kind, lhs_kind, may_require_tmp, stat);
|
||||
|
||||
gfc_add_expr_to_block (&se->pre, tmp);
|
||||
|
||||
if (se->ss)
|
||||
@ -1246,7 +1821,7 @@ gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind,
|
||||
}
|
||||
|
||||
|
||||
/* Send data to a remove coarray. */
|
||||
/* Send data to a remote coarray. */
|
||||
|
||||
static tree
|
||||
conv_caf_send (gfc_code *code) {
|
||||
@ -1254,9 +1829,10 @@ conv_caf_send (gfc_code *code) {
|
||||
gfc_se lhs_se, rhs_se;
|
||||
stmtblock_t block;
|
||||
tree caf_decl, token, offset, image_index, tmp, lhs_kind, rhs_kind;
|
||||
tree may_require_tmp, stat;
|
||||
tree may_require_tmp, src_stat, dst_stat;
|
||||
tree lhs_type = NULL_TREE;
|
||||
tree vec = null_pointer_node, rhs_vec = null_pointer_node;
|
||||
symbol_attribute lhs_caf_attr, rhs_caf_attr;
|
||||
|
||||
gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
|
||||
|
||||
@ -1266,7 +1842,9 @@ conv_caf_send (gfc_code *code) {
|
||||
? boolean_false_node : boolean_true_node;
|
||||
gfc_init_block (&block);
|
||||
|
||||
stat = null_pointer_node;
|
||||
lhs_caf_attr = gfc_caf_attr (lhs_expr);
|
||||
rhs_caf_attr = gfc_caf_attr (rhs_expr);
|
||||
src_stat = dst_stat = null_pointer_node;
|
||||
|
||||
/* LHS. */
|
||||
gfc_init_se (&lhs_se, NULL);
|
||||
@ -1279,6 +1857,21 @@ conv_caf_send (gfc_code *code) {
|
||||
lhs_se.expr = gfc_conv_scalar_to_descriptor (&lhs_se, lhs_se.expr, attr);
|
||||
lhs_se.expr = gfc_build_addr_expr (NULL_TREE, lhs_se.expr);
|
||||
}
|
||||
else if (lhs_caf_attr.alloc_comp && lhs_caf_attr.codimension)
|
||||
{
|
||||
lhs_se.want_pointer = 1;
|
||||
gfc_conv_expr_descriptor (&lhs_se, lhs_expr);
|
||||
/* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
|
||||
has the wrong type if component references are done. */
|
||||
lhs_type = gfc_typenode_for_spec (&lhs_expr->ts);
|
||||
tmp = build_fold_indirect_ref_loc (input_location, lhs_se.expr);
|
||||
gfc_add_modify (&lhs_se.pre, gfc_conv_descriptor_dtype (tmp),
|
||||
gfc_get_dtype_rank_type (
|
||||
gfc_has_vector_subscript (lhs_expr)
|
||||
? gfc_find_array_ref (lhs_expr)->dimen
|
||||
: lhs_expr->rank,
|
||||
lhs_type));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If has_vector, pass descriptor for whole array and the
|
||||
@ -1313,29 +1906,62 @@ conv_caf_send (gfc_code *code) {
|
||||
}
|
||||
|
||||
lhs_kind = build_int_cst (integer_type_node, lhs_expr->ts.kind);
|
||||
gfc_add_block_to_block (&block, &lhs_se.pre);
|
||||
|
||||
/* Special case: RHS is a coarray but LHS is not; this code path avoids a
|
||||
temporary and a loop. */
|
||||
if (!gfc_is_coindexed (lhs_expr))
|
||||
if (!gfc_is_coindexed (lhs_expr) && !lhs_caf_attr.codimension)
|
||||
{
|
||||
bool lhs_may_realloc = lhs_expr->rank > 0 && lhs_caf_attr.allocatable;
|
||||
gcc_assert (gfc_is_coindexed (rhs_expr));
|
||||
gfc_init_se (&rhs_se, NULL);
|
||||
if (lhs_expr->rank == 0 && gfc_expr_attr (lhs_expr).allocatable)
|
||||
{
|
||||
gfc_se scal_se;
|
||||
gfc_init_se (&scal_se, NULL);
|
||||
scal_se.want_pointer = 1;
|
||||
gfc_conv_expr (&scal_se, lhs_expr);
|
||||
/* Ensure scalar on lhs is allocated. */
|
||||
gfc_add_block_to_block (&block, &scal_se.pre);
|
||||
|
||||
gfc_allocate_using_malloc (&scal_se.pre, scal_se.expr,
|
||||
TYPE_SIZE_UNIT (
|
||||
gfc_typenode_for_spec (&lhs_expr->ts)),
|
||||
NULL_TREE);
|
||||
tmp = fold_build2 (EQ_EXPR, boolean_type_node, scal_se.expr,
|
||||
null_pointer_node);
|
||||
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
|
||||
tmp, gfc_finish_block (&scal_se.pre),
|
||||
build_empty_stmt (input_location));
|
||||
gfc_add_expr_to_block (&block, tmp);
|
||||
}
|
||||
else
|
||||
lhs_may_realloc = lhs_may_realloc
|
||||
&& gfc_full_array_ref_p (lhs_expr->ref, NULL);
|
||||
gfc_add_block_to_block (&block, &lhs_se.pre);
|
||||
gfc_conv_intrinsic_caf_get (&rhs_se, rhs_expr, lhs_se.expr, lhs_kind,
|
||||
may_require_tmp);
|
||||
may_require_tmp, lhs_may_realloc,
|
||||
&lhs_caf_attr);
|
||||
gfc_add_block_to_block (&block, &rhs_se.pre);
|
||||
gfc_add_block_to_block (&block, &rhs_se.post);
|
||||
gfc_add_block_to_block (&block, &lhs_se.post);
|
||||
return gfc_finish_block (&block);
|
||||
}
|
||||
|
||||
/* Obtain token, offset and image index for the LHS. */
|
||||
gfc_add_block_to_block (&block, &lhs_se.pre);
|
||||
|
||||
/* Obtain token, offset and image index for the LHS. */
|
||||
caf_decl = gfc_get_tree_for_caf_expr (lhs_expr);
|
||||
if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
|
||||
caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
|
||||
image_index = gfc_caf_get_image_index (&block, lhs_expr, caf_decl);
|
||||
gfc_get_caf_token_offset (&token, &offset, caf_decl, lhs_se.expr, lhs_expr);
|
||||
tmp = lhs_se.expr;
|
||||
if (lhs_caf_attr.alloc_comp)
|
||||
gfc_get_caf_token_offset (&lhs_se, &token, NULL, caf_decl, NULL_TREE,
|
||||
NULL);
|
||||
else
|
||||
gfc_get_caf_token_offset (&lhs_se, &token, &offset, caf_decl, tmp,
|
||||
lhs_expr);
|
||||
lhs_se.expr = tmp;
|
||||
|
||||
/* RHS. */
|
||||
gfc_init_se (&rhs_se, NULL);
|
||||
@ -1347,11 +1973,25 @@ conv_caf_send (gfc_code *code) {
|
||||
symbol_attribute attr;
|
||||
gfc_clear_attr (&attr);
|
||||
gfc_conv_expr (&rhs_se, rhs_expr);
|
||||
if (!gfc_is_coindexed (rhs_expr) && rhs_expr->ts.type != BT_CHARACTER)
|
||||
rhs_se.expr = fold_convert (lhs_type , rhs_se.expr);
|
||||
rhs_se.expr = gfc_conv_scalar_to_descriptor (&rhs_se, rhs_se.expr, attr);
|
||||
rhs_se.expr = gfc_build_addr_expr (NULL_TREE, rhs_se.expr);
|
||||
}
|
||||
else if (rhs_caf_attr.alloc_comp && rhs_caf_attr.codimension)
|
||||
{
|
||||
tree tmp2;
|
||||
rhs_se.want_pointer = 1;
|
||||
gfc_conv_expr_descriptor (&rhs_se, rhs_expr);
|
||||
/* Using gfc_conv_expr_descriptor, we only get the descriptor, but that
|
||||
has the wrong type if component references are done. */
|
||||
tmp2 = gfc_typenode_for_spec (&rhs_expr->ts);
|
||||
tmp = build_fold_indirect_ref_loc (input_location, rhs_se.expr);
|
||||
gfc_add_modify (&rhs_se.pre, gfc_conv_descriptor_dtype (tmp),
|
||||
gfc_get_dtype_rank_type (
|
||||
gfc_has_vector_subscript (rhs_expr)
|
||||
? gfc_find_array_ref (rhs_expr)->dimen
|
||||
: rhs_expr->rank,
|
||||
tmp2));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If has_vector, pass descriptor for whole array and the
|
||||
@ -1397,24 +2037,37 @@ conv_caf_send (gfc_code *code) {
|
||||
gfc_se stat_se;
|
||||
gfc_init_se (&stat_se, NULL);
|
||||
gfc_conv_expr_reference (&stat_se, tmp_stat);
|
||||
stat = stat_se.expr;
|
||||
dst_stat = stat_se.expr;
|
||||
gfc_add_block_to_block (&block, &stat_se.pre);
|
||||
gfc_add_block_to_block (&block, &stat_se.post);
|
||||
}
|
||||
else
|
||||
stat = null_pointer_node;
|
||||
|
||||
if (!gfc_is_coindexed (rhs_expr))
|
||||
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 10, token,
|
||||
offset, image_index, lhs_se.expr, vec,
|
||||
rhs_se.expr, lhs_kind, rhs_kind, may_require_tmp,
|
||||
stat);
|
||||
if (!gfc_is_coindexed (rhs_expr) && !rhs_caf_attr.codimension)
|
||||
{
|
||||
if (lhs_caf_attr.alloc_comp)
|
||||
{
|
||||
tree reference, dst_realloc;
|
||||
reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
|
||||
dst_realloc = lhs_caf_attr.allocatable ? boolean_true_node
|
||||
: boolean_false_node;
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
gfor_fndecl_caf_send_by_ref,
|
||||
9, token, image_index, rhs_se.expr,
|
||||
reference, lhs_kind, rhs_kind,
|
||||
may_require_tmp, dst_realloc, src_stat);
|
||||
}
|
||||
else
|
||||
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_send, 10,
|
||||
token, offset, image_index, lhs_se.expr, vec,
|
||||
rhs_se.expr, lhs_kind, rhs_kind,
|
||||
may_require_tmp, src_stat);
|
||||
}
|
||||
else
|
||||
{
|
||||
tree rhs_token, rhs_offset, rhs_image_index;
|
||||
|
||||
/* It guarantees memory consistency within the same segment */
|
||||
tmp = gfc_build_string_const (strlen ("memory") + 1, "memory"),
|
||||
/* It guarantees memory consistency within the same segment. */
|
||||
tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
|
||||
tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
|
||||
gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
|
||||
tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
|
||||
@ -1425,20 +2078,50 @@ conv_caf_send (gfc_code *code) {
|
||||
if (TREE_CODE (TREE_TYPE (caf_decl)) == REFERENCE_TYPE)
|
||||
caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
|
||||
rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl);
|
||||
gfc_get_caf_token_offset (&rhs_token, &rhs_offset, caf_decl, rhs_se.expr,
|
||||
rhs_expr);
|
||||
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget, 13,
|
||||
token, offset, image_index, lhs_se.expr, vec,
|
||||
rhs_token, rhs_offset, rhs_image_index,
|
||||
rhs_se.expr, rhs_vec, lhs_kind, rhs_kind,
|
||||
may_require_tmp);
|
||||
tmp = rhs_se.expr;
|
||||
if (rhs_caf_attr.alloc_comp)
|
||||
{
|
||||
tmp_stat = gfc_find_stat_co (lhs_expr);
|
||||
|
||||
if (tmp_stat)
|
||||
{
|
||||
gfc_se stat_se;
|
||||
gfc_init_se (&stat_se, NULL);
|
||||
gfc_conv_expr_reference (&stat_se, tmp_stat);
|
||||
src_stat = stat_se.expr;
|
||||
gfc_add_block_to_block (&block, &stat_se.pre);
|
||||
gfc_add_block_to_block (&block, &stat_se.post);
|
||||
}
|
||||
|
||||
gfc_get_caf_token_offset (&rhs_se, &rhs_token, NULL, caf_decl,
|
||||
NULL_TREE, NULL);
|
||||
tree lhs_reference, rhs_reference;
|
||||
lhs_reference = conv_expr_ref_to_caf_ref (&block, lhs_expr);
|
||||
rhs_reference = conv_expr_ref_to_caf_ref (&block, rhs_expr);
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
gfor_fndecl_caf_sendget_by_ref, 11,
|
||||
token, image_index, lhs_reference,
|
||||
rhs_token, rhs_image_index, rhs_reference,
|
||||
lhs_kind, rhs_kind, may_require_tmp,
|
||||
dst_stat, src_stat);
|
||||
}
|
||||
else
|
||||
{
|
||||
gfc_get_caf_token_offset (&rhs_se, &rhs_token, &rhs_offset, caf_decl,
|
||||
tmp, rhs_expr);
|
||||
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sendget,
|
||||
14, token, offset, image_index,
|
||||
lhs_se.expr, vec, rhs_token, rhs_offset,
|
||||
rhs_image_index, tmp, rhs_vec, lhs_kind,
|
||||
rhs_kind, may_require_tmp, src_stat);
|
||||
}
|
||||
}
|
||||
gfc_add_expr_to_block (&block, tmp);
|
||||
gfc_add_block_to_block (&block, &lhs_se.post);
|
||||
gfc_add_block_to_block (&block, &rhs_se.post);
|
||||
|
||||
/* It guarantees memory consistency within the same segment */
|
||||
tmp = gfc_build_string_const (strlen ("memory") + 1, "memory"),
|
||||
/* It guarantees memory consistency within the same segment. */
|
||||
tmp = gfc_build_string_const (strlen ("memory") + 1, "memory");
|
||||
tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
|
||||
gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
|
||||
tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
|
||||
@ -7962,7 +8645,8 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
|
||||
break;
|
||||
|
||||
case GFC_ISYM_CAF_GET:
|
||||
gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE);
|
||||
gfc_conv_intrinsic_caf_get (se, expr, NULL_TREE, NULL_TREE, NULL_TREE,
|
||||
false, NULL);
|
||||
break;
|
||||
|
||||
case GFC_ISYM_CMPLX:
|
||||
@ -9033,8 +9717,11 @@ conv_intrinsic_atomic_op (gfc_code *code)
|
||||
value = gfc_build_addr_expr (NULL_TREE, tmp);
|
||||
}
|
||||
|
||||
gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
|
||||
gfc_init_se (&argse, NULL);
|
||||
gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
|
||||
atom_expr);
|
||||
|
||||
gfc_add_block_to_block (&block, &argse.pre);
|
||||
if (code->resolved_isym->id == GFC_ISYM_ATOMIC_DEF)
|
||||
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_def, 7,
|
||||
token, offset, image_index, value, stat,
|
||||
@ -9052,6 +9739,7 @@ conv_intrinsic_atomic_op (gfc_code *code)
|
||||
(int) atom_expr->ts.kind));
|
||||
|
||||
gfc_add_expr_to_block (&block, tmp);
|
||||
gfc_add_block_to_block (&block, &argse.post);
|
||||
gfc_add_block_to_block (&block, &post_block);
|
||||
return gfc_finish_block (&block);
|
||||
}
|
||||
@ -9179,7 +9867,10 @@ conv_intrinsic_atomic_ref (gfc_code *code)
|
||||
else
|
||||
image_index = integer_zero_node;
|
||||
|
||||
gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
|
||||
gfc_init_se (&argse, NULL);
|
||||
gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
|
||||
atom_expr);
|
||||
gfc_add_block_to_block (&block, &argse.pre);
|
||||
|
||||
/* Different type, need type conversion. */
|
||||
if (!POINTER_TYPE_P (TREE_TYPE (value)))
|
||||
@ -9199,6 +9890,7 @@ conv_intrinsic_atomic_ref (gfc_code *code)
|
||||
if (vardecl != NULL_TREE)
|
||||
gfc_add_modify (&block, orig_value,
|
||||
fold_convert (TREE_TYPE (orig_value), vardecl));
|
||||
gfc_add_block_to_block (&block, &argse.post);
|
||||
gfc_add_block_to_block (&block, &post_block);
|
||||
return gfc_finish_block (&block);
|
||||
}
|
||||
@ -9312,7 +10004,10 @@ conv_intrinsic_atomic_cas (gfc_code *code)
|
||||
comp = gfc_build_addr_expr (NULL_TREE, tmp);
|
||||
}
|
||||
|
||||
gfc_get_caf_token_offset (&token, &offset, caf_decl, atom, atom_expr);
|
||||
gfc_init_se (&argse, NULL);
|
||||
gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
|
||||
atom_expr);
|
||||
gfc_add_block_to_block (&block, &argse.pre);
|
||||
|
||||
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_atomic_cas, 9,
|
||||
token, offset, image_index, old, comp, new_val,
|
||||
@ -9321,6 +10016,7 @@ conv_intrinsic_atomic_cas (gfc_code *code)
|
||||
build_int_cst (integer_type_node,
|
||||
(int) atom_expr->ts.kind));
|
||||
gfc_add_expr_to_block (&block, tmp);
|
||||
gfc_add_block_to_block (&block, &argse.post);
|
||||
gfc_add_block_to_block (&block, &post_block);
|
||||
return gfc_finish_block (&block);
|
||||
}
|
||||
@ -9407,7 +10103,8 @@ conv_intrinsic_event_query (gfc_code *code)
|
||||
|
||||
image_index = integer_zero_node;
|
||||
|
||||
gfc_get_caf_token_offset (&token, NULL, caf_decl, NULL_TREE, event_expr);
|
||||
gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
|
||||
event_expr);
|
||||
|
||||
/* For arrays, obtain the array index. */
|
||||
if (gfc_expr_attr (event_expr).dimension)
|
||||
|
@ -725,7 +725,8 @@ gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
gfc_get_caf_token_offset (&token, NULL, caf_decl, NULL_TREE, code->expr1);
|
||||
gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
|
||||
code->expr1);
|
||||
|
||||
if (gfc_is_coindexed (code->expr1))
|
||||
image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
|
||||
@ -921,7 +922,10 @@ gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
gfc_get_caf_token_offset (&token, NULL, caf_decl, NULL_TREE, code->expr1);
|
||||
gfc_init_se (&argse, NULL);
|
||||
gfc_get_caf_token_offset (&argse, &token, NULL, caf_decl, NULL_TREE,
|
||||
code->expr1);
|
||||
gfc_add_block_to_block (&se.pre, &argse.pre);
|
||||
|
||||
if (gfc_is_coindexed (code->expr1))
|
||||
image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
|
||||
@ -5876,11 +5880,30 @@ gfc_trans_allocate (gfc_code * code)
|
||||
/* Handle size computation of the type declared to alloc. */
|
||||
memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
|
||||
|
||||
if (gfc_caf_attr (expr).codimension
|
||||
&& flag_coarray == GFC_FCOARRAY_LIB)
|
||||
{
|
||||
/* Scalar allocatable components in coarray'ed derived types make
|
||||
it here and are treated now. */
|
||||
tree caf_decl, token;
|
||||
gfc_se caf_se;
|
||||
|
||||
gfc_init_se (&caf_se, NULL);
|
||||
|
||||
caf_decl = gfc_get_tree_for_caf_expr (expr);
|
||||
gfc_get_caf_token_offset (&caf_se, &token, NULL, caf_decl,
|
||||
NULL_TREE, NULL);
|
||||
gfc_add_block_to_block (&se.pre, &caf_se.pre);
|
||||
gfc_allocate_allocatable (&se.pre, se.expr, memsz,
|
||||
gfc_build_addr_expr (NULL_TREE, token),
|
||||
NULL_TREE, NULL_TREE, NULL_TREE,
|
||||
label_finish, expr, 1);
|
||||
}
|
||||
/* Allocate - for non-pointers with re-alloc checking. */
|
||||
if (gfc_expr_attr (expr).allocatable)
|
||||
gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
|
||||
stat, errmsg, errlen, label_finish,
|
||||
expr);
|
||||
else if (gfc_expr_attr (expr).allocatable)
|
||||
gfc_allocate_allocatable (&se.pre, se.expr, memsz,
|
||||
NULL_TREE, stat, errmsg, errlen,
|
||||
label_finish, expr, 0);
|
||||
else
|
||||
gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
|
||||
|
||||
@ -6147,10 +6170,12 @@ gfc_trans_allocate (gfc_code * code)
|
||||
/* Switch off automatic reallocation since we have just
|
||||
done the ALLOCATE. */
|
||||
int realloc_lhs = flag_realloc_lhs;
|
||||
gfc_expr *init_expr = gfc_expr_to_initialize (expr);
|
||||
flag_realloc_lhs = 0;
|
||||
tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
|
||||
e3rhs, false, false);
|
||||
tmp = gfc_trans_assignment (init_expr, e3rhs, false, false);
|
||||
flag_realloc_lhs = realloc_lhs;
|
||||
/* Free the expression allocated for init_expr. */
|
||||
gfc_free_expr (init_expr);
|
||||
}
|
||||
gfc_add_expr_to_block (&block, tmp);
|
||||
}
|
||||
@ -6298,7 +6323,7 @@ gfc_trans_deallocate (gfc_code *code)
|
||||
se.descriptor_only = 1;
|
||||
gfc_conv_expr (&se, expr);
|
||||
|
||||
if (expr->rank || gfc_is_coarray (expr))
|
||||
if (expr->rank || gfc_caf_attr (expr).codimension)
|
||||
{
|
||||
gfc_ref *ref;
|
||||
|
||||
|
@ -1054,7 +1054,7 @@ gfc_get_character_type (int kind, gfc_charlen * cl)
|
||||
/* Convert a basic type. This will be an array for character types. */
|
||||
|
||||
tree
|
||||
gfc_typenode_for_spec (gfc_typespec * spec)
|
||||
gfc_typenode_for_spec (gfc_typespec * spec, bool in_coarray)
|
||||
{
|
||||
tree basetype;
|
||||
|
||||
@ -1107,7 +1107,7 @@ gfc_typenode_for_spec (gfc_typespec * spec)
|
||||
|
||||
case BT_DERIVED:
|
||||
case BT_CLASS:
|
||||
basetype = gfc_get_derived_type (spec->u.derived);
|
||||
basetype = gfc_get_derived_type (spec->u.derived, in_coarray);
|
||||
|
||||
if (spec->type == BT_CLASS)
|
||||
GFC_CLASS_TYPE_P (basetype) = 1;
|
||||
@ -1311,7 +1311,7 @@ gfc_is_nodesc_array (gfc_symbol * sym)
|
||||
static tree
|
||||
gfc_build_array_type (tree type, gfc_array_spec * as,
|
||||
enum gfc_array_kind akind, bool restricted,
|
||||
bool contiguous)
|
||||
bool contiguous, bool in_coarray)
|
||||
{
|
||||
tree lbound[GFC_MAX_DIMENSIONS];
|
||||
tree ubound[GFC_MAX_DIMENSIONS];
|
||||
@ -1361,7 +1361,7 @@ gfc_build_array_type (tree type, gfc_array_spec * as,
|
||||
return gfc_get_array_type_bounds (type, as->rank == -1
|
||||
? GFC_MAX_DIMENSIONS : as->rank,
|
||||
corank, lbound,
|
||||
ubound, 0, akind, restricted);
|
||||
ubound, 0, akind, restricted, in_coarray);
|
||||
}
|
||||
|
||||
/* Returns the struct descriptor_dimension type. */
|
||||
@ -1724,7 +1724,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
|
||||
|
||||
static tree
|
||||
gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted,
|
||||
enum gfc_array_kind akind)
|
||||
enum gfc_array_kind akind, bool in_coarray)
|
||||
{
|
||||
tree fat_type, decl, arraytype, *chain = NULL;
|
||||
char name[16 + 2*GFC_RANK_DIGITS + 1 + 1];
|
||||
@ -1786,7 +1786,7 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted,
|
||||
TREE_NO_WARNING (decl) = 1;
|
||||
}
|
||||
|
||||
if (flag_coarray == GFC_FCOARRAY_LIB && codimen
|
||||
if (flag_coarray == GFC_FCOARRAY_LIB && (codimen || in_coarray)
|
||||
&& akind == GFC_ARRAY_ALLOCATABLE)
|
||||
{
|
||||
decl = gfc_add_field_to_struct_1 (fat_type,
|
||||
@ -1814,18 +1814,21 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted,
|
||||
tree
|
||||
gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
|
||||
tree * ubound, int packed,
|
||||
enum gfc_array_kind akind, bool restricted)
|
||||
enum gfc_array_kind akind, bool restricted,
|
||||
bool in_coarray)
|
||||
{
|
||||
char name[8 + 2*GFC_RANK_DIGITS + 1 + GFC_MAX_SYMBOL_LEN];
|
||||
tree fat_type, base_type, arraytype, lower, upper, stride, tmp, rtype;
|
||||
const char *type_name;
|
||||
int n;
|
||||
|
||||
base_type = gfc_get_array_descriptor_base (dimen, codimen, restricted, akind);
|
||||
base_type = gfc_get_array_descriptor_base (dimen, codimen, restricted, akind,
|
||||
in_coarray);
|
||||
fat_type = build_distinct_type_copy (base_type);
|
||||
/* Make sure that nontarget and target array type have the same canonical
|
||||
type (and same stub decl for debug info). */
|
||||
base_type = gfc_get_array_descriptor_base (dimen, codimen, false, akind);
|
||||
base_type = gfc_get_array_descriptor_base (dimen, codimen, false, akind,
|
||||
in_coarray);
|
||||
TYPE_CANONICAL (fat_type) = base_type;
|
||||
TYPE_STUB_DECL (fat_type) = TYPE_STUB_DECL (base_type);
|
||||
|
||||
@ -2161,7 +2164,7 @@ gfc_sym_type (gfc_symbol * sym)
|
||||
|| !sym->ts.u.cl->backend_decl))))
|
||||
type = gfc_character1_type_node;
|
||||
else
|
||||
type = gfc_typenode_for_spec (&sym->ts);
|
||||
type = gfc_typenode_for_spec (&sym->ts, sym->attr.codimension);
|
||||
|
||||
if (sym->attr.dummy && !sym->attr.function && !sym->attr.value)
|
||||
byref = 1;
|
||||
@ -2199,7 +2202,7 @@ gfc_sym_type (gfc_symbol * sym)
|
||||
else if (sym->attr.allocatable)
|
||||
akind = GFC_ARRAY_ALLOCATABLE;
|
||||
type = gfc_build_array_type (type, sym->as, akind, restricted,
|
||||
sym->attr.contiguous);
|
||||
sym->attr.contiguous, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2417,7 +2420,7 @@ gfc_get_union_type (gfc_symbol *un)
|
||||
in a parent namespace, this is used. */
|
||||
|
||||
tree
|
||||
gfc_get_derived_type (gfc_symbol * derived)
|
||||
gfc_get_derived_type (gfc_symbol * derived, bool in_coarray)
|
||||
{
|
||||
tree typenode = NULL, field = NULL, field_type = NULL;
|
||||
tree canonical = NULL_TREE;
|
||||
@ -2561,7 +2564,8 @@ gfc_get_derived_type (gfc_symbol * derived)
|
||||
|
||||
if ((!c->attr.pointer && !c->attr.proc_pointer)
|
||||
|| c->ts.u.derived->backend_decl == NULL)
|
||||
c->ts.u.derived->backend_decl = gfc_get_derived_type (c->ts.u.derived);
|
||||
c->ts.u.derived->backend_decl = gfc_get_derived_type (c->ts.u.derived,
|
||||
in_coarray);
|
||||
|
||||
if (c->ts.u.derived->attr.is_iso_c)
|
||||
{
|
||||
@ -2618,7 +2622,7 @@ gfc_get_derived_type (gfc_symbol * derived)
|
||||
c->ts.u.cl->backend_decl
|
||||
= build_int_cst (gfc_charlen_type_node, 0);
|
||||
|
||||
field_type = gfc_typenode_for_spec (&c->ts);
|
||||
field_type = gfc_typenode_for_spec (&c->ts, in_coarray);
|
||||
}
|
||||
|
||||
/* This returns an array descriptor type. Initialization may be
|
||||
@ -2638,7 +2642,8 @@ gfc_get_derived_type (gfc_symbol * derived)
|
||||
field_type = gfc_build_array_type (field_type, c->as, akind,
|
||||
!c->attr.target
|
||||
&& !c->attr.pointer,
|
||||
c->attr.contiguous);
|
||||
c->attr.contiguous,
|
||||
in_coarray);
|
||||
}
|
||||
else
|
||||
field_type = gfc_get_nodesc_array_type (field_type, c->as,
|
||||
@ -2683,6 +2688,19 @@ gfc_get_derived_type (gfc_symbol * derived)
|
||||
gcc_assert (field);
|
||||
if (!c->backend_decl)
|
||||
c->backend_decl = field;
|
||||
|
||||
/* Do not add a caf_token field for classes' data components. */
|
||||
if (in_coarray && !c->attr.dimension && !c->attr.codimension
|
||||
&& c->attr.allocatable && c->caf_token == NULL_TREE
|
||||
&& strcmp ("_data", c->name) != 0)
|
||||
{
|
||||
char caf_name[GFC_MAX_SYMBOL_LEN];
|
||||
snprintf (caf_name, GFC_MAX_SYMBOL_LEN, "_caf_%s", c->name);
|
||||
c->caf_token = gfc_add_field_to_struct (typenode,
|
||||
get_identifier (caf_name),
|
||||
pvoid_type_node, &chain);
|
||||
TREE_NO_WARNING (c->caf_token) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now lay out the derived type, including the fields. */
|
||||
@ -3324,4 +3342,121 @@ gfc_get_caf_vector_type (int dim)
|
||||
return vector_types[dim-1];
|
||||
}
|
||||
|
||||
|
||||
tree
|
||||
gfc_get_caf_reference_type ()
|
||||
{
|
||||
static tree reference_type = NULL_TREE;
|
||||
tree c_struct_type, s_struct_type, v_struct_type, union_type, dim_union_type,
|
||||
a_struct_type, u_union_type, tmp, *chain;
|
||||
|
||||
if (reference_type != NULL_TREE)
|
||||
return reference_type;
|
||||
|
||||
chain = 0;
|
||||
c_struct_type = make_node (RECORD_TYPE);
|
||||
tmp = gfc_add_field_to_struct_1 (c_struct_type,
|
||||
get_identifier ("offset"),
|
||||
gfc_array_index_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (c_struct_type,
|
||||
get_identifier ("caf_token_offset"),
|
||||
gfc_array_index_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
gfc_finish_type (c_struct_type);
|
||||
|
||||
chain = 0;
|
||||
s_struct_type = make_node (RECORD_TYPE);
|
||||
tmp = gfc_add_field_to_struct_1 (s_struct_type,
|
||||
get_identifier ("start"),
|
||||
gfc_array_index_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (s_struct_type,
|
||||
get_identifier ("end"),
|
||||
gfc_array_index_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (s_struct_type,
|
||||
get_identifier ("stride"),
|
||||
gfc_array_index_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
gfc_finish_type (s_struct_type);
|
||||
|
||||
chain = 0;
|
||||
v_struct_type = make_node (RECORD_TYPE);
|
||||
tmp = gfc_add_field_to_struct_1 (v_struct_type,
|
||||
get_identifier ("vector"),
|
||||
pvoid_type_node, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (v_struct_type,
|
||||
get_identifier ("nvec"),
|
||||
size_type_node, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (v_struct_type,
|
||||
get_identifier ("kind"),
|
||||
integer_type_node, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
gfc_finish_type (v_struct_type);
|
||||
|
||||
chain = 0;
|
||||
union_type = make_node (UNION_TYPE);
|
||||
tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("s"),
|
||||
s_struct_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("v"),
|
||||
v_struct_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
gfc_finish_type (union_type);
|
||||
|
||||
tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
|
||||
gfc_rank_cst[GFC_MAX_DIMENSIONS - 1]);
|
||||
dim_union_type = build_array_type (union_type, tmp);
|
||||
|
||||
chain = 0;
|
||||
a_struct_type = make_node (RECORD_TYPE);
|
||||
tmp = gfc_add_field_to_struct_1 (a_struct_type, get_identifier ("mode"),
|
||||
build_array_type (unsigned_char_type_node,
|
||||
build_range_type (gfc_array_index_type,
|
||||
gfc_index_zero_node,
|
||||
gfc_rank_cst[GFC_MAX_DIMENSIONS - 1])),
|
||||
&chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (a_struct_type,
|
||||
get_identifier ("static_array_type"),
|
||||
integer_type_node, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (a_struct_type, get_identifier ("dim"),
|
||||
dim_union_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
gfc_finish_type (a_struct_type);
|
||||
|
||||
chain = 0;
|
||||
u_union_type = make_node (UNION_TYPE);
|
||||
tmp = gfc_add_field_to_struct_1 (u_union_type, get_identifier ("c"),
|
||||
c_struct_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (u_union_type, get_identifier ("a"),
|
||||
a_struct_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
gfc_finish_type (u_union_type);
|
||||
|
||||
chain = 0;
|
||||
reference_type = make_node (RECORD_TYPE);
|
||||
tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("next"),
|
||||
build_pointer_type (reference_type), &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("type"),
|
||||
integer_type_node, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("item_size"),
|
||||
size_type_node, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("u"),
|
||||
u_union_type, &chain);
|
||||
TREE_NO_WARNING (tmp) = 1;
|
||||
gfc_finish_type (reference_type);
|
||||
TYPE_NAME (reference_type) = get_identifier ("caf_reference_t");
|
||||
|
||||
return reference_type;
|
||||
}
|
||||
|
||||
#include "gt-fortran-trans-types.h"
|
||||
|
@ -70,7 +70,7 @@ tree gfc_get_character_type_len (int, tree);
|
||||
tree gfc_get_character_type_len_for_eltype (tree, tree);
|
||||
|
||||
tree gfc_sym_type (gfc_symbol *);
|
||||
tree gfc_typenode_for_spec (gfc_typespec *);
|
||||
tree gfc_typenode_for_spec (gfc_typespec *, bool in_coarray = false);
|
||||
int gfc_copy_dt_decls_ifequal (gfc_symbol *, gfc_symbol *, bool);
|
||||
|
||||
tree gfc_get_function_type (gfc_symbol *);
|
||||
@ -81,7 +81,8 @@ tree gfc_build_uint_type (int);
|
||||
|
||||
tree gfc_get_element_type (tree);
|
||||
tree gfc_get_array_type_bounds (tree, int, int, tree *, tree *, int,
|
||||
enum gfc_array_kind, bool);
|
||||
enum gfc_array_kind, bool,
|
||||
bool in_coarray = false);
|
||||
tree gfc_get_nodesc_array_type (tree, gfc_array_spec *, gfc_packed, bool);
|
||||
|
||||
/* Add a field of given name and type to a UNION_TYPE or RECORD_TYPE. */
|
||||
@ -102,5 +103,6 @@ tree gfc_get_dtype (tree);
|
||||
|
||||
tree gfc_get_ppc_type (gfc_component *);
|
||||
tree gfc_get_caf_vector_type (int dim);
|
||||
tree gfc_get_caf_reference_type ();
|
||||
|
||||
#endif
|
||||
|
@ -734,7 +734,7 @@ gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size,
|
||||
|
||||
size = fold_convert (size_type_node, size);
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
gfor_fndecl_caf_register, 6,
|
||||
gfor_fndecl_caf_register, 7,
|
||||
fold_build2_loc (input_location,
|
||||
MAX_EXPR, size_type_node, size,
|
||||
build_int_cst (size_type_node, 1)),
|
||||
@ -742,11 +742,9 @@ gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size,
|
||||
lock_var ? GFC_CAF_LOCK_ALLOC
|
||||
: event_var ? GFC_CAF_EVENT_ALLOC
|
||||
: GFC_CAF_COARRAY_ALLOC),
|
||||
token, pstat, errmsg, errlen);
|
||||
token, gfc_build_addr_expr (pvoid_type_node, pointer),
|
||||
pstat, errmsg, errlen);
|
||||
|
||||
tmp = fold_build2_loc (input_location, MODIFY_EXPR,
|
||||
TREE_TYPE (pointer), pointer,
|
||||
fold_convert ( TREE_TYPE (pointer), tmp));
|
||||
gfc_add_expr_to_block (block, tmp);
|
||||
|
||||
/* It guarantees memory consistency within the same segment */
|
||||
@ -782,13 +780,15 @@ gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size,
|
||||
expr must be set to the original expression being allocated for its locus
|
||||
and variable name in case a runtime error has to be printed. */
|
||||
void
|
||||
gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token,
|
||||
tree status, tree errmsg, tree errlen, tree label_finish,
|
||||
gfc_expr* expr)
|
||||
gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size,
|
||||
tree token, tree status, tree errmsg, tree errlen,
|
||||
tree label_finish, gfc_expr* expr, int corank)
|
||||
{
|
||||
stmtblock_t alloc_block;
|
||||
tree tmp, null_mem, alloc, error;
|
||||
tree type = TREE_TYPE (mem);
|
||||
symbol_attribute caf_attr;
|
||||
bool need_assign = false;
|
||||
|
||||
size = fold_convert (size_type_node, size);
|
||||
null_mem = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
|
||||
@ -800,8 +800,11 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token,
|
||||
gfc_allocate_using_lib. */
|
||||
gfc_start_block (&alloc_block);
|
||||
|
||||
if (flag_coarray == GFC_FCOARRAY_LIB)
|
||||
caf_attr = gfc_caf_attr (expr, true);
|
||||
|
||||
if (flag_coarray == GFC_FCOARRAY_LIB
|
||||
&& gfc_expr_attr (expr).codimension)
|
||||
&& (corank > 0 || caf_attr.codimension))
|
||||
{
|
||||
tree cond;
|
||||
bool lock_var = expr->ts.type == BT_DERIVED
|
||||
@ -814,6 +817,33 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token,
|
||||
== INTMOD_ISO_FORTRAN_ENV
|
||||
&& expr->ts.u.derived->intmod_sym_id
|
||||
== ISOFORTRAN_EVENT_TYPE;
|
||||
gfc_se se;
|
||||
gfc_init_se (&se, NULL);
|
||||
|
||||
tree sub_caf_tree = gfc_get_ultimate_alloc_ptr_comps_caf_token (&se,
|
||||
expr);
|
||||
if (sub_caf_tree == NULL_TREE)
|
||||
sub_caf_tree = token;
|
||||
|
||||
/* When mem is an array ref, then strip the .data-ref. */
|
||||
if (TREE_CODE (mem) == COMPONENT_REF
|
||||
&& !(GFC_ARRAY_TYPE_P (TREE_TYPE (mem))))
|
||||
tmp = TREE_OPERAND (mem, 0);
|
||||
else
|
||||
tmp = mem;
|
||||
|
||||
if (!(GFC_ARRAY_TYPE_P (TREE_TYPE (tmp))
|
||||
&& TYPE_LANG_SPECIFIC (TREE_TYPE (tmp))->corank == 0)
|
||||
&& !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
|
||||
{
|
||||
symbol_attribute attr;
|
||||
|
||||
gfc_clear_attr (&attr);
|
||||
tmp = gfc_conv_scalar_to_descriptor (&se, mem, attr);
|
||||
need_assign = true;
|
||||
}
|
||||
gfc_add_block_to_block (&alloc_block, &se.pre);
|
||||
|
||||
/* In the front end, we represent the lock variable as pointer. However,
|
||||
the FE only passes the pointer around and leaves the actual
|
||||
representation to the library. Hence, we have to convert back to the
|
||||
@ -822,9 +852,11 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token,
|
||||
size = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
|
||||
size, TYPE_SIZE_UNIT (ptr_type_node));
|
||||
|
||||
gfc_allocate_using_lib (&alloc_block, mem, size, token, status,
|
||||
errmsg, errlen, lock_var, event_var);
|
||||
|
||||
gfc_allocate_using_lib (&alloc_block, tmp, size, sub_caf_tree,
|
||||
status, errmsg, errlen, lock_var, event_var);
|
||||
if (need_assign)
|
||||
gfc_add_modify (&alloc_block, mem, fold_convert (TREE_TYPE (mem),
|
||||
gfc_conv_descriptor_data_get (tmp)));
|
||||
if (status != NULL_TREE)
|
||||
{
|
||||
TREE_USED (label_finish) = 1;
|
||||
@ -1362,8 +1394,8 @@ gfc_deallocate_with_status (tree pointer, tree status, tree errmsg,
|
||||
|
||||
token = gfc_build_addr_expr (NULL_TREE, token);
|
||||
tmp = build_call_expr_loc (input_location,
|
||||
gfor_fndecl_caf_deregister, 4,
|
||||
token, pstat, errmsg, errlen);
|
||||
gfor_fndecl_caf_deregister, 4,
|
||||
token, pstat, errmsg, errlen);
|
||||
gfc_add_expr_to_block (&non_null, tmp);
|
||||
|
||||
/* It guarantees memory consistency within the same segment */
|
||||
|
@ -119,6 +119,27 @@ enum gfc_coarray_type
|
||||
};
|
||||
|
||||
|
||||
/* Specify the type of ref handed to the caf communication functions.
|
||||
Please keep in sync with libgfortran/caf/libcaf.h. */
|
||||
enum gfc_caf_ref_type_t {
|
||||
GFC_CAF_REF_COMPONENT,
|
||||
GFC_CAF_REF_ARRAY,
|
||||
GFC_CAF_REF_STATIC_ARRAY
|
||||
};
|
||||
|
||||
|
||||
/* Give the reference type of an array ref.
|
||||
Please keep in sync with libgfortran/caf/libcaf.h. */
|
||||
enum gfc_caf_array_ref_t {
|
||||
GFC_CAF_ARR_REF_NONE = 0,
|
||||
GFC_CAF_ARR_REF_VECTOR,
|
||||
GFC_CAF_ARR_REF_FULL,
|
||||
GFC_CAF_ARR_REF_RANGE,
|
||||
GFC_CAF_ARR_REF_SINGLE,
|
||||
GFC_CAF_ARR_REF_OPEN_END,
|
||||
GFC_CAF_ARR_REF_OPEN_START
|
||||
};
|
||||
|
||||
/* The array-specific scalarization information. The array members of
|
||||
this struct are indexed by actual array index, and thus can be sparse. */
|
||||
|
||||
@ -441,14 +462,14 @@ void gfc_conv_expr_lhs (gfc_se * se, gfc_expr * expr);
|
||||
void gfc_conv_expr_reference (gfc_se * se, gfc_expr *);
|
||||
void gfc_conv_expr_type (gfc_se * se, gfc_expr *, tree);
|
||||
|
||||
tree gfc_conv_scalar_to_descriptor (gfc_se *, tree, symbol_attribute);
|
||||
|
||||
|
||||
/* trans-expr.c */
|
||||
tree gfc_conv_scalar_to_descriptor (gfc_se *, tree, symbol_attribute);
|
||||
tree gfc_get_ultimate_alloc_ptr_comps_caf_token (gfc_se *, gfc_expr *);
|
||||
void gfc_conv_scalar_char_value (gfc_symbol *sym, gfc_se *se, gfc_expr **expr);
|
||||
tree gfc_string_to_single_character (tree len, tree str, int kind);
|
||||
tree gfc_get_tree_for_caf_expr (gfc_expr *);
|
||||
void gfc_get_caf_token_offset (tree *, tree *, tree, tree, gfc_expr *);
|
||||
void gfc_get_caf_token_offset (gfc_se*, tree *, tree *, tree, tree, gfc_expr *);
|
||||
tree gfc_caf_get_image_index (stmtblock_t *, gfc_expr *, tree);
|
||||
|
||||
/* Find the decl containing the auxiliary variables for assigned variables. */
|
||||
@ -661,7 +682,7 @@ tree gfc_build_memcpy_call (tree, tree, tree);
|
||||
|
||||
/* Allocate memory for allocatable variables, with optional status variable. */
|
||||
void gfc_allocate_allocatable (stmtblock_t*, tree, tree, tree, tree,
|
||||
tree, tree, tree, gfc_expr*);
|
||||
tree, tree, tree, gfc_expr*, int);
|
||||
|
||||
/* Allocate memory, with optional status variable. */
|
||||
void gfc_allocate_using_malloc (stmtblock_t *, tree, tree, tree);
|
||||
@ -760,6 +781,9 @@ extern GTY(()) tree gfor_fndecl_caf_deregister;
|
||||
extern GTY(()) tree gfor_fndecl_caf_get;
|
||||
extern GTY(()) tree gfor_fndecl_caf_send;
|
||||
extern GTY(()) tree gfor_fndecl_caf_sendget;
|
||||
extern GTY(()) tree gfor_fndecl_caf_get_by_ref;
|
||||
extern GTY(()) tree gfor_fndecl_caf_send_by_ref;
|
||||
extern GTY(()) tree gfor_fndecl_caf_sendget_by_ref;
|
||||
extern GTY(()) tree gfor_fndecl_caf_sync_all;
|
||||
extern GTY(()) tree gfor_fndecl_caf_sync_memory;
|
||||
extern GTY(()) tree gfor_fndecl_caf_sync_images;
|
||||
|
@ -1,3 +1,26 @@
|
||||
2016-09-19 Andre Vehreschild <vehre@gcc.gnu.org>
|
||||
|
||||
* gfortran.dg/coarray/alloc_comp_4.f90: New test.
|
||||
* gfortran.dg/coarray_38.f90:
|
||||
* gfortran.dg/coarray_alloc_comp_1.f08: New test.
|
||||
* gfortran.dg/coarray_alloc_comp_2.f08: New test.
|
||||
* gfortran.dg/coarray_allocate_7.f08: New test.
|
||||
* gfortran.dg/coarray_allocate_8.f08: New test.
|
||||
* gfortran.dg/coarray_allocate_9.f08: New test.
|
||||
* gfortran.dg/coarray_lib_alloc_1.f90: Adapted scan-tree-dumps to expect
|
||||
new caf_register.
|
||||
* gfortran.dg/coarray_lib_alloc_2.f90: Same.
|
||||
* gfortran.dg/coarray_lib_alloc_3.f90: Same.
|
||||
* gfortran.dg/coarray_lib_comm_1.f90: Adapted scan-tree-dumps to expect
|
||||
get_by_refs.
|
||||
* gfortran.dg/coarray_lib_token_3.f90: Same as for coarray_lib_alloc2.
|
||||
* gfortran.dg/coarray_lock_7.f90: Same.
|
||||
* gfortran.dg/coarray_poly_5.f90: Same.
|
||||
* gfortran.dg/coarray_poly_6.f90: Same.
|
||||
* gfortran.dg/coarray_poly_7.f90: Same.
|
||||
* gfortran.dg/coarray_poly_8.f90: Same.
|
||||
* gfortran.dg/coindexed_1.f90: Changed errors expected.
|
||||
|
||||
2016-09-19 Fritz Reese <fritzoreese@gmail.com>
|
||||
|
||||
PR fortran/77584
|
||||
|
21
gcc/testsuite/gfortran.dg/coarray/alloc_comp_4.f90
Normal file
21
gcc/testsuite/gfortran.dg/coarray/alloc_comp_4.f90
Normal file
@ -0,0 +1,21 @@
|
||||
! { dg-do run }
|
||||
|
||||
! Contributed by Damian Rouson
|
||||
|
||||
program main
|
||||
|
||||
implicit none
|
||||
|
||||
type mytype
|
||||
integer, allocatable :: indices(:)
|
||||
end type
|
||||
|
||||
type(mytype), save :: object[*]
|
||||
integer :: me
|
||||
|
||||
me=this_image()
|
||||
allocate(object%indices(me))
|
||||
object%indices = 42
|
||||
|
||||
if ( any( object[me]%indices(:) /= 42 ) ) call abort()
|
||||
end program
|
@ -15,11 +15,11 @@ end type t2
|
||||
type(t), save :: caf[*],x
|
||||
type(t2) :: y
|
||||
|
||||
x = caf[4] ! { dg-error "Sorry, coindexed coarray at \\(1\\) with allocatable component is not yet supported" }
|
||||
x%a = caf[4]%a ! { dg-error "Sorry, coindexed access to a pointer or allocatable component of the coindexed coarray at \\(1\\) is not yet supported" }
|
||||
x = caf[4] ! OK, now
|
||||
x%a = caf[4]%a ! OK, now
|
||||
x%b = caf[4]%b ! OK
|
||||
x = y%caf2[5] ! { dg-error "Sorry, coindexed coarray at \\(1\\) with allocatable component is not yet supported" }
|
||||
x%a = y%caf2[4]%a ! { dg-error "Sorry, coindexed access to a pointer or allocatable component of the coindexed coarray at \\(1\\) is not yet supported" }
|
||||
x = y%caf2[5] ! OK, now
|
||||
x%a = y%caf2[4]%a ! OK, now
|
||||
x%b = y%caf2[4]%b ! OK
|
||||
end subroutine one
|
||||
|
||||
@ -36,10 +36,10 @@ type(t), save :: caf[*],x
|
||||
type(t2) :: y
|
||||
|
||||
x = caf[4] ! OK
|
||||
x%a = caf[4]%a ! { dg-error "Sorry, coindexed access to a pointer or allocatable component of the coindexed coarray at \\(1\\) is not yet supported" }
|
||||
x%a = caf[4]%a ! OK, now
|
||||
x%b = caf[4]%b ! OK
|
||||
x = y%caf2[5] ! OK
|
||||
x%a = y%caf2[4]%a ! { dg-error "Sorry, coindexed access to a pointer or allocatable component of the coindexed coarray at \\(1\\) is not yet supported" }
|
||||
x%a = y%caf2[4]%a ! OK, now
|
||||
x%b = y%caf2[4]%b ! OK
|
||||
end subroutine two
|
||||
|
||||
@ -56,10 +56,10 @@ integer :: x(10)
|
||||
type(t2) :: y
|
||||
|
||||
x(1) = caf(2)[4]%b ! OK
|
||||
x(:) = caf(:)[4]%b ! { dg-error "Sorry, coindexed access at \\(1\\) to a scalar component with an array partref is not yet supported" }
|
||||
x(:) = caf(:)[4]%b ! OK now
|
||||
|
||||
x(1) = y%caf2(2)[4]%b ! OK
|
||||
x(:) = y%caf2(:)[4]%b ! { dg-error "Sorry, coindexed access at \\(1\\) to a scalar component with an array partref is not yet supported" }
|
||||
x(:) = y%caf2(:)[4]%b ! OK now
|
||||
end subroutine three
|
||||
|
||||
subroutine four
|
||||
@ -76,10 +76,10 @@ type(t) :: x
|
||||
type(t2) :: y
|
||||
|
||||
!x = caf[4] ! Unsupported - and ICEs in resolve_ordinary_assign, cf. PR fortran/65397
|
||||
x%a = caf[4]%a ! { dg-error "Sorry, coindexed access to a pointer or allocatable component of the coindexed coarray at \\(1\\) is not yet supported" }
|
||||
x%a = caf[4]%a ! OK, now
|
||||
x%b = caf[4]%b ! OK
|
||||
!x = y%caf2[5] ! Unsupported - and ICEs in resolve_ordinary_assign, cf. PR fortran/65397
|
||||
x%a = y%caf2[4]%a ! { dg-error "Sorry, coindexed access to a pointer or allocatable component of the coindexed coarray at \\(1\\) is not yet supported" }
|
||||
x%a = y%caf2[4]%a ! Ok, now
|
||||
x%b = y%caf2[4]%b ! OK
|
||||
end subroutine four
|
||||
|
||||
@ -97,10 +97,10 @@ type(t) :: x
|
||||
type(t2) :: y
|
||||
|
||||
!x = caf[4] ! OK - but ICEs in resolve_ordinary_assign, cf. PR fortran/65397
|
||||
x%a = caf[4]%a ! { dg-error "Sorry, coindexed access to a pointer or allocatable component of the coindexed coarray at \\(1\\) is not yet supported" }
|
||||
x%a = caf[4]%a ! OK, now
|
||||
x%b = caf[4]%b ! OK
|
||||
!x = y%caf2[5] ! OK - but ICEs in resolve_ordinary_assign, cf. PR fortran/65397
|
||||
x%a = y%caf2[4]%a ! { dg-error "Sorry, coindexed access to a pointer or allocatable component of the coindexed coarray at \\(1\\) is not yet supported" }
|
||||
x%a = y%caf2[4]%a ! OK, now
|
||||
x%b = y%caf2[4]%b ! OK
|
||||
end subroutine five
|
||||
|
||||
@ -117,8 +117,16 @@ integer :: x(10)
|
||||
type(t2) :: y
|
||||
|
||||
x(1) = caf(2)[4]%b ! OK
|
||||
x(:) = caf(:)[4]%b ! { dg-error "Sorry, coindexed access at \\(1\\) to a scalar component with an array partref is not yet supported" }
|
||||
x(:) = caf(:)[4]%b ! OK now
|
||||
|
||||
x(1) = y%caf2(2)[4]%b ! OK
|
||||
x(:) = y%caf2(:)[4]%b ! { dg-error "Sorry, coindexed access at \\(1\\) to a scalar component with an array partref is not yet supported" }
|
||||
x(:) = y%caf2(:)[4]%b ! OK now
|
||||
end subroutine six
|
||||
|
||||
call one()
|
||||
call two()
|
||||
call three()
|
||||
call four()
|
||||
call five()
|
||||
call six()
|
||||
end
|
||||
|
92
gcc/testsuite/gfortran.dg/coarray_alloc_comp_1.f08
Normal file
92
gcc/testsuite/gfortran.dg/coarray_alloc_comp_1.f08
Normal file
@ -0,0 +1,92 @@
|
||||
! { dg-do run }
|
||||
! { dg-options "-fcoarray=lib -lcaf_single" }
|
||||
|
||||
! Contributed by Damian Rouson
|
||||
! Check the new _caf_get_by_ref()-routine.
|
||||
|
||||
program main
|
||||
|
||||
implicit none
|
||||
|
||||
type :: mytype
|
||||
integer :: i
|
||||
integer, allocatable :: indices(:)
|
||||
real, dimension(2,5,3) :: volume
|
||||
integer, allocatable :: scalar
|
||||
integer :: j
|
||||
integer, allocatable :: matrix(:,:)
|
||||
real, allocatable :: dynvol(:,:,:)
|
||||
end type
|
||||
|
||||
type arrtype
|
||||
type(mytype), allocatable :: vec(:)
|
||||
type(mytype), allocatable :: mat(:,:)
|
||||
end type arrtype
|
||||
|
||||
type(mytype), save :: object[*]
|
||||
type(arrtype), save :: bar[*]
|
||||
integer :: i,j,me,neighbor
|
||||
integer :: idx(5)
|
||||
real, allocatable :: volume(:,:,:), vol2(:,:,:)
|
||||
real :: vol_static(2,5,3)
|
||||
|
||||
idx = (/ 1,2,1,7,5 /)
|
||||
|
||||
me=this_image()
|
||||
object%indices=[(i,i=1,5)]
|
||||
allocate(object%scalar, object%matrix(10,7))
|
||||
object%i = 37
|
||||
object%scalar = 42
|
||||
vol_static = reshape([(i, i=1, 2*5*3)], [2, 5, 3])
|
||||
object%volume = vol_static
|
||||
object%matrix = reshape([(i, i=1, 70)], [10, 7])
|
||||
object%dynvol = vol_static
|
||||
sync all
|
||||
neighbor = merge(1,neighbor,me==num_images())
|
||||
if (object[neighbor]%scalar /= 42) call abort()
|
||||
if (object[neighbor]%indices(4) /= 4) call abort()
|
||||
if (object[neighbor]%matrix(3,6) /= 53) call abort()
|
||||
if (any( object[neighbor]%indices(:) /= [1,2,3,4,5] )) call abort()
|
||||
if (any( object[neighbor]%matrix(:,:) /= reshape([(i, i=1, 70)], [10, 7]))) call abort()
|
||||
if (any( object[neighbor]%matrix(3,:) /= [(i * 10 + 3, i=0, 6)])) call abort()
|
||||
if (any( object[neighbor]%matrix(:,2) /= [(i + 10, i=1, 10)])) call abort()
|
||||
if (any( object[neighbor]%matrix(idx,2) /= [11, 12, 11, 17, 15])) call abort()
|
||||
if (any( object[neighbor]%matrix(3,idx) /= [3, 13, 3, 63, 43])) call abort()
|
||||
if (any( object[neighbor]%matrix(2:8:4, 5:1:-1) /= reshape([42, 46, 32, 36, 22, 26, 12, 16, 2, 6], [2,5]))) call abort()
|
||||
if (any( object[neighbor]%matrix(:8:4, 2::2) /= reshape([11, 15, 31, 35, 51, 55], [2,3]))) call abort()
|
||||
if (any( object[neighbor]%volume /= vol_static)) call abort()
|
||||
if (any( object[neighbor]%dynvol /= vol_static)) call abort()
|
||||
if (any( object[neighbor]%volume(:, 2:4, :) /= vol_static(:, 2:4, :))) call abort()
|
||||
if (any( object[neighbor]%dynvol(:, 2:4, :) /= vol_static(:, 2:4, :))) call abort()
|
||||
|
||||
vol2 = vol_static(:, ::2, :)
|
||||
if (any( object[neighbor]%volume(:, ::2, :) /= vol2)) call abort()
|
||||
if (any( object[neighbor]%dynvol(:, ::2, :) /= vol2)) call abort()
|
||||
|
||||
allocate(bar%vec(-2:2))
|
||||
|
||||
bar%vec(1)%volume = vol_static
|
||||
if (any(bar[neighbor]%vec(1)%volume /= vol_static)) call abort()
|
||||
|
||||
i = 15
|
||||
bar%vec(1)%scalar = i
|
||||
if (.not. allocated(bar%vec(1)%scalar)) call abort()
|
||||
if (bar[neighbor]%vec(1)%scalar /= 15) call abort()
|
||||
|
||||
bar%vec(0)%scalar = 27
|
||||
if (.not. allocated(bar%vec(0)%scalar)) call abort()
|
||||
if (bar[neighbor]%vec(0)%scalar /= 27) call abort()
|
||||
|
||||
bar%vec(1)%indices = [ 3, 4, 15 ]
|
||||
allocate(bar%vec(2)%indices(5))
|
||||
bar%vec(2)%indices = 89
|
||||
|
||||
if (.not. allocated(bar%vec(1)%indices)) call abort()
|
||||
if (allocated(bar%vec(-2)%indices)) call abort()
|
||||
if (allocated(bar%vec(-1)%indices)) call abort()
|
||||
if (allocated(bar%vec( 0)%indices)) call abort()
|
||||
if (.not. allocated(bar%vec( 2)%indices)) call abort()
|
||||
if (any(bar[me]%vec(2)%indices /= 89)) call abort()
|
||||
|
||||
if (any (bar[neighbor]%vec(1)%indices /= [ 3,4,15])) call abort()
|
||||
end program
|
27
gcc/testsuite/gfortran.dg/coarray_allocate_7.f08
Normal file
27
gcc/testsuite/gfortran.dg/coarray_allocate_7.f08
Normal file
@ -0,0 +1,27 @@
|
||||
! { dg-do run }
|
||||
! { dg-options "-fcoarray=lib -lcaf_single -fdump-tree-original" }
|
||||
|
||||
! Contributed by Damian Rouson
|
||||
! Checking whether (de-)registering of coarrays works.
|
||||
|
||||
program main
|
||||
|
||||
implicit none
|
||||
|
||||
type mytype
|
||||
integer, allocatable :: indices(:)
|
||||
end type
|
||||
|
||||
type(mytype), save :: object[*]
|
||||
integer :: i,me
|
||||
|
||||
me=this_image() ! me is always 1 here
|
||||
object%indices=[(i,i=1,me)]
|
||||
if ( size(object%indices) /= 1 ) call abort()
|
||||
! therefore no array is present here and no array test needed.
|
||||
if ( object%indices(1) /= 1 ) call abort()
|
||||
end program
|
||||
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(D.\[0-9\]{4}, 1, &\\(\\(struct mytype\\) \\*object\\).indices.token, &\\(\\(struct mytype\\) \\*object\\).indices, 0B, 0B, 0\\);" 2 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister \\(&\\(\\(struct mytype\\) \\*object\\).indices.token, 0B, 0B, 0\\);" 1 "original" } }
|
||||
|
38
gcc/testsuite/gfortran.dg/coarray_allocate_8.f08
Normal file
38
gcc/testsuite/gfortran.dg/coarray_allocate_8.f08
Normal file
@ -0,0 +1,38 @@
|
||||
! { dg-do run }
|
||||
! { dg-options "-fcoarray=lib -lcaf_single -fdump-tree-original" }
|
||||
|
||||
program alloc_comp
|
||||
implicit none
|
||||
|
||||
type coords
|
||||
real,allocatable :: x(:)
|
||||
real,allocatable :: y(:)
|
||||
real,allocatable :: z(:)
|
||||
end type
|
||||
|
||||
integer :: me,np,n,i
|
||||
type(coords) :: coo[*]
|
||||
|
||||
! with caf_single num_images is always == 1
|
||||
me = this_image(); np = num_images()
|
||||
n = 100
|
||||
|
||||
allocate(coo%x(n),coo%y(n),coo%z(n))
|
||||
|
||||
coo%y = me
|
||||
|
||||
do i=1, n
|
||||
coo%y(i) = coo%y(i) + i
|
||||
end do
|
||||
|
||||
sync all
|
||||
|
||||
! Check the caf_get()-offset is computed correctly.
|
||||
if(me == 1 .and. coo[np]%y(10) /= 11 ) call abort()
|
||||
|
||||
! Check the whole array is correct.
|
||||
if (me == 1 .and. any( coo[np]%y /= [(i, i=2, 101)] ) ) call abort()
|
||||
|
||||
deallocate(coo%x)
|
||||
|
||||
end program
|
31
gcc/testsuite/gfortran.dg/coarray_allocate_9.f08
Normal file
31
gcc/testsuite/gfortran.dg/coarray_allocate_9.f08
Normal file
@ -0,0 +1,31 @@
|
||||
! { dg-do run }
|
||||
! { dg-options "-fcoarray=lib -lcaf_single" }
|
||||
|
||||
! Contributed by Damian Rouson
|
||||
|
||||
program main
|
||||
implicit none
|
||||
|
||||
type particles
|
||||
real x(2)
|
||||
end type
|
||||
|
||||
type vector
|
||||
type(particles), allocatable :: v(:)
|
||||
end type
|
||||
|
||||
type(vector) :: outbox[*]
|
||||
type(particles), allocatable :: object(:)[:]
|
||||
|
||||
allocate(outbox%v(1), source=particles(this_image()))
|
||||
|
||||
if (any( outbox[1]%v(1)%x(1:2) /= [ 1.0, 1.0] )) call abort()
|
||||
if (any( outbox[1]%v(1)%x(:) /= [ 1.0, 1.0] )) call abort()
|
||||
if (any( outbox[1]%v(1)%x /= [ 1.0, 1.0] )) call abort()
|
||||
|
||||
allocate(object(1)[*], source=particles(this_image()))
|
||||
|
||||
if (any( object(1)[1]%x(1:2) /= [ 1.0, 1.0] )) call abort()
|
||||
if (any( object(1)[1]%x(:) /= [ 1.0, 1.0] )) call abort()
|
||||
if (any( object(1)[1]%x /= [ 1.0, 1.0] )) call abort()
|
||||
end program
|
@ -13,8 +13,8 @@
|
||||
deallocate(xx,yy,stat=stat, errmsg=errmsg)
|
||||
end
|
||||
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register .4, 1, &xx.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register .8, 1, &yy.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(4, 1, &xx.token, \\(void \\*\\) &xx, &stat.., &errmsg, 200\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(8, 1, &yy.token, \\(void \\*\\) &yy, &stat.., &errmsg, 200\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&xx.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&yy.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&yy.token, 0B, 0B, 0.;" 1 "original" } }
|
||||
|
@ -15,8 +15,8 @@
|
||||
deallocate(xx,yy,stat=stat, errmsg=errmsg)
|
||||
end
|
||||
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register .1, 1, &xx._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register .1, 1, &yy._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(1, 1, &xx._data.token, \\(void \\*\\) &xx._data, &stat.., &errmsg, 200\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(1, 1, &yy._data.token, \\(void \\*\\) &yy._data, &stat.., &errmsg, 200\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&xx._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&yy._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&yy._data.token, 0B, 0B, 0.;" 1 "original" } }
|
||||
|
@ -16,8 +16,8 @@ subroutine test
|
||||
deallocate(xx,yy,stat=stat, errmsg=errmsg)
|
||||
end
|
||||
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register .1, 1, &xx._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register .1, 1, &yy._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(1, 1, &xx._data.token, \\(void \\*\\) &xx._data, &stat.., &errmsg, 200\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(1, 1, &yy._data.token, \\(void \\*\\) &yy._data, &stat.., &errmsg, 200\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&xx._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&yy._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&yy._data.token, 0B, 0B, 0.;" 1 "original" } }
|
||||
|
@ -38,8 +38,9 @@ B(1:5) = B(3:7)
|
||||
if (any (A-B /= 0)) call abort
|
||||
end
|
||||
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_get \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, &parm.\[0-9\]+, 4, 4, 0, 0B\\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_get \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, &parm.\[0-9\]+, 4, 4, 1, 0B\\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_get \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, &p, 4, 4, 1, 0B\\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_get \\\(caf_token.1, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) b, 1, &parm.\[0-9\]+, 0B, &p, 4, 4, 0, 0B\\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_sendget \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, 4, 4, 0\\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_sendget \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, _gfortran_caf_this_image \\\(0\\\), &parm.\[0-9\]+, 0B, caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, 4, 4, 0, 0B\\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_sendget \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, _gfortran_caf_this_image \\\(0\\\), &parm.\[0-9\]+, 0B, caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, 4, 4, 1, 0B\\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_get_by_ref \\\(caf_token.0, 1, &p, &caf_ref.\[0-9\]+, 4, 4, 1, 0, 0B\\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_get_by_ref \\\(caf_token.1, 1, &p, &caf_ref.\[0-9\]+, 4, 4, 0, 0, 0B\\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_sendget \\\(caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, caf_token.0, \\\(integer\\\(kind=\[48\]\\\)\\\) parm.\[0-9\]+.data - \\\(integer\\\(kind=\[48\]\\\)\\\) a, 1, &parm.\[0-9\]+, 0B, 4, 4, 0, 0B\\\);" 1 "original" } }
|
||||
|
||||
|
@ -8,5 +8,5 @@ allocate(CAF(1)[*])
|
||||
allocate(CAF_SCALAR[*])
|
||||
end
|
||||
|
||||
! { dg-final { scan-tree-dump-times "caf.data = \\(void . restrict\\) _gfortran_caf_register \\(4, 1, &caf.token, 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "caf_scalar.data = \\(void . restrict\\) _gfortran_caf_register \\(4, 1, &caf_scalar.token, 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(4, 1, &caf.token, \\(void \\*\\) &caf, 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(4, 1, &caf_scalar.token, \\(void \\*\\) &caf_scalar, 0B, 0B, 0\\);" 1 "original" } }
|
||||
|
@ -27,10 +27,10 @@ lock(four(1)[6], acquired_lock=ll, stat=ii)
|
||||
unlock(four(2)[7])
|
||||
end
|
||||
|
||||
! { dg-final { scan-tree-dump-times "one = \\(void \\* \\* restrict\\) _gfortran_caf_register \\(1, 2, \\(void \\* \\*\\) &caf_token.., 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "two = \\(void \\*\\\[25\\\] \\* restrict\\) _gfortran_caf_register \\(25, 2, \\(void \\* \\*\\) &caf_token.., 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "three.data = \\(void \\* restrict\\) _gfortran_caf_register \\(1, 3, &three.token, &stat.., 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "four.data = \\(void \\* restrict\\) _gfortran_caf_register \\(7, 3, &four.token, &stat.., 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(1, 2, \\(void \\* \\*\\) &caf_token.., \\(void \\*\\) &desc.., 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(25, 2, \\(void \\* \\*\\) &caf_token.., \\(void \\*\\) &desc.., 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(1, 3, &three.token, \\(void \\*\\) &three, &stat.., 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(7, 3, &four.token, \\(void \\*\\) &four, &stat.., 0B, 0\\);" 1 "original" } }
|
||||
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(caf_token.., 0, 0, 0B, 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(caf_token.., 0, 0, 0B, 0B, 0\\);" 1 "original" } }
|
||||
@ -38,9 +38,9 @@ end
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(caf_token.., \\(3 - \\(integer\\(kind=4\\)\\) parm...dim\\\[0\\\].lbound\\) \\+ \\(integer\\(kind=4\\)\\) MAX_EXPR <\\(parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound\\) \\+ 1, 0> \\* \\(3 - \\(integer\\(kind=4\\)\\) parm...dim\\\[1\\\].lbound\\), 0, 0B, &ii, 0B, 0\\);|_gfortran_caf_lock \\(caf_token.1, \\(3 - parm...dim\\\[0\\\].lbound\\) \\+ MAX_EXPR <\\(parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound\\) \\+ 1, 0> \\* \\(3 - parm...dim\\\[1\\\].lbound\\), 0, 0B, &ii, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(caf_token.., \\(2 - \\(integer\\(kind=4\\)\\) parm...dim\\\[0\\\].lbound\\) \\+ \\(integer\\(kind=4\\)\\) MAX_EXPR <\\(parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound\\) \\+ 1, 0> \\* \\(3 - \\(integer\\(kind=4\\)\\) parm...dim\\\[1\\\].lbound\\), 0, &ii, 0B, 0\\);|_gfortran_caf_unlock \\(caf_token.., \\(2 - parm...dim\\\[0\\\].lbound\\) \\+ MAX_EXPR <\\(parm...dim\\\[0\\\].ubound - parm...dim\\\[0\\\].lbound\\) \\+ 1, 0> \\* \\(3 - parm...dim\\\[1\\\].lbound\\), 0, &ii, 0B, 0\\);" 1 "original" } }
|
||||
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(three.token, 0, 5 - \\(integer\\(kind=4\\)\\) three.dim\\\[0\\\].lbound, &acquired.8, 0B, 0B, 0\\);|_gfortran_caf_lock \\(three.token, 0, 5 - three.dim\\\[0\\\].lbound, &acquired.., 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(three.token, 0, 5 - \\(integer\\(kind=4\\)\\) three.dim\\\[0\\\].lbound, &acquired.\[0-9\]+, 0B, 0B, 0\\);|_gfortran_caf_lock \\(three.token, 0, 5 - three.dim\\\[0\\\].lbound, &acquired.\[0-9\]+, 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(three.token, 0, 8 - \\(integer\\(kind=4\\)\\) three.dim\\\[0\\\].lbound, &ii, 0B, 0\\);|_gfortran_caf_unlock \\(three.token, 0, 8 - three.dim\\\[0\\\].lbound, &ii, 0B, 0\\);" 1 "original" } }
|
||||
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(four.token, 1 - \\(integer\\(kind=4\\)\\) four.dim\\\[0\\\].lbound, 7 - \\(integer\\(kind=4\\)\\) four.dim\\\[1\\\].lbound, &acquired.., &ii, 0B, 0\\);|_gfortran_caf_lock \\(four.token, 1 - four.dim\\\[0\\\].lbound, 7 - four.dim\\\[1\\\].lbound, &acquired.., &ii, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(four.token, 1 - \\(integer\\(kind=4\\)\\) four.dim\\\[0\\\].lbound, 7 - \\(integer\\(kind=4\\)\\) four.dim\\\[1\\\].lbound, &acquired.\[0-9\]+, &ii, 0B, 0\\);|_gfortran_caf_lock \\(four.token, 1 - four.dim\\\[0\\\].lbound, 7 - four.dim\\\[1\\\].lbound, &acquired.\[0-9\]+, &ii, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(four.token, 2 - \\(integer\\(kind=4\\)\\) four.dim\\\[0\\\].lbound, 8 - \\(integer\\(kind=4\\)\\) four.dim\\\[1\\\].lbound, 0B, 0B, 0\\);|_gfortran_caf_unlock \\(four.token, 2 - four.dim\\\[0\\\].lbound, 8 - four.dim\\\[1\\\].lbound, 0B, 0B, 0\\);" 1 "original" } }
|
||||
|
||||
|
@ -10,4 +10,4 @@ class(t) :: x
|
||||
allocate(x%x[*])
|
||||
end subroutine test
|
||||
|
||||
! { dg-final { scan-tree-dump-times "x->_data->x.data = _gfortran_caf_register \\(4, 1, &x->_data->x.token, 0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "_gfortran_caf_register \\(4, 1, &x->_data->x.token, \\(void \\*\\) &x->_data->x, 0B, 0B, 0\\);" 1 "original" } }
|
||||
|
@ -18,4 +18,4 @@ end
|
||||
! { dg-final { scan-tree-dump-times "foo \\(struct __class_MAIN___T_0_1t & restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "bar \\(struct __class_MAIN___T_0_1t \\* x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "bar \\(0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data._data.token, \\(integer\\(kind=\[48\]\\)\\) class..._data.data - \\(integer\\(kind=\[48\]\\)\\) y._data._data.data\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data.token, \\(integer\\(kind=\[48\]\\)\\) class..._data.data - \\(integer\\(kind=\[48\]\\)\\) y._data.data\\);" 1 "original" } }
|
||||
|
@ -18,4 +18,4 @@ end
|
||||
! { dg-final { scan-tree-dump-times "foo \\(struct __class_MAIN___T_1_1t & restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "bar \\(struct __class_MAIN___T_1_1t \\* x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "bar \\(0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data._data.token, \\(integer\\(kind=\[48\]\\)\\) class..._data.data - \\(integer\\(kind=\[48\]\\)\\) y._data._data.data\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data.token, \\(integer\\(kind=\[48\]\\)\\) class..._data.data - \\(integer\\(kind=\[48\]\\)\\) y._data.data\\);" 1 "original" } }
|
||||
|
@ -18,4 +18,4 @@ end
|
||||
! { dg-final { scan-tree-dump-times "foo \\(struct __class_MAIN___T_1_1t & restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "bar \\(struct __class_MAIN___T_1_1t \\* x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) caf_offset..\\)" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "bar \\(0B, 0B, 0\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data._data.token, \\(integer\\(kind=\[48\]\\)\\) class..._data.data - \\(integer\\(kind=\[48\]\\)\\) y._data._data.data\\);" 1 "original" } }
|
||||
! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data.token, \\(integer\\(kind=\[48\]\\)\\) class..._data.data - \\(integer\\(kind=\[48\]\\)\\) y._data.data\\);" 1 "original" } }
|
||||
|
@ -14,7 +14,7 @@ program pmup
|
||||
integer :: ii
|
||||
|
||||
!! --- ONE ---
|
||||
allocate(real :: a(3)[*])
|
||||
allocate(real :: a(3)[*]) ! { dg-error "Sorry, coindexed access to an unlimited polymorphic object at" }
|
||||
IF (this_image() == num_images()) THEN
|
||||
SELECT TYPE (a)
|
||||
TYPE IS (real)
|
||||
@ -43,11 +43,11 @@ program pmup
|
||||
|
||||
!! --- TWO ---
|
||||
deallocate(a)
|
||||
allocate(t :: a(3)[*])
|
||||
allocate(t :: a(3)[*]) ! { dg-error "Sorry, coindexed access to an unlimited polymorphic object at" }
|
||||
IF (this_image() == num_images()) THEN
|
||||
SELECT TYPE (a)
|
||||
TYPE IS (t) ! FIXME: When implemented, turn into "do-do run"
|
||||
a(:)[1]%a = 4.0 ! { dg-error "Sorry, coindexed access at \\(1\\) to a scalar component with an array partref is not yet supported" }
|
||||
TYPE IS (t)
|
||||
a(:)[1]%a = 4.0
|
||||
END SELECT
|
||||
END IF
|
||||
SYNC ALL
|
||||
@ -57,8 +57,8 @@ program pmup
|
||||
TYPE IS (real)
|
||||
ii = a(1)[1]
|
||||
call abort()
|
||||
TYPE IS (t) ! FIXME: When implemented, turn into "do-do run"
|
||||
IF (ALL(A(:)[1]%a == 4.0)) THEN ! { dg-error "Sorry, coindexed access at \\(1\\) to a scalar component with an array partref is not yet supported" }
|
||||
TYPE IS (t)
|
||||
IF (ALL(A(:)[1]%a == 4.0)) THEN
|
||||
!WRITE(*,*) 'OK'
|
||||
ELSE
|
||||
WRITE(*,*) 'FAIL'
|
||||
|
@ -1,3 +1,37 @@
|
||||
2016-09-19 Andre Vehreschild <vehre@gcc.gnu.org>
|
||||
|
||||
* caf/libcaf.h: Add caf_reference_type.
|
||||
* caf/mpi.c: Adapted signature of caf_register().
|
||||
* caf/single.c (struct caf_single_token): Added to keep the pointer
|
||||
to the memory registered and array descriptor.
|
||||
(caf_internal_error): Added convenience interface.
|
||||
(_gfortran_caf_register): Adapted to work with caf_single_token and
|
||||
return memory in the array descriptor.
|
||||
(_gfortran_caf_deregister): Same.
|
||||
(assign_char1_from_char4): Fixed style.
|
||||
(convert_type): Fixed incorrect conversion.
|
||||
(_gfortran_caf_get): Adapted to work with caf_single_token.
|
||||
(_gfortran_caf_send): Same.
|
||||
(_gfortran_caf_sendget): Same.
|
||||
(copy_data): Added to stop repeating it in all _by_ref functions.
|
||||
(get_for_ref): Recursive getting of coarray data using a chain of
|
||||
references.
|
||||
(_gfortran_caf_get_by_ref): Driver for computing the memory needed for
|
||||
the get and checking properties of the operation.
|
||||
(send_by_ref): Same as get_for_ref but for sending data.
|
||||
(_gfortran_caf_send_by_ref): Same like caf_get_by_ref but for sending.
|
||||
(_gfortran_caf_sendget_by_ref): Uses get_by_ref and send_by_ref to
|
||||
implement sendget for reference chains.
|
||||
(_gfortran_caf_atomic_define): Adapted to work with caf_single_token.
|
||||
(_gfortran_caf_atomic_ref): Likewise.
|
||||
(_gfortran_caf_atomic_cas): Likewise.
|
||||
(_gfortran_caf_atomic_op): Likewise.
|
||||
(_gfortran_caf_event_post): Likewise.
|
||||
(_gfortran_caf_event_wait): Likewise.
|
||||
(_gfortran_caf_event_query): Likewise.
|
||||
(_gfortran_caf_lock): Likewise.
|
||||
(_gfortran_caf_unlock): Likewise.
|
||||
|
||||
2016-09-09 Steven G. Kargl <kargl@gcc.gnu.org>
|
||||
|
||||
PR fortran/77507
|
||||
|
@ -90,6 +90,81 @@ typedef struct caf_vector_t {
|
||||
}
|
||||
caf_vector_t;
|
||||
|
||||
typedef enum caf_ref_type_t {
|
||||
/* Reference a component of a derived type, either regular one or an
|
||||
allocatable or pointer type. For regular ones idx in caf_reference_t is
|
||||
set to -1. */
|
||||
CAF_REF_COMPONENT,
|
||||
/* Reference an allocatable array. */
|
||||
CAF_REF_ARRAY,
|
||||
/* Reference a non-allocatable/non-pointer array. */
|
||||
CAF_REF_STATIC_ARRAY
|
||||
} caf_ref_type_t;
|
||||
|
||||
typedef enum caf_array_ref_t {
|
||||
/* No array ref. This terminates the array ref. */
|
||||
CAF_ARR_REF_NONE = 0,
|
||||
/* Reference array elements given by a vector. Only for this mode
|
||||
caf_reference_t.u.a.dim[i].v is valid. */
|
||||
CAF_ARR_REF_VECTOR,
|
||||
/* A full array ref (:). */
|
||||
CAF_ARR_REF_FULL,
|
||||
/* Reference a range on elements given by start, end and stride. */
|
||||
CAF_ARR_REF_RANGE,
|
||||
/* Only a single item is referenced given in the start member. */
|
||||
CAF_ARR_REF_SINGLE,
|
||||
/* An array ref of the kind (i:), where i is an arbitrary valid index in the
|
||||
array. The index i is given in the start member. */
|
||||
CAF_ARR_REF_OPEN_END,
|
||||
/* An array ref of the kind (:i), where the lower bound of the array ref
|
||||
is given by the remote side. The index i is given in the end member. */
|
||||
CAF_ARR_REF_OPEN_START
|
||||
} caf_array_ref_t;
|
||||
|
||||
/* References to remote components of a derived type. */
|
||||
typedef struct caf_reference_t {
|
||||
/* A pointer to the next ref or NULL. */
|
||||
struct caf_reference_t *next;
|
||||
/* The type of the reference. */
|
||||
/* caf_ref_type_t, replaced by int to allow specification in fortran FE. */
|
||||
int type;
|
||||
/* The size of an item referenced in bytes. I.e. in an array ref this is
|
||||
the factor to advance the array pointer with to get to the next item.
|
||||
For component refs this gives just the size of the element referenced. */
|
||||
size_t item_size;
|
||||
union {
|
||||
struct {
|
||||
/* The offset (in bytes) of the component in the derived type. */
|
||||
ptrdiff_t offset;
|
||||
/* The offset (in bytes) to the caf_token associated with this
|
||||
component. NULL, when not allocatable/pointer ref. */
|
||||
ptrdiff_t caf_token_offset;
|
||||
} c;
|
||||
struct {
|
||||
/* The mode of the array ref. See CAF_ARR_REF_*. */
|
||||
/* caf_array_ref_t, replaced by unsigend char to allow specification in
|
||||
fortran FE. */
|
||||
unsigned char mode[GFC_MAX_DIMENSIONS];
|
||||
/* The type of a static array. Unset for array's with descriptors. */
|
||||
int static_array_type;
|
||||
/* Subscript refs (s) or vector refs (v). */
|
||||
union {
|
||||
struct {
|
||||
/* The start and end boundary of the ref and the stride. */
|
||||
index_type start, end, stride;
|
||||
} s;
|
||||
struct {
|
||||
/* nvec entries of kind giving the elements to reference. */
|
||||
void *vector;
|
||||
/* The number of entries in vector. */
|
||||
size_t nvec;
|
||||
/* The integer kind used for the elements in vector. */
|
||||
int kind;
|
||||
} v;
|
||||
} dim[GFC_MAX_DIMENSIONS];
|
||||
} a;
|
||||
} u;
|
||||
} caf_reference_t;
|
||||
|
||||
void _gfortran_caf_init (int *, char ***);
|
||||
void _gfortran_caf_finalize (void);
|
||||
@ -97,8 +172,8 @@ void _gfortran_caf_finalize (void);
|
||||
int _gfortran_caf_this_image (int);
|
||||
int _gfortran_caf_num_images (int, int);
|
||||
|
||||
void *_gfortran_caf_register (size_t, caf_register_t, caf_token_t *, int *,
|
||||
char *, int);
|
||||
void _gfortran_caf_register (size_t, caf_register_t, caf_token_t *,
|
||||
gfc_descriptor_t *, int *, char *, int);
|
||||
void _gfortran_caf_deregister (caf_token_t *, int *, char *, int);
|
||||
|
||||
void _gfortran_caf_sync_all (int *, char *, int);
|
||||
@ -130,6 +205,18 @@ void _gfortran_caf_sendget (caf_token_t, size_t, int, gfc_descriptor_t *,
|
||||
caf_vector_t *, caf_token_t, size_t, int,
|
||||
gfc_descriptor_t *, caf_vector_t *, int, int, bool);
|
||||
|
||||
void _gfortran_caf_get_by_ref (caf_token_t token, int image_idx,
|
||||
gfc_descriptor_t *dst, caf_reference_t *refs, int dst_kind,
|
||||
int src_kind, bool may_require_tmp, bool dst_reallocatable, int *stat);
|
||||
void _gfortran_caf_send_by_ref (caf_token_t token, int image_index,
|
||||
gfc_descriptor_t *src, caf_reference_t *refs, int dst_kind,
|
||||
int src_kind, bool may_require_tmp, bool dst_reallocatable, int *stat);
|
||||
void _gfortran_caf_sendget_by_ref (
|
||||
caf_token_t dst_token, int dst_image_index, caf_reference_t *dst_refs,
|
||||
caf_token_t src_token, int src_image_index, caf_reference_t *src_refs,
|
||||
int dst_kind, int src_kind, bool may_require_tmp, int *dst_stat,
|
||||
int *src_stat);
|
||||
|
||||
void _gfortran_caf_atomic_define (caf_token_t, size_t, int, void *, int *,
|
||||
int, int);
|
||||
void _gfortran_caf_atomic_ref (caf_token_t, size_t, int, void *, int *,
|
||||
|
@ -131,7 +131,8 @@ _gfortran_caf_num_images (int distance __attribute__ ((unused)),
|
||||
|
||||
void *
|
||||
_gfortran_caf_register (size_t size, caf_register_t type, caf_token_t *token,
|
||||
int *stat, char *errmsg, int errmsg_len)
|
||||
int *stat, char *errmsg, int errmsg_len,
|
||||
int num_alloc_comps __attribute__ ((unused)))
|
||||
{
|
||||
void *local;
|
||||
int err;
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user