xref: /llvm-project/flang/include/flang/ISO_Fortran_binding.h (revision fc97d2e68b03bc2979395e84b645e5b3ba35aecd)
1 /*===-- include/flang/ISO_Fortran_binding.h -----------------------*- C++ -*-===
2  *
3  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  * See https://llvm.org/LICENSE.txt for license information.
5  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  *
7  * ===-----------------------------------------------------------------------===
8  */
9 
10 #ifndef CFI_ISO_FORTRAN_BINDING_H_
11 #define CFI_ISO_FORTRAN_BINDING_H_
12 
13 /* When this header is included into the compiler and runtime implementations,
14  * it does so by means of a wrapper header that establishes namespaces and
15  * a macro for extra function attributes (RT_API_ATTRS).
16  */
17 #ifndef FORTRAN_ISO_FORTRAN_BINDING_WRAPPER_H_
18 #include <stddef.h>
19 #define FORTRAN_ISO_NAMESPACE_
20 #endif
21 
22 /* Standard interface to Fortran from C and C++.
23  * These interfaces are named in subclause 18.5 of the Fortran 2018
24  * standard, with most of the actual details being left to the
25  * implementation.
26  */
27 
28 #ifndef RT_API_ATTRS
29 #define RT_API_ATTRS
30 #endif
31 
32 /* 18.5.4 */
33 #define CFI_VERSION 20240719
34 
35 #if !defined CFI_MAX_RANK || !defined __OVERRIDE_CFI_MAX_RANK
36 #define CFI_MAX_RANK 15
37 #endif
38 typedef unsigned char CFI_rank_t;
39 
40 /* This type is probably larger than a default Fortran INTEGER
41  * and should be used for all array indexing and loop bound calculations.
42  */
43 typedef ptrdiff_t CFI_index_t;
44 
45 typedef unsigned char CFI_attribute_t;
46 #define CFI_attribute_pointer 1
47 #define CFI_attribute_allocatable 2
48 #define CFI_attribute_other 0 /* neither pointer nor allocatable */
49 
50 typedef signed char CFI_type_t;
51 /* These codes are required to be macros (i.e., #ifdef will work).
52  * They are not required to be distinct, but neither are they required
53  * to have had their synonyms combined.
54  */
55 #define CFI_type_signed_char 1
56 #define CFI_type_short 2
57 #define CFI_type_int 3
58 #define CFI_type_long 4
59 #define CFI_type_long_long 5
60 #define CFI_type_size_t 6
61 #define CFI_type_int8_t 7
62 #define CFI_type_int16_t 8
63 #define CFI_type_int32_t 9
64 #define CFI_type_int64_t 10
65 #define CFI_type_int128_t 11 /* extension kind=16 */
66 #define CFI_type_int_least8_t 12
67 #define CFI_type_int_least16_t 13
68 #define CFI_type_int_least32_t 14
69 #define CFI_type_int_least64_t 15
70 #define CFI_type_int_least128_t 16 /* extension */
71 #define CFI_type_int_fast8_t 17
72 #define CFI_type_int_fast16_t 18
73 #define CFI_type_int_fast32_t 19
74 #define CFI_type_int_fast64_t 20
75 #define CFI_type_int_fast128_t 21 /* extension */
76 #define CFI_type_intmax_t 22
77 #define CFI_type_intptr_t 23
78 #define CFI_type_ptrdiff_t 24
79 #define CFI_type_half_float 25 /* extension: kind=2 */
80 #define CFI_type_bfloat 26 /* extension: kind=3 */
81 #define CFI_type_float 27
82 #define CFI_type_double 28
83 #define CFI_type_extended_double 29 /* extension: kind=10 */
84 #define CFI_type_long_double 30
85 #define CFI_type_float128 31 /* extension: kind=16 */
86 #define CFI_type_half_float_Complex 32 /* extension: kind=2 */
87 #define CFI_type_bfloat_Complex 33 /* extension: kind=3 */
88 #define CFI_type_float_Complex 34
89 #define CFI_type_double_Complex 35
90 #define CFI_type_extended_double_Complex 36 /* extension: kind=10 */
91 #define CFI_type_long_double_Complex 37
92 #define CFI_type_float128_Complex 38 /* extension: kind=16 */
93 #define CFI_type_Bool 39
94 #define CFI_type_char 40
95 #define CFI_type_cptr 41
96 #define CFI_type_struct 42
97 #define CFI_type_char16_t 43 /* extension kind=2 */
98 #define CFI_type_char32_t 44 /* extension kind=4 */
99 #define CFI_type_uint8_t 45 /* extension: unsigned */
100 #define CFI_type_uint16_t 46
101 #define CFI_type_uint32_t 47
102 #define CFI_type_uint64_t 48
103 #define CFI_type_uint128_t 49
104 #define CFI_TYPE_LAST CFI_type_uint128_t
105 #define CFI_type_other (-1) // must be negative
106 
107 /* Error code macros - skip some of the small values to avoid conflicts with
108  * other status codes mandated by the standard, e.g. those returned by
109  * GET_ENVIRONMENT_VARIABLE (16.9.84) */
110 #define CFI_SUCCESS 0 /* must be zero */
111 #define CFI_ERROR_BASE_ADDR_NULL 11
112 #define CFI_ERROR_BASE_ADDR_NOT_NULL 12
113 #define CFI_INVALID_ELEM_LEN 13
114 #define CFI_INVALID_RANK 14
115 #define CFI_INVALID_TYPE 15
116 #define CFI_INVALID_ATTRIBUTE 16
117 #define CFI_INVALID_EXTENT 17
118 #define CFI_INVALID_DESCRIPTOR 18
119 #define CFI_ERROR_MEM_ALLOCATION 19
120 #define CFI_ERROR_OUT_OF_BOUNDS 20
121 
122 /* 18.5.2 per-dimension information */
123 typedef struct CFI_dim_t {
124   CFI_index_t lower_bound;
125   CFI_index_t extent; /* == -1 for assumed size */
126   CFI_index_t sm; /* memory stride in bytes */
127 } CFI_dim_t;
128 
129 #ifdef __cplusplus
130 namespace cfi_internal {
131 // C++ does not support flexible array.
132 // The below structure emulates a flexible array. This structure does not take
133 // care of getting the memory storage. Note that it already contains one element
134 // because a struct cannot be empty.
135 extern "C++" template <typename T> struct FlexibleArray : T {
136   RT_API_ATTRS T &operator[](int index) { return *(this + index); }
137   RT_API_ATTRS const T &operator[](int index) const { return *(this + index); }
138   RT_API_ATTRS operator T *() { return this; }
139   RT_API_ATTRS operator const T *() const { return this; }
140 };
141 } // namespace cfi_internal
142 #endif
143 
144 /* 18.5.3 generic data descriptor */
145 
146 /* Descriptor header members */
147 #define _CFI_CDESC_T_HEADER_MEMBERS \
148   /* These three members must appear first, \
149    * in exactly this order. */ \
150   void *base_addr; \
151   size_t elem_len; /* element size in bytes */ \
152   int version; /* == CFI_VERSION */ \
153   CFI_rank_t rank; /* [0 .. CFI_MAX_RANK] */ \
154   CFI_type_t type; \
155   CFI_attribute_t attribute; \
156   /* This encodes both the presence of the f18Addendum and the index of the \
157    * allocator used to managed memory of the data hold by the descriptor. */ \
158   unsigned char extra;
159 
160 typedef struct CFI_cdesc_t {
161   _CFI_CDESC_T_HEADER_MEMBERS
162 #ifdef __cplusplus
163   cfi_internal::FlexibleArray<CFI_dim_t> dim;
164 #else
165   CFI_dim_t dim[]; /* must appear last */
166 #endif
167 } CFI_cdesc_t;
168 
169 /* 18.5.4 */
170 #ifdef __cplusplus
171 // This struct acquires the additional storage, if any is
172 // needed, for C++'s CFI_cdesc_t's emulated flexible
173 // dim[] array.
174 namespace cfi_internal {
175 extern "C++" template <int r> struct CdescStorage : public CFI_cdesc_t {
176   static_assert((r > 1 && r <= CFI_MAX_RANK), "CFI_INVALID_RANK");
177   CFI_dim_t dim[r - 1];
178 };
179 extern "C++" template <> struct CdescStorage<1> : public CFI_cdesc_t {};
180 extern "C++" template <> struct CdescStorage<0> : public CFI_cdesc_t {};
181 } // namespace cfi_internal
182 #define CFI_CDESC_T(rank) \
183   FORTRAN_ISO_NAMESPACE_::cfi_internal::CdescStorage<rank>
184 #else
185 #define CFI_CDESC_T(_RANK) \
186   struct { \
187     _CFI_CDESC_T_HEADER_MEMBERS \
188     CFI_dim_t dim[_RANK]; \
189   }
190 #endif
191 
192 /* 18.5.5 procedural interfaces*/
193 #ifdef __cplusplus
194 extern "C" {
195 #endif
196 RT_API_ATTRS void *CFI_address(
197     const CFI_cdesc_t *, const CFI_index_t subscripts[]);
198 RT_API_ATTRS int CFI_allocate(CFI_cdesc_t *, const CFI_index_t lower_bounds[],
199     const CFI_index_t upper_bounds[], size_t elem_len);
200 RT_API_ATTRS int CFI_deallocate(CFI_cdesc_t *);
201 RT_API_ATTRS int CFI_establish(CFI_cdesc_t *, void *base_addr, CFI_attribute_t,
202     CFI_type_t, size_t elem_len, CFI_rank_t, const CFI_index_t extents[]);
203 RT_API_ATTRS int CFI_is_contiguous(const CFI_cdesc_t *);
204 RT_API_ATTRS int CFI_section(CFI_cdesc_t *, const CFI_cdesc_t *source,
205     const CFI_index_t lower_bounds[], const CFI_index_t upper_bounds[],
206     const CFI_index_t strides[]);
207 RT_API_ATTRS int CFI_select_part(CFI_cdesc_t *, const CFI_cdesc_t *source,
208     size_t displacement, size_t elem_len);
209 RT_API_ATTRS int CFI_setpointer(
210     CFI_cdesc_t *, const CFI_cdesc_t *source, const CFI_index_t lower_bounds[]);
211 #ifdef __cplusplus
212 } // extern "C"
213 #endif
214 
215 #endif /* CFI_ISO_FORTRAN_BINDING_H_ */
216