Commit bbf18dc5 by Paul Thomas

gfortran.texi: Add description in sections on TS 29113 and further interoperability with C.

2019-01-12  Paul Thomas  <pault@gcc.gnu.org>

	* gfortran.texi : Add description in sections on TS 29113 and
	further interoperability with C.
	* trans-array.c (gfc_conv_descriptor_attribute): New function.
	(gfc_get_dataptr_offset): Remove static function attribute.
	* trans-array.h : Add prototypes for above functions.
	* trans-decl.c : Add declarations for the library functions
	cfi_desc_to_gfc_desc and gfc_desc_to_cfi_desc.
	* trans-expr.c (gfc_conv_gfc_desc_to_cfi_desc): New function.
	(gfc_conv_procedure_call): Call it for scalar and array actual
	arguments, when the formal arguments are bind_c with assumed
	shape or assumed rank.
	* trans.h : External declarations for gfor_fndecl_cfi_to_gfc
	and gfor_fndecl_gfc_to_cfi.

2019-01-12  Paul Thomas  <pault@gcc.gnu.org>

	* gfortran.dg/ISO_Fortran_binding_1.f90 : New test.
	* gfortran.dg/ISO_Fortran_binding_1.c : Auxilliary file for test.
	* gfortran.dg/ISO_Fortran_binding_2.f90 : New test.
	* gfortran.dg/ISO_Fortran_binding_2.c : Auxilliary file for test.
	* gfortran.dg/bind_c_array_params_2.f90 : Change search string
	for dump tree scan.

2019-01-12  Paul Thomas  <pault@gcc.gnu.org>

	* ISO_Fortran_binding.h : New file.
	* Makefile.am : Include ISO_Fortran_binding.c in the list of
	files to compile.
	* Makefile.in : Regenerated.
	* gfortran.map : Add _gfortran_cfi_desc_to_gfc_desc,
	_gfortran_gfc_desc_to_cfi_desc and the CFI API functions.
	* runtime/ISO_Fortran_binding.c : New file containing the new
	functions added to the map.

From-SVN: r267881
parent af79605e
2019-01-12 Paul Thomas <pault@gcc.gnu.org>
* gfortran.texi : Add description in sections on TS 29113 and
further interoperability with C.
* trans-array.c (gfc_conv_descriptor_attribute): New function.
(gfc_get_dataptr_offset): Remove static function attribute.
* trans-array.h : Add prototypes for above functions.
* trans-decl.c : Add declarations for the library functions
cfi_desc_to_gfc_desc and gfc_desc_to_cfi_desc.
* trans-expr.c (gfc_conv_gfc_desc_to_cfi_desc): New function.
(gfc_conv_procedure_call): Call it for scalar and array actual
arguments, when the formal arguments are bind_c with assumed
shape or assumed rank.
* trans.h : External declarations for gfor_fndecl_cfi_to_gfc
and gfor_fndecl_gfc_to_cfi.
2019-01-11 Steven G. Kargl <kargl@gcc.gnu.org> 2019-01-11 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/35031 PR fortran/35031
......
...@@ -1103,8 +1103,6 @@ arrays are supported for named constants (@code{PARAMETER}). ...@@ -1103,8 +1103,6 @@ arrays are supported for named constants (@code{PARAMETER}).
@node Fortran 2018 status @node Fortran 2018 status
@section Status of Fortran 2018 support @section Status of Fortran 2018 support
So far very little work has been done to support Fortran 2018.
@itemize @itemize
@item ERROR STOP in a PURE procedure @item ERROR STOP in a PURE procedure
An @code{ERROR STOP} statement is permitted in a @code{PURE} An @code{ERROR STOP} statement is permitted in a @code{PURE}
...@@ -1143,8 +1141,12 @@ attribute is compatible with TS 29113. ...@@ -1143,8 +1141,12 @@ attribute is compatible with TS 29113.
@item Assumed types (@code{TYPE(*)}). @item Assumed types (@code{TYPE(*)}).
@item Assumed-rank (@code{DIMENSION(..)}). However, the array descriptor @item Assumed-rank (@code{DIMENSION(..)}).
of the TS is not yet supported.
@item ISO_Fortran_binding (now in Fortran 2018 18.4) is implemented such that
conversion of the array descriptor for assumed type or assumed rank arrays is
done in the library. The include file ISO_Fortran_binding.h is can be found in
@code{~prefix/lib/gcc/$target/$version}.
@end itemize @end itemize
...@@ -3430,11 +3432,14 @@ and constraints, it adds assumed-type (@code{TYPE(*)}) and assumed-rank ...@@ -3430,11 +3432,14 @@ and constraints, it adds assumed-type (@code{TYPE(*)}) and assumed-rank
assumed-shape, assumed-rank and deferred-shape arrays, including assumed-shape, assumed-rank and deferred-shape arrays, including
allocatables and pointers. allocatables and pointers.
Note: Currently, GNU Fortran does not support the array descriptor Note: Currently, GNU Fortran does not use internally the array descriptor
(dope vector) as specified in the Technical Specification, but uses (dope vector) as specified in the Technical Specification, but uses
an array descriptor with different fields. The Chasm Language an array descriptor with different fields. Assumed type and assumed rank
Interoperability Tools, @url{http://chasm-interop.sourceforge.net/}, formal arguments are converted in the library to the specified form. The
provide an interface to GNU Fortran's array descriptor. ISO_Fortran_binding API functions (also Fortran 2018 18.4) are implemented
in libgfortran. Alternatively, the Chasm Language Interoperability Tools,
@url{http://chasm-interop.sourceforge.net/}, provide an interface to GNU
Fortran's array descriptor.
The Technical Specification adds the following new features, which The Technical Specification adds the following new features, which
are supported by GNU Fortran: are supported by GNU Fortran:
......
...@@ -293,6 +293,22 @@ gfc_conv_descriptor_rank (tree desc) ...@@ -293,6 +293,22 @@ gfc_conv_descriptor_rank (tree desc)
tree tree
gfc_conv_descriptor_attribute (tree desc)
{
tree tmp;
tree dtype;
dtype = gfc_conv_descriptor_dtype (desc);
tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
GFC_DTYPE_ATTRIBUTE);
gcc_assert (tmp!= NULL_TREE
&& TREE_TYPE (tmp) == short_integer_type_node);
return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
dtype, tmp, NULL_TREE);
}
tree
gfc_get_descriptor_dimension (tree desc) gfc_get_descriptor_dimension (tree desc)
{ {
tree type, field; tree type, field;
...@@ -6767,7 +6783,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, ...@@ -6767,7 +6783,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
/* Calculate the overall offset, including subreferences. */ /* Calculate the overall offset, including subreferences. */
static void void
gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset, gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
bool subref, gfc_expr *expr) bool subref, gfc_expr *expr)
{ {
......
...@@ -136,6 +136,8 @@ void gfc_conv_tmp_array_ref (gfc_se * se); ...@@ -136,6 +136,8 @@ void gfc_conv_tmp_array_ref (gfc_se * se);
/* Translate a reference to an array temporary. */ /* Translate a reference to an array temporary. */
void gfc_conv_tmp_ref (gfc_se *); void gfc_conv_tmp_ref (gfc_se *);
/* Calculate the overall offset, including subreferences. */
void gfc_get_dataptr_offset (stmtblock_t*, tree, tree, tree, bool, gfc_expr*);
/* Obtain the span of an array. */ /* Obtain the span of an array. */
tree gfc_get_array_span (tree, gfc_expr *); tree gfc_get_array_span (tree, gfc_expr *);
/* Evaluate an array expression. */ /* Evaluate an array expression. */
...@@ -167,6 +169,7 @@ tree gfc_conv_descriptor_offset_get (tree); ...@@ -167,6 +169,7 @@ tree gfc_conv_descriptor_offset_get (tree);
tree gfc_conv_descriptor_span_get (tree); tree gfc_conv_descriptor_span_get (tree);
tree gfc_conv_descriptor_dtype (tree); tree gfc_conv_descriptor_dtype (tree);
tree gfc_conv_descriptor_rank (tree); tree gfc_conv_descriptor_rank (tree);
tree gfc_conv_descriptor_attribute (tree);
tree gfc_get_descriptor_dimension (tree); tree gfc_get_descriptor_dimension (tree);
tree gfc_conv_descriptor_stride_get (tree, tree); tree gfc_conv_descriptor_stride_get (tree, tree);
tree gfc_conv_descriptor_lbound_get (tree, tree); tree gfc_conv_descriptor_lbound_get (tree, tree);
......
...@@ -114,6 +114,8 @@ tree gfor_fndecl_fdate; ...@@ -114,6 +114,8 @@ tree gfor_fndecl_fdate;
tree gfor_fndecl_ttynam; tree gfor_fndecl_ttynam;
tree gfor_fndecl_in_pack; tree gfor_fndecl_in_pack;
tree gfor_fndecl_in_unpack; tree gfor_fndecl_in_unpack;
tree gfor_fndecl_cfi_to_gfc;
tree gfor_fndecl_gfc_to_cfi;
tree gfor_fndecl_associated; tree gfor_fndecl_associated;
tree gfor_fndecl_system_clock4; tree gfor_fndecl_system_clock4;
tree gfor_fndecl_system_clock8; tree gfor_fndecl_system_clock8;
...@@ -3619,6 +3621,14 @@ gfc_build_builtin_function_decls (void) ...@@ -3619,6 +3621,14 @@ gfc_build_builtin_function_decls (void)
get_identifier (PREFIX("internal_unpack")), ".wR", get_identifier (PREFIX("internal_unpack")), ".wR",
void_type_node, 2, pvoid_type_node, pvoid_type_node); void_type_node, 2, pvoid_type_node, pvoid_type_node);
gfor_fndecl_cfi_to_gfc = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("cfi_desc_to_gfc_desc")), ".ww",
void_type_node, 2, pvoid_type_node, ppvoid_type_node);
gfor_fndecl_gfc_to_cfi = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("gfc_desc_to_cfi_desc")), ".wR",
void_type_node, 2, ppvoid_type_node, pvoid_type_node);
gfor_fndecl_associated = gfc_build_library_function_decl_with_spec ( gfor_fndecl_associated = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("associated")), ".RR", get_identifier (PREFIX("associated")), ".RR",
integer_type_node, 2, ppvoid_type_node, ppvoid_type_node); integer_type_node, 2, ppvoid_type_node, ppvoid_type_node);
......
...@@ -4891,6 +4891,102 @@ expr_may_alias_variables (gfc_expr *e, bool array_may_alias) ...@@ -4891,6 +4891,102 @@ expr_may_alias_variables (gfc_expr *e, bool array_may_alias)
} }
/* Provide an interface between gfortran array descriptors and the F2018:18.4
ISO_Fortran_binding array descriptors. */
static void
gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
{
tree tmp;
tree cfi_desc_ptr;
tree gfc_desc_ptr;
tree type;
int attribute;
symbol_attribute attr = gfc_expr_attr (e);
/* If this is a full array or a scalar, the allocatable and pointer
attributes can be passed. Otherwise it is 'CFI_attribute_other'*/
attribute = 2;
if (!e->rank || gfc_get_full_arrayspec_from_expr (e))
{
if (attr.pointer)
attribute = 0;
else if (attr.allocatable)
attribute = 1;
}
if (e->rank)
{
gfc_conv_expr_descriptor (parmse, e);
/* All the temporary descriptors are marked as DECL_ARTIFICIAL. If
the expression type is different from the descriptor type, then
the offset must be found (eg. to a component ref or substring)
and the dtype updated. */
type = gfc_typenode_for_spec (&e->ts);
if (DECL_ARTIFICIAL (parmse->expr)
&& type != gfc_get_element_type (TREE_TYPE (parmse->expr)))
{
/* Obtain the offset to the data. */
gfc_get_dataptr_offset (&parmse->pre, parmse->expr, parmse->expr,
gfc_index_zero_node, true, e);
/* Update the dtype. */
gfc_add_modify (&parmse->pre,
gfc_conv_descriptor_dtype (parmse->expr),
gfc_get_dtype_rank_type (e->rank, type));
}
else if (!is_subref_array (e) && !DECL_ARTIFICIAL (parmse->expr))
{
/* Make sure that the span is set for expressions where it
might not have been done already. */
tmp = TREE_TYPE (parmse->expr);
tmp = TYPE_SIZE_UNIT (gfc_get_element_type (tmp));
tmp = fold_convert (gfc_array_index_type, tmp);
gfc_conv_descriptor_span_set (&parmse->pre, parmse->expr, tmp);
}
}
else
{
gfc_conv_expr (parmse, e);
/* Copy the scalar for INTENT_IN. */
if (e->expr_type == EXPR_VARIABLE && fsym->attr.intent == INTENT_IN)
parmse->expr = gfc_evaluate_now (parmse->expr, &parmse->pre);
parmse->expr = gfc_conv_scalar_to_descriptor (parmse,
parmse->expr, attr);
}
/* Set the CFI attribute field. */
tmp = gfc_conv_descriptor_attribute (parmse->expr);
tmp = fold_build2_loc (input_location, MODIFY_EXPR,
void_type_node, tmp,
build_int_cst (TREE_TYPE (tmp), attribute));
gfc_add_expr_to_block (&parmse->pre, tmp);
/* Now pass the gfc_descriptor by reference. */
parmse->expr = gfc_build_addr_expr (NULL_TREE, parmse->expr);
/* Variables to point to the gfc and CFI descriptors. */
gfc_desc_ptr = parmse->expr;
cfi_desc_ptr = gfc_create_var (pvoid_type_node, "cfi");
/* Allocate the CFI descriptor and fill the fields. */
tmp = gfc_build_addr_expr (NULL_TREE, cfi_desc_ptr);
tmp = build_call_expr_loc (input_location,
gfor_fndecl_gfc_to_cfi, 2, tmp, gfc_desc_ptr);
gfc_add_expr_to_block (&parmse->pre, tmp);
/* The CFI descriptor is passed to the bind_C procedure. */
parmse->expr = cfi_desc_ptr;
/* Transfer values back to gfc descriptor and free the CFI descriptor. */
tmp = gfc_build_addr_expr (NULL_TREE, parmse->expr);
tmp = build_call_expr_loc (input_location,
gfor_fndecl_cfi_to_gfc, 2, gfc_desc_ptr, tmp);
gfc_prepend_expr_to_block (&parmse->post, tmp);
}
/* Generate code for a procedure call. Note can return se->post != NULL. /* Generate code for a procedure call. Note can return se->post != NULL.
If se->direct_byref is set then se->expr contains the return parameter. If se->direct_byref is set then se->expr contains the return parameter.
Return nonzero, if the call has alternate specifiers. Return nonzero, if the call has alternate specifiers.
...@@ -5234,6 +5330,14 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -5234,6 +5330,14 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
tmp = gfc_get_symbol_decl (e->symtree->n.sym->cp_pointer); tmp = gfc_get_symbol_decl (e->symtree->n.sym->cp_pointer);
parmse.expr = convert (type, tmp); parmse.expr = convert (type, tmp);
} }
else if (sym->attr.is_bind_c && e
&& fsym && fsym->attr.dimension
&& (fsym->as->type == AS_ASSUMED_RANK
|| fsym->as->type == AS_ASSUMED_SHAPE))
/* Implement F2018, C.12.6.1: paragraph (2). */
gfc_conv_gfc_desc_to_cfi_desc (&parmse, e, fsym);
else if (fsym && fsym->attr.value) else if (fsym && fsym->attr.value)
{ {
if (fsym->ts.type == BT_CHARACTER if (fsym->ts.type == BT_CHARACTER
...@@ -5273,6 +5377,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -5273,6 +5377,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
} }
} }
} }
else if (arg->name && arg->name[0] == '%') else if (arg->name && arg->name[0] == '%')
/* Argument list functions %VAL, %LOC and %REF are signalled /* Argument list functions %VAL, %LOC and %REF are signalled
through arg->name. */ through arg->name. */
...@@ -5287,6 +5392,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -5287,6 +5392,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_conv_expr (&parmse, e); gfc_conv_expr (&parmse, e);
parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr); parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr);
} }
else if (e->expr_type == EXPR_FUNCTION else if (e->expr_type == EXPR_FUNCTION
&& e->symtree->n.sym->result && e->symtree->n.sym->result
&& e->symtree->n.sym->result != e->symtree->n.sym && e->symtree->n.sym->result != e->symtree->n.sym
...@@ -5297,6 +5403,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -5297,6 +5403,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
if (fsym && fsym->attr.proc_pointer) if (fsym && fsym->attr.proc_pointer)
parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr); parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr);
} }
else else
{ {
if (e->ts.type == BT_CLASS && fsym if (e->ts.type == BT_CLASS && fsym
...@@ -5670,7 +5777,14 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -5670,7 +5777,14 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
parmse.force_tmp = 1; parmse.force_tmp = 1;
} }
if (e->expr_type == EXPR_VARIABLE if (sym->attr.is_bind_c && e
&& fsym && fsym->attr.dimension
&& (fsym->as->type == AS_ASSUMED_RANK
|| fsym->as->type == AS_ASSUMED_SHAPE))
/* Implement F2018, C.12.6.1: paragraph (2). */
gfc_conv_gfc_desc_to_cfi_desc (&parmse, e, fsym);
else if (e->expr_type == EXPR_VARIABLE
&& is_subref_array (e) && is_subref_array (e)
&& !(fsym && fsym->attr.pointer)) && !(fsym && fsym->attr.pointer))
/* The actual argument is a component reference to an /* The actual argument is a component reference to an
...@@ -5680,6 +5794,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, ...@@ -5680,6 +5794,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_conv_subref_array_arg (&parmse, e, nodesc_arg, gfc_conv_subref_array_arg (&parmse, e, nodesc_arg,
fsym ? fsym->attr.intent : INTENT_INOUT, fsym ? fsym->attr.intent : INTENT_INOUT,
fsym && fsym->attr.pointer); fsym && fsym->attr.pointer);
else if (gfc_is_class_array_ref (e, NULL) else if (gfc_is_class_array_ref (e, NULL)
&& fsym && fsym->ts.type == BT_DERIVED) && fsym && fsym->ts.type == BT_DERIVED)
/* The actual argument is a component reference to an /* The actual argument is a component reference to an
......
...@@ -801,6 +801,8 @@ extern GTY(()) tree gfor_fndecl_ctime; ...@@ -801,6 +801,8 @@ extern GTY(()) tree gfor_fndecl_ctime;
extern GTY(()) tree gfor_fndecl_fdate; extern GTY(()) tree gfor_fndecl_fdate;
extern GTY(()) tree gfor_fndecl_in_pack; extern GTY(()) tree gfor_fndecl_in_pack;
extern GTY(()) tree gfor_fndecl_in_unpack; extern GTY(()) tree gfor_fndecl_in_unpack;
extern GTY(()) tree gfor_fndecl_cfi_to_gfc;
extern GTY(()) tree gfor_fndecl_gfc_to_cfi;
extern GTY(()) tree gfor_fndecl_associated; extern GTY(()) tree gfor_fndecl_associated;
extern GTY(()) tree gfor_fndecl_system_clock4; extern GTY(()) tree gfor_fndecl_system_clock4;
extern GTY(()) tree gfor_fndecl_system_clock8; extern GTY(()) tree gfor_fndecl_system_clock8;
......
/* Test F2008 18.5: ISO_Fortran_binding.h functions. */
#include <ISO_Fortran_binding.h>
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
/* Test the example in F2008 C.12.9: Processing assumed-shape arrays in C,
modified to use CFI_address instead of pointer arithmetic. */
int elemental_mult_c(CFI_cdesc_t * a_desc, CFI_cdesc_t * b_desc,
CFI_cdesc_t * c_desc)
{
CFI_index_t idx[2];
int *res_addr;
int err = 1; /* this error code represents all errors */
if (a_desc->rank == 0)
{
err = *(int*)a_desc->base_addr;
*(int*)a_desc->base_addr = 0;
return err;
}
if (a_desc->type != CFI_type_int
|| b_desc->type != CFI_type_int
|| c_desc->type != CFI_type_int)
return err;
/* Only support two dimensions. */
if (a_desc->rank != 2
|| b_desc->rank != 2
|| c_desc->rank != 2)
return err;
for (idx[0] = 0; idx[0] < a_desc->dim[0].extent; idx[0]++)
for (idx[1] = 0; idx[1] < a_desc->dim[1].extent; idx[1]++)
{
res_addr = CFI_address (a_desc, idx);
*res_addr = *(int*)CFI_address (b_desc, idx)
* *(int*)CFI_address (c_desc, idx);
}
return 0;
}
int deallocate_c(CFI_cdesc_t * dd)
{
return CFI_deallocate(dd);
}
int allocate_c(CFI_cdesc_t * da, CFI_index_t lower[], CFI_index_t upper[])
{
int err = 1;
CFI_index_t idx[2];
int *res_addr;
if (CFI_allocate(da, lower, upper, 0)) return err;
for (idx[0] = 0; idx[0] < da->dim[0].extent; idx[0]++)
for (idx[1] = 0; idx[1] < da->dim[1].extent; idx[1]++)
{
res_addr = CFI_address (da, idx);
*res_addr = (int)((idx[0] + da->dim[0].lower_bound)
* (idx[1] + da->dim[1].lower_bound));
}
return 0;
}
int establish_c(CFI_cdesc_t * desc)
{
typedef struct {double x; double _Complex y;} t;
int err;
CFI_index_t idx[1], extent[1];
t *res_addr;
double value = 1.0;
double complex z_value = 0.0 + 2.0 * I;
extent[0] = 10;
err = CFI_establish((CFI_cdesc_t *)desc,
malloc ((size_t)(extent[0] * sizeof(t))),
CFI_attribute_pointer,
CFI_type_struct,
sizeof(t), 1, extent);
for (idx[0] = 0; idx[0] < extent[0]; idx[0]++)
{
res_addr = (t*)CFI_address (desc, idx);
res_addr->x = value++;
res_addr->y = z_value * (idx[0] + 1);
}
return err;
}
int contiguous_c(CFI_cdesc_t * desc)
{
return CFI_is_contiguous(desc);
}
float section_c(int *std_case, CFI_cdesc_t * source, int *low, int *str)
{
CFI_index_t idx[CFI_MAX_RANK], lower[CFI_MAX_RANK],
strides[CFI_MAX_RANK], upper[CFI_MAX_RANK];
CFI_CDESC_T(1) section;
int ind, size;
float *ret_addr;
float ans = 0.0;
/* Case (i) from F2018:18.5.5.7. */
if (*std_case == 1)
{
lower[0] = (CFI_index_t)low[0];
strides[0] = (CFI_index_t)str[0];
ind = CFI_establish((CFI_cdesc_t *)&section, NULL, CFI_attribute_other,
CFI_type_float, 0, 1, NULL);
if (ind) return -1.0;
ind = CFI_section((CFI_cdesc_t *)&section, source, lower, NULL, strides);
if (ind) return -2.0;
/* Sum over the section */
size = (section.dim[0].extent - 1)
* section.elem_len/section.dim[0].sm + 1;
for (idx[0] = 0; idx[0] < size; idx[0]++)
ans += *(float*)CFI_address ((CFI_cdesc_t*)&section, idx);
return ans;
}
else if (*std_case == 2)
{
int ind;
lower[0] = source->dim[0].lower_bound;
upper[0] = source->dim[0].lower_bound + source->dim[0].extent - 1;
strides[0] = str[0];
lower[1] = upper[1] = source->dim[1].lower_bound + low[1] - 1;
strides[1] = 0;
ind = CFI_establish((CFI_cdesc_t *)&section, NULL, CFI_attribute_other,
CFI_type_float, 0, 1, NULL);
if (ind) return -1.0;
ind = CFI_section((CFI_cdesc_t *)&section, source,
lower, upper, strides);
if (ind) return -2.0;
/* Sum over the section */
size = (section.dim[0].extent - 1)
* section.elem_len/section.dim[0].sm + 1;
for (idx[0] = 0; idx[0] < size; idx[0]++)
ans += *(float*)CFI_address ((CFI_cdesc_t*)&section, idx);
return ans;
}
return 0.0;
}
double select_part_c (CFI_cdesc_t * source)
{
typedef struct {
double x; double _Complex y;
} t;
CFI_CDESC_T(2) component;
CFI_cdesc_t * comp_cdesc = (CFI_cdesc_t *)&component;
CFI_index_t extent[] = {10,10};
CFI_index_t idx[] = {4,0};
double ans = 0.0;
int size;
(void)CFI_establish(comp_cdesc, NULL, CFI_attribute_other,
CFI_type_double_Complex, sizeof(double _Complex),
2, extent);
(void)CFI_select_part(comp_cdesc, source, offsetof(t,y), 0);
/* Sum over comp_cdesc[4,:] */
size = comp_cdesc->dim[1].extent;
for (idx[1] = 0; idx[1] < size; idx[1]++)
ans += cimag (*(double _Complex*)CFI_address ((CFI_cdesc_t*)comp_cdesc,
idx));
return ans;
}
int setpointer_c(CFI_cdesc_t * ptr, int lbounds[])
{
CFI_index_t lower_bounds[] = {lbounds[0],lbounds[1]};
int ind;
ind = CFI_setpointer(ptr, ptr, lower_bounds);
return ind;
}
int assumed_size_c(CFI_cdesc_t * desc)
{
int ierr;
ierr = CFI_is_contiguous(desc);
if (ierr)
return 1;
if (desc->rank)
ierr = 2 * (desc->dim[desc->rank-1].extent
!= (CFI_index_t)(long long)(-1));
else
ierr = 3;
return ierr;
}
! { dg-do run }
! { dg-additional-sources ISO_Fortran_binding_1.c }
!
! Test F2008 18.5: ISO_Fortran_binding.h functions.
!
USE, INTRINSIC :: ISO_C_BINDING
TYPE, BIND(C) :: T
REAL(C_DOUBLE) :: X
complex(C_DOUBLE_COMPLEX) :: Y
END TYPE
type :: mytype
integer :: i
integer :: j
end type
INTERFACE
FUNCTION elemental_mult(a, b, c) BIND(C, NAME="elemental_mult_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
type(*), DIMENSION(..) :: a, b, c
END FUNCTION elemental_mult
FUNCTION c_deallocate(a) BIND(C, NAME="deallocate_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
type(*), DIMENSION(..) :: a
END FUNCTION c_deallocate
FUNCTION c_allocate(a, lower, upper) BIND(C, NAME="allocate_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
type(*), DIMENSION(..) :: a
integer(C_INTPTR_T), DIMENSION(15) :: lower, upper
END FUNCTION c_allocate
FUNCTION c_establish(a) BIND(C, NAME="establish_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
import
INTEGER(C_INT) :: err
type (T), DIMENSION(..), intent(out) :: a
END FUNCTION c_establish
FUNCTION c_contiguous(a) BIND(C, NAME="contiguous_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
type(*), DIMENSION(..) :: a
END FUNCTION c_contiguous
FUNCTION c_section(std_case, a, lower, strides) BIND(C, NAME="section_c") RESULT(ans)
USE, INTRINSIC :: ISO_C_BINDING
real(C_FLOAT) :: ans
INTEGER(C_INT) :: std_case
INTEGER(C_INT), dimension(15) :: lower
INTEGER(C_INT), dimension(15) :: strides
type(*), DIMENSION(..) :: a
END FUNCTION c_section
FUNCTION c_select_part(a) BIND(C, NAME="select_part_c") RESULT(ans)
USE, INTRINSIC :: ISO_C_BINDING
real(C_DOUBLE) :: ans
type(*), DIMENSION(..) :: a
END FUNCTION c_select_part
FUNCTION c_setpointer(a, lbounds) BIND(C, NAME="setpointer_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
INTEGER(C_INT), dimension(2) :: lbounds
type(*), DIMENSION(..) :: a
END FUNCTION c_setpointer
FUNCTION c_assumed_size(a) BIND(C, NAME="assumed_size_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
type(*), DIMENSION(..) :: a
END FUNCTION c_assumed_size
END INTERFACE
integer, dimension(:,:), allocatable :: x, y, z
integer, dimension(2,2) :: a, b, c
integer, dimension(4,4) :: d
integer :: i = 42, j, k
integer(C_INTPTR_T), dimension(15) :: lower, upper
real, dimension(10,10) :: arg
type (mytype), dimension(2,2) :: der
allocate (x, source = reshape ([4,3,2,1], [2,2]))
allocate (y, source = reshape ([2,3,4,5], [2,2]))
allocate (z, source = reshape ([0,0,0,0], [2,2]))
call test_CFI_address
call test_CFI_deallocate
call test_CFI_allocate
call test_CFI_establish
call test_CFI_contiguous (a)
call test_CFI_section (arg)
call test_CFI_select_part
call test_CFI_setpointer
call test_assumed_size (a)
contains
subroutine test_CFI_address
! Basic test that CFI_desc_t can be passed and that CFI_address works
if (elemental_mult (z, x, y) .ne. 0) stop 1
if (any (z .ne. reshape ([8,9,8,5], [2,2]))) stop 2
a = reshape ([4,3,2,1], [2,2])
b = reshape ([2,3,4,5], [2,2])
c = 0
! Verify that components of arrays of derived types are OK.
der%j = a
! Check that non-pointer/non-allocatable arguments are OK
if (elemental_mult (c, der%j, b) .ne. 0) stop 3
if (any (c .ne. reshape ([8,9,8,5], [2,2]))) stop 4
! Check array sections
d = 0
d(4:2:-2, 1:3:2) = b
if (elemental_mult (c, a, d(4:2:-2, 1:3:2)) .ne. 0) stop 5
if (any (c .ne. reshape ([8,9,8,5], [2,2]))) stop 6
! If a scalar result is passed to 'elemental_mult' it is returned
! as the function result and then zeroed. This tests that scalars
! are correctly converted to CF_desc_t.
if ((elemental_mult (i, a, b) .ne. 42) &
.or. (i .ne. 0)) stop 7
deallocate (y,z)
end subroutine test_CFI_address
subroutine test_CFI_deallocate
! Test CFI_deallocate.
if (c_deallocate (x) .ne. 0) stop 8
if (allocated (x)) stop 9
end subroutine test_CFI_deallocate
subroutine test_CFI_allocate
! Test CFI_allocate.
lower(1:2) = [2,2]
upper(1:2) = [10,10]
if (c_allocate (x, lower, upper) .ne. 0) stop 10
if (.not.allocated (x)) stop 11
if (any (lbound (x) .ne. lower(1:2))) stop 12
if (any (ubound (x) .ne. upper(1:2))) stop 13
! Elements are filled by 'c_allocate' with the product of the fortran indices
do j = lower(1) , upper(1)
do k = lower(2) , upper(2)
x(j,k) = x(j,k) - j * k
end do
end do
if (any (x .ne. 0)) stop 14
deallocate (x)
end subroutine test_CFI_allocate
subroutine test_CFI_establish
! Test CFI_establish.
type(T), pointer :: case2(:) => null()
if (c_establish(case2) .ne. 0) stop 14
if (ubound(case2, 1) .ne. 9) stop 15
if (.not.associated(case2)) stop 16
if (sizeof(case2) .ne. 240) stop 17
if (int (sum (case2%x)) .ne. 55) stop 18
if (int (sum (imag (case2%y))) .ne. 110) stop 19
deallocate (case2)
end subroutine test_CFI_establish
subroutine test_CFI_contiguous (arg)
integer, dimension (2,*) :: arg
character(4), dimension(2) :: chr
! These are contiguous
if (c_contiguous (arg) .ne. 0) stop 20
if (.not.allocated (x)) allocate (x(2, 2))
if (c_contiguous (x) .ne. 0) stop 22
deallocate (x)
if (c_contiguous (chr) .ne. 0) stop 23
! These are not contiguous
if (c_contiguous (der%i) .eq. 0) stop 24
if (c_contiguous (arg(1:1,1:2)) .eq. 0) stop 25
if (c_contiguous (d(4:2:-2, 1:3:2)) .eq. 0) stop 26
if (c_contiguous (chr(:)(2:3)) .eq. 0) stop 27
end subroutine test_CFI_contiguous
subroutine test_CFI_section (arg)
real, dimension (100) :: a
real, dimension (10,*) :: arg
integer, dimension(15) :: lower, strides
integer :: i
! Case (i) from F2018:18.5.5.7.
a = [(real(i), i = 1, 100)]
lower(1) = 10
strides(1) = 5
if (int (sum(a(lower(1)::strides(1))) &
- c_section(1, a, lower, strides)) .ne. 0) stop 28
! Case (ii) from F2018:18.5.5.7.
arg(:,1:10) = reshape ([(real(i), i = 1, 100)], [10,10])
lower(1) = 1
lower(2) = 5
strides(1) = 1
strides(2) = 0
if (int (sum(arg(:,5)) &
- c_section (2, arg, lower, strides)) .ne. 0) stop 29
end subroutine test_CFI_section
subroutine test_CFI_select_part
! Test the example from F2018:18.5.5.8.
! Modify to take rank 2 and sum the section type_t(5, :)%y%im
! Note that sum_z_5 = sum (type_t(5, :)%y%im) is broken on Darwin.
!
type (t), dimension(10, 10) :: type_t
real(kind(type_t%x)) :: v, sum_z_5 = 0.0
complex(kind(type_t%y)) :: z
! Set the array 'type_t'.
do j = 1, 10
do k = 1, 10
v = dble (j * k)
z = cmplx (2 * v, 3 * v)
type_t(j, k) = t (v, z)
if (j .eq. 5) sum_z_5 = sum_z_5 + imag (z)
end do
end do
! Now do the test.
if (int (c_select_part (type_t) - sum_z_5) .ne. 0) stop 28
end subroutine test_CFI_select_part
subroutine test_CFI_setpointer
! Test the example from F2018:18.5.5.9.
integer, dimension(:,:), pointer :: ptr => NULL ()
integer, dimension(2,2), target :: tgt
integer, dimension(2) :: lbounds = [-1, -2]
! The C-function resets the lbounds
ptr(1:, 1:) => tgt
if (c_setpointer (ptr, lbounds) .ne. 0) stop 30
if (any (lbound(ptr) .ne. lbounds)) stop 31
end subroutine test_CFI_setpointer
subroutine test_assumed_size (arg)
integer, dimension(2,*) :: arg
! The C-function checks contiguousness and that extent[1] == -1.
if (c_assumed_size (arg) .ne. 0) stop 32
end subroutine
end
/* Test F2018 18.5: ISO_Fortran_binding.h functions. */
#include <ISO_Fortran_binding.h>
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
/* Test the example in F2018 C.12.9: Processing assumed-shape arrays in C,
modified to use CFI_address instead of pointer arithmetic. */
int address_c(CFI_cdesc_t * a_desc, const int idx[])
{
int *res_addr;
CFI_index_t CFI_idx[1];
CFI_idx[0] = (CFI_index_t)idx[0];
res_addr = CFI_address (a_desc, CFI_idx);
if (res_addr == NULL)
return -1;
return *res_addr;
}
int deallocate_c(CFI_cdesc_t * dd)
{
return CFI_deallocate(dd);
}
int allocate_c(CFI_cdesc_t * da, CFI_index_t lower[], CFI_index_t upper[])
{
return CFI_allocate(da, lower, upper, 0);
}
int establish_c(CFI_cdesc_t * desc, int *rank, int *attr)
{
typedef struct {double x; double _Complex y;} t;
int err;
CFI_index_t idx[1], extent[1];
void *ptr;
extent[0] = 1;
ptr = malloc ((size_t)(extent[0] * sizeof(t)));
err = CFI_establish((CFI_cdesc_t *)desc,
ptr,
(CFI_attribute_t)*attr,
CFI_type_struct,
sizeof(t), (CFI_rank_t)*rank, extent);
free (ptr);
return err;
}
int contiguous_c(CFI_cdesc_t * desc)
{
return CFI_is_contiguous(desc);
}
float section_c(int *std_case, CFI_cdesc_t * source, int *low, int *str)
{
CFI_index_t idx[CFI_MAX_RANK], lower[CFI_MAX_RANK],
strides[CFI_MAX_RANK], upper[CFI_MAX_RANK];
CFI_CDESC_T(1) section;
int ind, size;
float *ret_addr;
float ans = 0.0;
if (*std_case == 1)
{
lower[0] = (CFI_index_t)low[0];
strides[0] = (CFI_index_t)str[0];
ind = CFI_establish((CFI_cdesc_t *)&section, NULL, CFI_attribute_other,
CFI_type_float, 0, 1, NULL);
if (ind) return -1.0;
ind = CFI_section((CFI_cdesc_t *)&section, source, lower, NULL, strides);
if (ind) return (float)ind;
}
return 0.0;
}
int select_part_c (CFI_cdesc_t * source)
{
typedef struct
{
double x;
double _Complex y;
} t;
CFI_CDESC_T(2) component;
CFI_cdesc_t * comp_cdesc = (CFI_cdesc_t *)&component;
CFI_index_t extent[] = {10,10};
CFI_index_t idx[] = {4,0};
int res;
res = CFI_establish(comp_cdesc, NULL, CFI_attribute_other,
CFI_type_double_Complex, sizeof(double _Complex),
2, extent);
if (res)
return res;
res = CFI_select_part(comp_cdesc, source, offsetof(t,y), 0);
return res;
}
int setpointer_c(CFI_cdesc_t * ptr1, CFI_cdesc_t * ptr2, int lbounds[])
{
CFI_index_t lower_bounds[] = {lbounds[0],lbounds[1]};
int ind;
ind = CFI_setpointer(ptr1, ptr2, lower_bounds);
return ind;
}
! { dg-do run }
! { dg-additional-sources ISO_Fortran_binding_2.c }
! { dg-options "-fbounds-check" }
!
! Test F2018 18.5: ISO_Fortran_binding.h function errors.
!
USE, INTRINSIC :: ISO_C_BINDING
TYPE, BIND(C) :: T
REAL(C_DOUBLE) :: X
complex(C_DOUBLE_COMPLEX) :: Y
END TYPE
type :: mytype
integer :: i
integer :: j
end type
INTERFACE
FUNCTION c_address(a, idx) BIND(C, NAME="address_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
INTEGER(C_INT), dimension(1) :: idx
type(*), DIMENSION(..) :: a
END FUNCTION c_address
FUNCTION c_deallocate(a) BIND(C, NAME="deallocate_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
type(*), DIMENSION(..) :: a
END FUNCTION c_deallocate
FUNCTION c_allocate(a, lower, upper) BIND(C, NAME="allocate_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
type(*), DIMENSION(..) :: a
integer(C_INTPTR_T), DIMENSION(15) :: lower, upper
END FUNCTION c_allocate
FUNCTION c_establish(a, rank, attr) BIND(C, NAME="establish_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
import
INTEGER(C_INT) :: err
INTEGER(C_INT) :: rank, attr
type (T), DIMENSION(..), intent(out) :: a
END FUNCTION c_establish
FUNCTION c_contiguous(a) BIND(C, NAME="contiguous_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
type(*), DIMENSION(..) :: a
END FUNCTION c_contiguous
FUNCTION c_section(std_case, a, lower, strides) BIND(C, NAME="section_c") RESULT(ans)
USE, INTRINSIC :: ISO_C_BINDING
real(C_FLOAT) :: ans
INTEGER(C_INT) :: std_case
INTEGER(C_INT), dimension(15) :: lower
INTEGER(C_INT), dimension(15) :: strides
type(*), DIMENSION(..) :: a
END FUNCTION c_section
FUNCTION c_select_part(a) BIND(C, NAME="select_part_c") RESULT(ans)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: ans
type(*), DIMENSION(..) :: a
END FUNCTION c_select_part
FUNCTION c_setpointer(a, b, lbounds) BIND(C, NAME="setpointer_c") RESULT(err)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT) :: err
INTEGER(C_INT), dimension(2) :: lbounds
type(*), DIMENSION(..) :: a, b
END FUNCTION c_setpointer
END INTERFACE
integer(C_INTPTR_T), dimension(15) :: lower, upper
call test_CFI_address
call test_CFI_deallocate
call test_CFI_allocate
call test_CFI_establish
call test_CFI_contiguous
call test_CFI_section
call test_CFI_select_part
call test_CFI_setpointer
contains
subroutine test_CFI_address
integer, dimension(:), allocatable :: a
allocate (a, source = [1,2,3])
if (c_address (a, [2]) .ne. 3) stop 1 ! OK
if (c_address (a, [3]) .ne. -1) stop 2 ! "subscripts[0], is out of bounds"
if (c_address (a, [-1]) .ne. -1) stop 3 ! "subscripts[0], is out of bounds"
deallocate (a)
if (c_address (a, [2]) .ne. -1) stop 4 ! "C Descriptor must not be NULL"
end subroutine test_CFI_address
subroutine test_CFI_deallocate
integer, dimension(:), allocatable :: a
integer, dimension(2,2) :: b
if (c_deallocate (a) .ne. 2) stop 5 ! "Base address is already NULL"
allocate (a(2))
if (c_deallocate (a) .ne. 0) stop 6 ! OK
if (c_deallocate (b) .ne. 7) stop 7 ! "must describe a pointer or allocatable"
end subroutine test_CFI_deallocate
subroutine test_CFI_allocate
integer, dimension(:,:), allocatable :: a
integer, dimension(2,2) :: b
lower(1:2) = [2,2]
upper(1:2) = [10,10]
allocate (a(1,1))
if (c_allocate (a, lower, upper) .ne. 3) stop 8 ! "C descriptor must be NULL"
if (allocated (a)) deallocate (a)
if (c_allocate (a, lower, upper) .ne. 0) stop 9 ! OK
if (c_allocate (b, lower, upper) .ne. 7) STOP 10 ! "must describe a pointer or allocatable"
end subroutine test_CFI_allocate
subroutine test_CFI_establish
type(T), allocatable :: a(:)
INTEGER(C_INT) :: rank
INTEGER(C_INT) :: attr
attr = 0 ! establish a pointer
rank = 16
if (c_establish (a, rank, attr) .ne. 5) stop 11 ! "Rank must be between 0 and 15"
rank = 1
if (c_establish (a, rank, attr) .ne. 0) stop 12 ! OK
if (allocated (a)) deallocate (a)
if (c_establish (a, rank, attr) .ne. 0) Stop 13 ! OK the first time
if (c_establish (a, rank, attr) .ne. 10) Stop 14 ! "its base address must be NULL"
if (allocated (a)) deallocate (a)
attr = 1 ! establish an allocatable
if (c_establish (a, rank, attr) .ne. 7) Stop 15 ! "is for a nonallocatable entity"
end subroutine test_CFI_establish
subroutine test_CFI_contiguous
integer, allocatable :: a
if (c_contiguous (a) .ne. 2) stop 16 ! "Descriptor is already NULL"
allocate (a)
if (c_contiguous (a) .ne. 5) stop 17 ! "must describe an array"
end subroutine test_CFI_contiguous
subroutine test_CFI_section
real, allocatable, dimension (:) :: a
integer, dimension(15) :: lower, strides
integer :: i
real :: b
lower(1) = 10
strides(1) = 5
if (int (c_section (1, a, lower, strides)) .ne. 2) &
stop 18 ! "Base address of source must not be NULL"
allocate (a(100))
if (int (c_section (1, a, lower, strides)) .ne. 0) &
stop 19 ! OK
if (int (c_section (1, b, lower, strides)) .ne. 5) &
stop 20 ! "Source must describe an array"
strides(1) = 0
if (int (c_section (1, a, lower, strides)) .ne. 5) &
stop 21 ! "Rank of result must be equal to the rank of source"
strides(1) = 5
lower(1) = -1
if (int (c_section (1, a, lower, strides)) .ne. 12) &
stop 22 ! "Lower bounds must be within the bounds of the fortran array"
lower(1) = 100
if (int (c_section (1, a, lower, strides)) .ne. 12) &
stop 23 ! "Lower bounds must be within the bounds of the fortran array"
end subroutine test_CFI_section
subroutine test_CFI_select_part
type(t), allocatable, dimension(:) :: a
type(t) :: src
allocate (a(1), source = src)
if (c_select_part (a) .ne. 5) stop 24 ! "Source and result must have the same rank"
deallocate (a)
if (c_select_part (a) .ne. 2) stop 25 ! "source must not be NULL"
end subroutine test_CFI_select_part
subroutine test_CFI_setpointer
integer, dimension(2,2), target :: tgt1
integer, dimension(:,:), pointer :: src
type (t), dimension(2), target :: tgt2
type (t), dimension(:), pointer :: res
type (t), dimension(2, 2), target, save :: tgt3
type (t), dimension(:, :), pointer :: src1
integer, dimension(2) :: lbounds = [-1, -2]
src => tgt1
res => tgt2
if (c_setpointer (res, src, lbounds) .ne. 4) stop 26 ! "Element lengths"
src1 => tgt3
if (c_setpointer (res, src1, lbounds) .ne. 5) stop 27 ! "Ranks of result"
end subroutine test_CFI_setpointer
end
...@@ -20,4 +20,4 @@ end ...@@ -20,4 +20,4 @@ end
! { dg-final { scan-assembler-times "myBindC,%r2" 1 { target { hppa*-*-* } } } } ! { dg-final { scan-assembler-times "myBindC,%r2" 1 { target { hppa*-*-* } } } }
! { dg-final { scan-assembler-times "call\tmyBindC" 1 { target { *-*-cygwin* } } } } ! { dg-final { scan-assembler-times "call\tmyBindC" 1 { target { *-*-cygwin* } } } }
! { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,myBindC" 1 { target { s390*-*-* } } } } ! { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,myBindC" 1 { target { s390*-*-* } } } }
! { dg-final { scan-tree-dump-times "test \\\(&parm\\." 1 "original" } } ! { dg-final { scan-tree-dump-times "cfi_desc_to_gfc_desc \\\(&parm\\." 1 "original" } }
2019-01-12 Paul Thomas <pault@gcc.gnu.org>
* ISO_Fortran_binding.h : New file.
* Makefile.am : Include ISO_Fortran_binding.c in the list of
files to compile.
* Makefile.in : Regenerated.
* gfortran.map : Add _gfortran_cfi_desc_to_gfc_desc,
_gfortran_gfc_desc_to_cfi_desc and the CFI API functions.
* runtime/ISO_Fortran_binding.c : New file containing the new
functions added to the map.
2019-01-12 Jakub Jelinek <jakub@redhat.com> 2019-01-12 Jakub Jelinek <jakub@redhat.com>
PR libfortran/88807 PR libfortran/88807
......
/* Declarations for ISO Fortran binding.
Copyright (C) 2018 Free Software Foundation, Inc.
Contributed by Daniel Celis Garza <celisdanieljr@gmail.com>
This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
Libgfortran is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef ISO_FORTRAN_BINDING_H
#define ISO_FORTRAN_BINDING_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h> /* Standard ptrdiff_t tand size_t. */
#include <stdint.h> /* Integer types. */
/* Constants, defined as macros. */
#define CFI_VERSION 1
#define CFI_MAX_RANK 15
/* Attributes. */
#define CFI_attribute_pointer 0
#define CFI_attribute_allocatable 1
#define CFI_attribute_other 2
/* Error codes.
CFI_INVALID_STRIDE should be defined in the standard because they are useful to the implementation of the functions.
*/
#define CFI_SUCCESS 0
#define CFI_FAILURE 1
#define CFI_ERROR_BASE_ADDR_NULL 2
#define CFI_ERROR_BASE_ADDR_NOT_NULL 3
#define CFI_INVALID_ELEM_LEN 4
#define CFI_INVALID_RANK 5
#define CFI_INVALID_TYPE 6
#define CFI_INVALID_ATTRIBUTE 7
#define CFI_INVALID_EXTENT 8
#define CFI_INVALID_STRIDE 9
#define CFI_INVALID_DESCRIPTOR 10
#define CFI_ERROR_MEM_ALLOCATION 11
#define CFI_ERROR_OUT_OF_BOUNDS 12
/* CFI type definitions. */
typedef ptrdiff_t CFI_index_t;
typedef int8_t CFI_rank_t;
typedef int8_t CFI_attribute_t;
typedef int16_t CFI_type_t;
/* CFI_dim_t. */
typedef struct CFI_dim_t
{
CFI_index_t lower_bound;
CFI_index_t extent;
CFI_index_t sm;
}
CFI_dim_t;
/* CFI_cdesc_t, C descriptors are cast to this structure as follows:
CFI_CDESC_T(CFI_MAX_RANK) foo;
CFI_cdesc_t * bar = (CFI_cdesc_t *) &foo;
*/
typedef struct CFI_cdesc_t
{
void *base_addr;
size_t elem_len;
int version;
CFI_rank_t rank;
CFI_attribute_t attribute;
CFI_type_t type;
CFI_dim_t dim[];
}
CFI_cdesc_t;
/* CFI_CDESC_T with an explicit type. */
#define CFI_CDESC_TYPE_T(r, base_type) \
struct { \
base_type *base_addr; \
size_t elem_len; \
int version; \
CFI_rank_t rank; \
CFI_attribute_t attribute; \
CFI_type_t type; \
CFI_dim_t dim[r]; \
}
#define CFI_CDESC_T(r) CFI_CDESC_TYPE_T (r, void)
/* CFI function declarations. */
extern void *CFI_address (const CFI_cdesc_t *, const CFI_index_t []);
extern int CFI_allocate (CFI_cdesc_t *, const CFI_index_t [], const CFI_index_t [],
size_t);
extern int CFI_deallocate (CFI_cdesc_t *);
extern int CFI_establish (CFI_cdesc_t *, void *, CFI_attribute_t, CFI_type_t, size_t,
CFI_rank_t, const CFI_index_t []);
extern int CFI_is_contiguous (const CFI_cdesc_t *);
extern int CFI_section (CFI_cdesc_t *, const CFI_cdesc_t *, const CFI_index_t [],
const CFI_index_t [], const CFI_index_t []);
extern int CFI_select_part (CFI_cdesc_t *, const CFI_cdesc_t *, size_t, size_t);
extern int CFI_setpointer (CFI_cdesc_t *, CFI_cdesc_t *, const CFI_index_t []);
/* Types and kind numbers. Allows bitwise and to reveal the intrinsic type of a kind type. It also allows us to find the kind parameter by inverting the bit-shift equation.
CFI_type_kind_shift = 8
CFI_intrinsic_type = 0 0 0 0 0 0 0 0 0 0 1 0
CFI_type_kind = 0 0 0 0 0 0 0 0 1 0 0 0
CFI_type_example = CFI_intrinsic_type + (CFI_type_kind << CFI_type_kind_shift)
Defining the CFI_type_example.
CFI_type_kind = 0 0 0 0 0 0 0 0 1 0 0 0 << CFI_type_kind_shift
-------------------------
1 0 0 0 0 0 0 0 0 0 0 0 +
CFI_intrinsic_type = 0 0 0 0 0 0 0 0 0 0 1 0
-------------------------
CFI_type_example = 1 0 0 0 0 0 0 0 0 0 1 0
Finding the intrinsic type with the logical mask.
CFI_type_example = 1 0 0 0 0 0 0 0 0 0 1 0 &
CFI_type_mask = 0 0 0 0 1 1 1 1 1 1 1 1
-------------------------
CFI_intrinsic_type = 0 0 0 0 0 0 0 0 0 0 1 0
Using the intrinsic type and kind shift to find the kind value of the type.
CFI_type_kind = (CFI_type_example - CFI_intrinsic_type) >> CFI_type_kind_shift
CFI_type_example = 1 0 0 0 0 0 0 0 0 0 1 0 -
CFI_intrinsic_type = 0 0 0 0 0 0 0 0 0 0 1 0
-------------------------
1 0 0 0 0 0 0 0 0 0 0 0 >> CFI_type_kind_shift
-------------------------
CFI_type_kind = 0 0 0 0 0 0 0 0 1 0 0 0
*/
#define CFI_type_mask 0xFF
#define CFI_type_kind_shift 8
/* Intrinsic types. Their kind number defines their storage size. */
#define CFI_type_Integer 1
#define CFI_type_Logical 2
#define CFI_type_Real 3
#define CFI_type_Complex 4
#define CFI_type_Character 5
/* Types with no kind. */
#define CFI_type_struct 6
#define CFI_type_cptr 7
#define CFI_type_cfunptr 8
#define CFI_type_other -1
/* Types with kind parameter.
The kind parameter represents the type's byte size. The exception is kind = 10, which has byte size of 64 but 80 bit precision. Complex variables are double the byte size of their real counterparts. The ucs4_char matches wchar_t if sizeof (wchar_t) == 4.
*/
#define CFI_type_char (CFI_type_Character + (1 << CFI_type_kind_shift))
#define CFI_type_ucs4_char (CFI_type_Character + (4 << CFI_type_kind_shift))
/* C-Fortran Interoperability types. */
#define CFI_type_signed_char (CFI_type_Integer + (1 << CFI_type_kind_shift))
#define CFI_type_short (CFI_type_Integer + (2 << CFI_type_kind_shift))
#define CFI_type_int (CFI_type_Integer + (4 << CFI_type_kind_shift))
#define CFI_type_long (CFI_type_Integer + (8 << CFI_type_kind_shift))
#define CFI_type_long_long (CFI_type_Integer + (8 << CFI_type_kind_shift))
#define CFI_type_size_t (CFI_type_Integer + (8 << CFI_type_kind_shift))
#define CFI_type_int8_t (CFI_type_Integer + (1 << CFI_type_kind_shift))
#define CFI_type_int16_t (CFI_type_Integer + (2 << CFI_type_kind_shift))
#define CFI_type_int32_t (CFI_type_Integer + (4 << CFI_type_kind_shift))
#define CFI_type_int64_t (CFI_type_Integer + (8 << CFI_type_kind_shift))
#define CFI_type_int_least8_t (CFI_type_Integer + (1 << CFI_type_kind_shift))
#define CFI_type_int_least16_t (CFI_type_Integer + (2 << CFI_type_kind_shift))
#define CFI_type_int_least32_t (CFI_type_Integer + (4 << CFI_type_kind_shift))
#define CFI_type_int_least64_t (CFI_type_Integer + (8 << CFI_type_kind_shift))
#define CFI_type_int_fast8_t (CFI_type_Integer + (1 << CFI_type_kind_shift))
#define CFI_type_int_fast16_t (CFI_type_Integer + (2 << CFI_type_kind_shift))
#define CFI_type_int_fast32_t (CFI_type_Integer + (4 << CFI_type_kind_shift))
#define CFI_type_int_fast64_t (CFI_type_Integer + (8 << CFI_type_kind_shift))
#define CFI_type_intmax_t (CFI_type_Integer + (8 << CFI_type_kind_shift))
#define CFI_type_intptr_t (CFI_type_Integer + (8 << CFI_type_kind_shift))
#define CFI_type_ptrdiff_t (CFI_type_Integer + (8 << CFI_type_kind_shift))
#define CFI_type_int128_t (CFI_type_Integer + (16 << CFI_type_kind_shift))
#define CFI_type_int_least128_t (CFI_type_Integer + (16 << CFI_type_kind_shift))
#define CFI_type_int_fast128_t (CFI_type_Integer + (16 << CFI_type_kind_shift))
#define CFI_type_Bool (CFI_type_Logical + (1 << CFI_type_kind_shift))
#define CFI_type_float (CFI_type_Real + (4 << CFI_type_kind_shift))
#define CFI_type_double (CFI_type_Real + (8 << CFI_type_kind_shift))
#define CFI_type_long_double (CFI_type_Real + (10 << CFI_type_kind_shift))
#define CFI_type_float128 (CFI_type_Real + (16 << CFI_type_kind_shift))
#define CFI_type_float_Complex (CFI_type_Complex + (4 << CFI_type_kind_shift))
#define CFI_type_double_Complex (CFI_type_Complex + (8 << CFI_type_kind_shift))
#define CFI_type_long_double_Complex (CFI_type_Complex + (10 << CFI_type_kind_shift))
#define CFI_type_float128_Complex (CFI_type_Complex + (16 << CFI_type_kind_shift))
#ifdef __cplusplus
}
#endif
#endif /* ISO_FORTRAN_BINDING_H */
...@@ -30,6 +30,9 @@ version_arg = ...@@ -30,6 +30,9 @@ version_arg =
version_dep = version_dep =
endif endif
gfor_c_HEADERS = $(srcdir)/ISO_Fortran_binding.h
gfor_cdir = $(libdir)/gcc/$(target_alias)/$(gcc_version)$(MULTISUBDIR)/include
LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) \ LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) \
$(lt_host_flags) $(lt_host_flags)
...@@ -783,6 +786,9 @@ $(srcdir)/generated/spread_c8.c \ ...@@ -783,6 +786,9 @@ $(srcdir)/generated/spread_c8.c \
$(srcdir)/generated/spread_c10.c \ $(srcdir)/generated/spread_c10.c \
$(srcdir)/generated/spread_c16.c $(srcdir)/generated/spread_c16.c
i_isobinding_c = \
$(srcdir)/runtime/ISO_Fortran_binding.c
m4_files= m4/iparm.m4 m4/ifunction.m4 m4/iforeach.m4 m4/all.m4 \ m4_files= m4/iparm.m4 m4/ifunction.m4 m4/iforeach.m4 m4/all.m4 \
m4/any.m4 m4/count.m4 m4/maxloc0.m4 m4/maxloc1.m4 m4/maxval.m4 \ m4/any.m4 m4/count.m4 m4/maxloc0.m4 m4/maxloc1.m4 m4/maxval.m4 \
m4/minloc0.m4 m4/minloc1.m4 m4/minval.m4 m4/product.m4 m4/sum.m4 \ m4/minloc0.m4 m4/minloc1.m4 m4/minval.m4 m4/product.m4 m4/sum.m4 \
...@@ -810,7 +816,7 @@ gfor_built_src= $(i_all_c) $(i_any_c) $(i_count_c) $(i_maxloc0_c) \ ...@@ -810,7 +816,7 @@ gfor_built_src= $(i_all_c) $(i_any_c) $(i_count_c) $(i_maxloc0_c) \
$(i_minloc1s_c) $(i_maxloc2s_c) $(i_minloc2s_c) $(i_maxvals_c) \ $(i_minloc1s_c) $(i_maxloc2s_c) $(i_minloc2s_c) $(i_maxvals_c) \
$(i_maxval0s_c) $(i_minval0s_c) $(i_maxval1s_c) $(i_minval1s_c) \ $(i_maxval0s_c) $(i_minval0s_c) $(i_maxval1s_c) $(i_minval1s_c) \
$(i_findloc0_c) $(i_findloc0s_c) $(i_findloc1_c) $(i_findloc1s_c) \ $(i_findloc0_c) $(i_findloc0s_c) $(i_findloc1_c) $(i_findloc1s_c) \
$(i_findloc2s_c) $(i_findloc2s_c) $(i_isobinding_c)
# Machine generated specifics # Machine generated specifics
gfor_built_specific_src= \ gfor_built_specific_src= \
......
...@@ -780,7 +780,6 @@ infodir ...@@ -780,7 +780,6 @@ infodir
docdir docdir
oldincludedir oldincludedir
includedir includedir
runstatedir
localstatedir localstatedir
sharedstatedir sharedstatedir
sysconfdir sysconfdir
...@@ -871,7 +870,6 @@ datadir='${datarootdir}' ...@@ -871,7 +870,6 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc' sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com' sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var' localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include' includedir='${prefix}/include'
oldincludedir='/usr/include' oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
...@@ -1124,15 +1122,6 @@ do ...@@ -1124,15 +1122,6 @@ do
| -silent | --silent | --silen | --sile | --sil) | -silent | --silent | --silen | --sile | --sil)
silent=yes ;; silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;; ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
...@@ -1270,7 +1259,7 @@ fi ...@@ -1270,7 +1259,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \ datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir runstatedir libdir localedir mandir
do do
eval ac_val=\$$ac_var eval ac_val=\$$ac_var
# Remove trailing slashes. # Remove trailing slashes.
...@@ -1423,7 +1412,6 @@ Fine tuning of the installation directories: ...@@ -1423,7 +1412,6 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var] --localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib] --libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include] --includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include] --oldincludedir=DIR C header files for non-gcc [/usr/include]
...@@ -12696,7 +12684,7 @@ else ...@@ -12696,7 +12684,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF cat > conftest.$ac_ext <<_LT_EOF
#line 12699 "configure" #line 12687 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
...@@ -12802,7 +12790,7 @@ else ...@@ -12802,7 +12790,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF cat > conftest.$ac_ext <<_LT_EOF
#line 12805 "configure" #line 12793 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
...@@ -16051,7 +16039,7 @@ else ...@@ -16051,7 +16039,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807, We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */ incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1) && LARGE_OFF_T % 2147483647 == 1)
? 1 : -1]; ? 1 : -1];
...@@ -16097,7 +16085,7 @@ else ...@@ -16097,7 +16085,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807, We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */ incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1) && LARGE_OFF_T % 2147483647 == 1)
? 1 : -1]; ? 1 : -1];
...@@ -16121,7 +16109,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ...@@ -16121,7 +16109,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807, We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */ incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1) && LARGE_OFF_T % 2147483647 == 1)
? 1 : -1]; ? 1 : -1];
...@@ -16166,7 +16154,7 @@ else ...@@ -16166,7 +16154,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807, We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */ incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1) && LARGE_OFF_T % 2147483647 == 1)
? 1 : -1]; ? 1 : -1];
...@@ -16190,7 +16178,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ...@@ -16190,7 +16178,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807, We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */ incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1) && LARGE_OFF_T % 2147483647 == 1)
? 1 : -1]; ? 1 : -1];
......
...@@ -1486,6 +1486,16 @@ GFORTRAN_C99_8 { ...@@ -1486,6 +1486,16 @@ GFORTRAN_C99_8 {
GFORTRAN_9 { GFORTRAN_9 {
global: global:
CFI_address;
CFI_allocate;
CFI_deallocate;
CFI_establish;
CFI_is_contiguous;
CFI_section;
CFI_select_part;
CFI_setpointer;
_gfortran_gfc_desc_to_cfi_desc;
_gfortran_cfi_desc_to_gfc_desc;
_gfortran_findloc0_c16; _gfortran_findloc0_c16;
_gfortran_findloc0_c4; _gfortran_findloc0_c4;
_gfortran_findloc0_c8; _gfortran_findloc0_c8;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment