J3/04-371r1 Date: 12 August 2004 To: J3 From: Bill Long Subject: Interoperability of pointers, allocatables, and assumed-shape arrays Number: Title: Interoperability of pointers, allocatables, and assumed-shape arrays Submitted By: J3 Status: For consideration Basic Functionality: Extensions to C Interop that allow arguments that are pointers, allocatables, and assumed-shape arrays to be interoperable. Rationale: C interoperability provides a mechanism to share array data between Fortran and C. However, even with C interop, it is still necessary for users to implement a translation layer between C and Fortran assumed-shape array data structures. Under some circumstances, it may even be necessary to make temporary copies of array data in this translation layer. In the translation layer, for each array-valued parameter in a BIND(C) procedure, a user needs to pass the address of the array as well as each value of the array shape as integer procedure parameters. For BIND(C) procedures taking many array arguments, the resulting argument list can be exceptionally long. In addition, data marshaling in the translation layer can be a performance hit. Estimated Impact: Small impact for the standard and probably small to moderate impact for the processors. Detailed Specification: The processor will be required to supply, for each companion C processor, a C header file and C functions (or macros) implementing the C prototypes shown below. In C, descriptors for assumed-shape, allocatable, and Fortran pointer objects are represented by opaque types. The C functions specified by these prototypes allow C programmers to create and destroy memory for descriptors, functions to get and set parameters in a descriptor, and functions to allocate and deallocate the memory described by the descriptors. Separate opaque types are defined for the assumed-shape, allocatable, and pointer cases. Type and function names containing _ASSUMED_ are used with assumed-shape arguments, names containing _ALLOC_ are used with allocatable arguments, and names containing _POINTER_ are used with pointer arguments. The rank may be specified as 0 for allocatable and pointer descriptors, in which case the corresponding Fortran object shall be a scalar. If the base_addr parameter in the FDesc_Alloc_Create or FDesc_Alloc_Reset functions is NULL, the resulting descriptor represents an unallocated object. If the base_addr parameter in the FDesc_Pointer_Create or FDesc_Pointer_Reset is NULL, the resulting descriptor represents an unassociated pointer. A C function calling a Fortran procedure with the BIND(C) attribute will pass a pointer to an array descriptor as the actual argument corresponding to an assumed-shape, allocatable, or pointer dummy argument. Depending on the details of the processor's Fortran descriptors, the procedure may be required to merge additional information into the descriptor based on the declaration of the dummy argument, or to create a local representation based on the information in the descriptor. If the dummy argument is deallocated, allocated, or has its pointer association status changed in the procedure, the descriptor shall be modified to reflect the new state of the argument. A C function that is called from a Fortran procedure will be passed a pointer to a descriptor of the type appropriate for the corresponding dummy argument in the interface for the called function. Such an argument must have interoperable type and type parameters. /** * FDesc.h - name of include file declaring descriptor typedefs * and prototypes */ /** * * An opaque type for the size of extents. * * F_extent_t * */ /** * Opaque descriptor types. * * FDesc_Alloc_t * FDesc_Pointer_t * FDesc_Assumed_t * */ /** * Allocation, deallocation and reset routines for descriptors */ /** * Create a descriptor and initialize its data. * * Memory for the descriptor must be freed by a subsequent call to * FDesc_Alloc_Destroy, FDesc_Pointer_Destroy, or FDesc_Assumed_Destroy. * * @param fdesc contains address of descriptor on return. * @param base_addr the base address of the array or scalar object. * @param elem_size the size of an array element or scalar object (in bytes). * @param rank the rank of the array; 0 if object is scalar. * @param shape array[rank] containing the array shape. * @param stride array[rank] containing the distance between successive * array elements for each dimension (in bytes). * @return 0 if successful (nonzero on error). */ int FDesc_Alloc_Create(FDesc_Alloc_t* fdesc, void* base_addr, size_t elem_size, int rank, F_extent_t shape[], size_t stride[] ); int FDesc_Pointer_Create(FDesc_Pointer_t* fdesc, void* base_addr, size_t elem_size, int rank, F_extent_t shape[], size_t stride[] ); int FDesc_Assumed_Create(FDesc_Assumed_t* fdesc, void* base_addr, size_t elem_size, int rank, F_extent_t shape[] ); /** * Set the elements of a descriptor. * * @param fdesc address of descriptor. * @param base_addr the base address of the array or scalar object. * @param shape array[rank] containing the array shape (in elements). * If base_addr is NULL, the contents of shape are ignored * and the descriptor shape values are set to 0. * @param stride array[rank] containing the distance between successive * array elements for each dimension (in bytes). * If base_addr is NULL, the contents of stride are ignored * and the descriptor stride values are set to 0. * @return 0 if successful (nonzero on error). */ int FDesc_Alloc_Reset(FDesc_Alloc_t* fdesc, void* base_addr, F_extent_t shape[], size_t stride[] ); int FDesc_Pointer_Reset(FDesc_Pointer_t* fdesc, void* base_addr, F_extent_t shape[], size_t stride[] ); /** * Frees memory for a descriptor. * * @param fdesc address of a descriptor. * @return 0 if successful (nonzero on error). */ int FDesc_Alloc_Destroy(FDesc_Alloc_t* fdesc); int FDesc_Pointer_Destroy(FDesc_Pointer_t* fdesc); int FDesc_Assumed_Destroy(FDesc_Assumed_t* fdesc); /** * Routines to allocate and deallocate array or scalar object memory */ /** * Returns a value appropriate for use as base_addr in Create and * and Reset routines. Syntax like that of malloc(). * * @param size amount of memory to allocate, in bytes. * @return pointer to allocated memory, or NULL if the * memory allocation fails. */ void* FDesc_Alloc_Allocate(size_t size); void* FDesc_Pointer_Allocate(size_t size); void* FDesc_Assumed_Allocate(size_t size); /** * Frees memory previously allocated with FDesc_Alloc_Allocate, * FDesc_Pointer_Allocate, or FDesc_Assumed_Allocate. * FDesc_Alloc_Deallocate and FDesc_Pointer_Deallocate may be * used to deallocate memory previously allocated by a Fortran * procedure. Syntax like that of free(). * * @param base_addr pointer a block of previously allocated memory. * @return 0 is successful (nonzero on error). */ int FDesc_Alloc_Deallocate(void* base_addr); int FDesc_Pointer_Deallocate(void* base_addr); int FDesc_Assumed_Deallocate(void* base_addr); /** * Accessors */ /** Returns true if the pointer is associated (false otherwise). */ _Bool FDesc_Associated(FDesc_Pointer_t fdesc); /** Returns true if the object is allocated (false otherwise). */ _Bool FDesc_Allocated(FDesc_Alloc_t fdesc); /** Returns the rank of the array described by a descriptor */ int FDesc_Alloc_Rank(FDesc_Alloc_t fdesc); int FDesc_Pointer_Rank(FDesc_Pointer_t fdesc); int FDesc_Assumed_Rank(FDesc_Assumed_t fdesc); /** * Return the address, shape, and stride information in a descriptor. * * @param fdesc the descriptor. * @param base_addr contains the address of the array or scalar object on return. * @param shape array[rank] containing the array shape on return * (in elements). If the rank is 0, shape is not returned. * @param stride array[rank] containing the distance between successive * array elements for each dimension (in bytes) on return. * If rank is 0, stride is not returned. * @return 0 if successful (nonzero on error). */ int FDesc_Alloc_Get(FDesc_Alloc_t fdesc, void** base_addr, F_extent_t shape[], size_t stride[] ); int FDesc_Pointer_Get(FDesc_Pointer_t fdesc, void** base_addr, F_extent_t shape[], size_t stride[] ); int FDesc_Assumed_Get(FDesc_Assumed_t fdesc, void** base_addr, F_extent_t shape[], size_t stride[] ); /** End of FDesc.h */ History: Submitted as paper 04-371r1 at meeting 169.