blob: 7689eee13024877818c175bd210b7a2fc5417a0f [file] [log] [blame]
/*===-- include/flang/ISO_Fortran_binding.h -----------------------*- C++ -*-===
*
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
* ===-----------------------------------------------------------------------===
*/
#ifndef CFI_ISO_FORTRAN_BINDING_H_
#define CFI_ISO_FORTRAN_BINDING_H_
#include <stddef.h>
/* Standard interface to Fortran from C and C++.
* These interfaces are named in subclause 18.5 of the Fortran 2018
* standard, with most of the actual details being left to the
* implementation.
*/
#ifdef __cplusplus
namespace Fortran {
namespace ISO {
inline namespace Fortran_2018 {
#endif
/* 18.5.4 */
#define CFI_VERSION 20180515
#define CFI_MAX_RANK 15
typedef unsigned char CFI_rank_t;
/* This type is probably larger than a default Fortran INTEGER
* and should be used for all array indexing and loop bound calculations.
*/
typedef ptrdiff_t CFI_index_t;
typedef unsigned char CFI_attribute_t;
#define CFI_attribute_pointer 1
#define CFI_attribute_allocatable 2
#define CFI_attribute_other 0 /* neither pointer nor allocatable */
typedef signed char CFI_type_t;
/* These codes are required to be macros (i.e., #ifdef will work).
* They are not required to be distinct, but neither are they required
* to have had their synonyms combined.
*/
#define CFI_type_signed_char 1
#define CFI_type_short 2
#define CFI_type_int 3
#define CFI_type_long 4
#define CFI_type_long_long 5
#define CFI_type_size_t 6
#define CFI_type_int8_t 7
#define CFI_type_int16_t 8
#define CFI_type_int32_t 9
#define CFI_type_int64_t 10
#define CFI_type_int128_t 11 /* extension */
#define CFI_type_int_least8_t 12
#define CFI_type_int_least16_t 13
#define CFI_type_int_least32_t 14
#define CFI_type_int_least64_t 15
#define CFI_type_int_least128_t 16
#define CFI_type_int_fast8_t 17
#define CFI_type_int_fast16_t 18
#define CFI_type_int_fast32_t 19
#define CFI_type_int_fast64_t 20
#define CFI_type_int_fast128_t 21
#define CFI_type_intmax_t 22
#define CFI_type_intptr_t 23
#define CFI_type_ptrdiff_t 24
#define CFI_type_float 25
#define CFI_type_double 26
#define CFI_type_long_double 27
#define CFI_type_float_Complex 28
#define CFI_type_double_Complex 29
#define CFI_type_long_double_Complex 30
#define CFI_type_Bool 31
#define CFI_type_char 32
#define CFI_type_cptr 33
#define CFI_type_struct 34
#define CFI_type_char16_t 35 /* extension: char16_t */
#define CFI_type_char32_t 36 /* extension: char32_t */
#define CFI_TYPE_LAST CFI_type_char32_t
#define CFI_type_other (-1) // must be negative
/* Error code macros - skip some of the small values to avoid conflicts with
* other status codes mandated by the standard, e.g. those returned by
* GET_ENVIRONMENT_VARIABLE (16.9.84) */
#define CFI_SUCCESS 0 /* must be zero */
#define CFI_ERROR_BASE_ADDR_NULL 11
#define CFI_ERROR_BASE_ADDR_NOT_NULL 12
#define CFI_INVALID_ELEM_LEN 13
#define CFI_INVALID_RANK 14
#define CFI_INVALID_TYPE 15
#define CFI_INVALID_ATTRIBUTE 16
#define CFI_INVALID_EXTENT 17
#define CFI_INVALID_DESCRIPTOR 18
#define CFI_ERROR_MEM_ALLOCATION 19
#define CFI_ERROR_OUT_OF_BOUNDS 20
/* 18.5.2 per-dimension information */
typedef struct CFI_dim_t {
CFI_index_t lower_bound;
CFI_index_t extent; /* == -1 for assumed size */
CFI_index_t sm; /* memory stride in bytes */
} CFI_dim_t;
#ifdef __cplusplus
namespace cfi_internal {
// C++ does not support flexible array.
// The below structure emulates a flexible array. This structure does not take
// care of getting the memory storage. Note that it already contains one element
// because a struct cannot be empty.
template <typename T> struct FlexibleArray : T {
T &operator[](int index) { return *(this + index); }
const T &operator[](int index) const { return *(this + index); }
operator T *() { return this; }
operator const T *() const { return this; }
};
} // namespace cfi_internal
#endif
/* 18.5.3 generic data descriptor */
typedef struct CFI_cdesc_t {
/* These three members must appear first, in exactly this order. */
void *base_addr;
size_t elem_len; /* element size in bytes */
int version; /* == CFI_VERSION */
CFI_rank_t rank; /* [0 .. CFI_MAX_RANK] */
CFI_type_t type;
CFI_attribute_t attribute;
unsigned char f18Addendum;
#ifdef __cplusplus
cfi_internal::FlexibleArray<CFI_dim_t> dim;
#else
CFI_dim_t dim[]; /* must appear last */
#endif
} CFI_cdesc_t;
/* 18.5.4 */
#ifdef __cplusplus
// The struct below take care of getting the memory storage for C++ CFI_cdesc_t
// that contain an emulated flexible array.
namespace cfi_internal {
template <int r> struct CdescStorage : public CFI_cdesc_t {
static_assert((r > 1 && r <= CFI_MAX_RANK), "CFI_INVALID_RANK");
CFI_dim_t dim[r - 1];
};
template <> struct CdescStorage<1> : public CFI_cdesc_t {};
template <> struct CdescStorage<0> : public CFI_cdesc_t {};
} // namespace cfi_internal
#define CFI_CDESC_T(rank) cfi_internal::CdescStorage<rank>
#else
#define CFI_CDESC_T(rank) \
struct { \
CFI_cdesc_t cdesc; /* must be first */ \
CFI_dim_t dim[rank]; \
}
#endif
/* 18.5.5 procedural interfaces*/
#ifdef __cplusplus
extern "C" {
#endif
void *CFI_address(const CFI_cdesc_t *, const CFI_index_t subscripts[]);
int CFI_allocate(CFI_cdesc_t *, const CFI_index_t lower_bounds[],
const CFI_index_t upper_bounds[], size_t elem_len);
int CFI_deallocate(CFI_cdesc_t *);
int CFI_establish(CFI_cdesc_t *, void *base_addr, CFI_attribute_t, CFI_type_t,
size_t elem_len, CFI_rank_t, const CFI_index_t extents[]);
int CFI_is_contiguous(const CFI_cdesc_t *);
int CFI_section(CFI_cdesc_t *, const CFI_cdesc_t *source,
const CFI_index_t lower_bounds[], const CFI_index_t upper_bounds[],
const CFI_index_t strides[]);
int CFI_select_part(CFI_cdesc_t *, const CFI_cdesc_t *source,
size_t displacement, size_t elem_len);
int CFI_setpointer(
CFI_cdesc_t *, const CFI_cdesc_t *source, const CFI_index_t lower_bounds[]);
#ifdef __cplusplus
} // extern "C"
} // inline namespace Fortran_2018
}
}
#endif
#endif /* CFI_ISO_FORTRAN_BINDING_H_ */