9#ifndef FORTRAN_RUNTIME_DESCRIPTOR_H_
10#define FORTRAN_RUNTIME_DESCRIPTOR_H_
21#include "flang/ISO_Fortran_binding_wrapper.h"
22#include "flang/Runtime/descriptor-consts.h"
23#include "flang/Runtime/memory.h"
24#include "flang/Runtime/type-code.h"
32namespace Fortran::runtime {
37static constexpr RT_CONST_VAR_ATTRS
int maxRank{CFI_MAX_RANK};
45 RT_API_ATTRS SubscriptValue LowerBound()
const {
return raw_.lower_bound; }
46 RT_API_ATTRS SubscriptValue Extent()
const {
return raw_.extent; }
47 RT_API_ATTRS SubscriptValue UpperBound()
const {
48 return LowerBound() + Extent() - 1;
50 RT_API_ATTRS SubscriptValue ByteStride()
const {
return raw_.sm; }
53 SubscriptValue lower, SubscriptValue upper) {
55 raw_.lower_bound = lower;
56 raw_.extent = upper - lower + 1;
65 RT_API_ATTRS
Dimension &SetLowerBound(SubscriptValue lower) {
66 raw_.lower_bound = lower;
69 RT_API_ATTRS
Dimension &SetUpperBound(SubscriptValue upper) {
70 auto lower{raw_.lower_bound};
71 raw_.extent = upper >= lower ? upper - lower + 1 : 0;
74 RT_API_ATTRS
Dimension &SetExtent(SubscriptValue extent) {
78 RT_API_ATTRS
Dimension &SetByteStride(SubscriptValue bytes) {
97 : derivedType_{dt}, len_{0} {}
109 RT_API_ATTRS std::size_t LenParameters()
const;
111 RT_API_ATTRS typeInfo::TypeParameterValue LenParameterValue(
int which)
const {
114 static constexpr RT_API_ATTRS std::size_t SizeInBytes(
int lenParameters) {
117 std::max(lenParameters - 1, 0) *
sizeof(typeInfo::TypeParameterValue);
119 RT_API_ATTRS std::size_t SizeInBytes()
const;
121 RT_API_ATTRS
void SetLenParameterValue(
122 int which, typeInfo::TypeParameterValue x) {
126 void Dump(FILE * = stdout)
const;
130 typeInfo::TypeParameterValue len_[1];
157 static RT_API_ATTRS std::size_t BytesFor(TypeCategory category,
int kind);
159 RT_API_ATTRS
void Establish(
TypeCode t, std::size_t elementBytes,
160 void *p =
nullptr,
int rank = maxRank,
161 const SubscriptValue *extent =
nullptr,
162 ISO::CFI_attribute_t attribute = CFI_attribute_other,
163 bool addendum =
false);
164 RT_API_ATTRS
void Establish(TypeCategory,
int kind,
void *p =
nullptr,
165 int rank = maxRank,
const SubscriptValue *extent =
nullptr,
166 ISO::CFI_attribute_t attribute = CFI_attribute_other,
167 bool addendum =
false);
168 RT_API_ATTRS
void Establish(
int characterKind, std::size_t characters,
169 void *p =
nullptr,
int rank = maxRank,
170 const SubscriptValue *extent =
nullptr,
171 ISO::CFI_attribute_t attribute = CFI_attribute_other,
172 bool addendum =
false);
174 void *p =
nullptr,
int rank = maxRank,
175 const SubscriptValue *extent =
nullptr,
176 ISO::CFI_attribute_t attribute = CFI_attribute_other);
184 std::size_t elementBytes,
void *p =
nullptr,
int rank = maxRank,
185 const SubscriptValue *extent =
nullptr,
186 ISO::CFI_attribute_t attribute = CFI_attribute_other,
189 void *p =
nullptr,
int rank = maxRank,
190 const SubscriptValue *extent =
nullptr,
191 ISO::CFI_attribute_t attribute = CFI_attribute_other);
193 SubscriptValue characters,
void *p =
nullptr,
int rank = maxRank,
194 const SubscriptValue *extent =
nullptr,
195 ISO::CFI_attribute_t attribute = CFI_attribute_other);
198 const SubscriptValue *extent =
nullptr,
199 ISO::CFI_attribute_t attribute = CFI_attribute_other);
201 RT_API_ATTRS ISO::CFI_cdesc_t &raw() {
return raw_; }
202 RT_API_ATTRS
const ISO::CFI_cdesc_t &raw()
const {
return raw_; }
203 RT_API_ATTRS std::size_t ElementBytes()
const {
return raw_.elem_len; }
204 RT_API_ATTRS
int rank()
const {
return raw_.rank; }
207 RT_API_ATTRS
Descriptor &set_base_addr(
void *p) {
212 RT_API_ATTRS
bool IsPointer()
const {
213 return raw_.attribute == CFI_attribute_pointer;
215 RT_API_ATTRS
bool IsAllocatable()
const {
216 return raw_.attribute == CFI_attribute_allocatable;
218 RT_API_ATTRS
bool IsAllocated()
const {
return raw_.base_addr !=
nullptr; }
220 RT_API_ATTRS
Dimension &GetDimension(
int dim) {
221 return *
reinterpret_cast<Dimension *
>(&raw_.dim[dim]);
223 RT_API_ATTRS
const Dimension &GetDimension(
int dim)
const {
224 return *
reinterpret_cast<const Dimension *
>(&raw_.dim[dim]);
227 RT_API_ATTRS std::size_t SubscriptByteOffset(
228 int dim, SubscriptValue subscriptValue)
const {
229 const Dimension &dimension{GetDimension(dim)};
230 return (subscriptValue - dimension.LowerBound()) * dimension.ByteStride();
233 RT_API_ATTRS std::size_t SubscriptsToByteOffset(
234 const SubscriptValue subscript[])
const {
235 std::size_t offset{0};
236 for (
int j{0}; j < raw_.rank; ++j) {
237 offset += SubscriptByteOffset(j, subscript[j]);
242 template <
typename A =
char>
243 RT_API_ATTRS A *OffsetElement(std::size_t offset = 0)
const {
244 return reinterpret_cast<A *
>(
245 reinterpret_cast<char *
>(raw_.base_addr) + offset);
248 template <
typename A>
249 RT_API_ATTRS A *Element(
const SubscriptValue subscript[])
const {
250 return OffsetElement<A>(SubscriptsToByteOffset(subscript));
253 template <
typename A>
254 RT_API_ATTRS A *ElementComponent(
255 const SubscriptValue subscript[], std::size_t componentOffset)
const {
256 return OffsetElement<A>(
257 SubscriptsToByteOffset(subscript) + componentOffset);
260 template <
typename A>
261 RT_API_ATTRS A *ZeroBasedIndexedElement(std::size_t n)
const {
262 SubscriptValue at[maxRank];
263 if (SubscriptsForZeroBasedElementNumber(at, n)) {
264 return Element<A>(at);
269 RT_API_ATTRS
int GetLowerBounds(SubscriptValue subscript[])
const {
270 for (
int j{0}; j < raw_.rank; ++j) {
271 subscript[j] = GetDimension(j).LowerBound();
276 RT_API_ATTRS
int GetShape(SubscriptValue subscript[])
const {
277 for (
int j{0}; j < raw_.rank; ++j) {
278 subscript[j] = GetDimension(j).Extent();
286 RT_API_ATTRS
bool IncrementSubscripts(
287 SubscriptValue subscript[],
const int *permutation =
nullptr)
const {
288 for (
int j{0}; j < raw_.rank; ++j) {
289 int k{permutation ? permutation[j] : j};
291 if (subscript[k]++ < dim.UpperBound()) {
294 subscript[k] = dim.LowerBound();
299 RT_API_ATTRS
bool DecrementSubscripts(
300 SubscriptValue[],
const int *permutation =
nullptr)
const;
303 RT_API_ATTRS
bool SubscriptsForZeroBasedElementNumber(
304 SubscriptValue subscript[], std::size_t elementNumber,
305 const int *permutation =
nullptr)
const {
306 if (raw_.rank == 0) {
307 return elementNumber == 0;
309 std::size_t dimCoefficient[maxRank];
310 int k0{permutation ? permutation[0] : 0};
311 dimCoefficient[0] = 1;
312 auto coefficient{
static_cast<std::size_t
>(GetDimension(k0).Extent())};
313 for (
int j{1}; j < raw_.rank; ++j) {
314 int k{permutation ? permutation[j] : j};
316 dimCoefficient[j] = coefficient;
317 coefficient *= dim.Extent();
319 if (elementNumber >= coefficient) {
322 for (
int j{raw_.rank - 1}; j > 0; --j) {
323 int k{permutation ? permutation[j] : j};
325 std::size_t quotient{elementNumber / dimCoefficient[j]};
326 subscript[k] = quotient + dim.LowerBound();
327 elementNumber -= quotient * dimCoefficient[j];
329 subscript[k0] = elementNumber + GetDimension(k0).LowerBound();
333 RT_API_ATTRS std::size_t ZeroBasedElementNumber(
334 const SubscriptValue *,
const int *permutation =
nullptr)
const;
346 &GetDimension(rank()));
353 static constexpr RT_API_ATTRS std::size_t SizeInBytes(
354 int rank,
bool addendum =
false,
int lengthTypeParameters = 0) {
357 if (addendum || lengthTypeParameters > 0) {
358 bytes += DescriptorAddendum::SizeInBytes(lengthTypeParameters);
363 RT_API_ATTRS std::size_t SizeInBytes()
const;
365 RT_API_ATTRS std::size_t Elements()
const;
372 RT_API_ATTRS
int Allocate();
373 RT_API_ATTRS
void SetByteStrides();
377 RT_API_ATTRS
int Deallocate();
381 RT_API_ATTRS
int Destroy(
bool finalize =
false,
bool destroyPointers =
false,
384 RT_API_ATTRS
bool IsContiguous(
int leadingDimensions = maxRank)
const {
385 auto bytes{
static_cast<SubscriptValue
>(ElementBytes())};
386 if (leadingDimensions > raw_.rank) {
387 leadingDimensions = raw_.rank;
389 bool stridesAreContiguous{
true};
390 for (
int j{0}; j < leadingDimensions; ++j) {
392 stridesAreContiguous &=
393 (bytes == dim.ByteStride()) || (dim.Extent() == 1);
394 bytes *= dim.Extent();
403 return stridesAreContiguous || bytes == 0;
407 RT_API_ATTRS
bool EstablishPointerSection(
const Descriptor &source,
408 const SubscriptValue *lower =
nullptr,
409 const SubscriptValue *upper =
nullptr,
410 const SubscriptValue *stride =
nullptr);
412 RT_API_ATTRS
void ApplyMold(
const Descriptor &,
int rank);
414 RT_API_ATTRS
void Check()
const;
416 void Dump(FILE * = stdout)
const;
418 RT_API_ATTRS
inline bool HasAddendum()
const {
419 return raw_.extra & _CFI_ADDENDUM_FLAG;
421 RT_API_ATTRS
inline void SetHasAddendum() {
422 raw_.extra |= _CFI_ADDENDUM_FLAG;
424 RT_API_ATTRS
inline int GetAllocIdx()
const {
425 return (raw_.extra & _CFI_ALLOCATOR_IDX_MASK) >> _CFI_ALLOCATOR_IDX_SHIFT;
427 RT_API_ATTRS
inline void SetAllocIdx(
int pos) {
428 raw_.extra &= ~_CFI_ALLOCATOR_IDX_MASK;
429 raw_.extra |= pos << _CFI_ALLOCATOR_IDX_SHIFT;
433 ISO::CFI_cdesc_t raw_;
435static_assert(
sizeof(
Descriptor) ==
sizeof(ISO::CFI_cdesc_t));
446template <
int MAX_RANK = maxRank,
bool ADDENDUM = false,
int MAX_LEN_PARMS = 0>
449 RT_OFFLOAD_VAR_GROUP_BEGIN
450 static constexpr int maxRank{MAX_RANK};
451 static constexpr int maxLengthTypeParameters{MAX_LEN_PARMS};
452 static constexpr bool hasAddendum{ADDENDUM || MAX_LEN_PARMS > 0};
453 static constexpr std::size_t byteSize{
454 Descriptor::SizeInBytes(maxRank, hasAddendum, maxLengthTypeParameters)};
455 static_assert(byteSize <=
456 MaxDescriptorSizeInBytes(maxRank, hasAddendum, maxLengthTypeParameters));
457 RT_OFFLOAD_VAR_GROUP_END
460 return *
reinterpret_cast<Descriptor *
>(storage_);
462 RT_API_ATTRS
const Descriptor &descriptor()
const {
463 return *
reinterpret_cast<const Descriptor *
>(storage_);
466 RT_API_ATTRS
void Check() {
467 assert(descriptor().rank() <= maxRank);
468 assert(descriptor().SizeInBytes() <= byteSize);
472 assert(addendum->LenParameters() <= maxLengthTypeParameters);
474 assert(!hasAddendum);
475 assert(maxLengthTypeParameters == 0);
477 descriptor().Check();
481 char storage_[byteSize]{};
Definition: descriptor.h:93
Definition: descriptor.h:138
Definition: descriptor.h:43
Definition: descriptor.h:447
Definition: terminator.h:23
Definition: type-code.h:21
Definition: type-info.h:204