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