forked from OSchip/llvm-project
[flang] checkpoint work on descriptors
Original-commit: flang-compiler/f18@5e68ebea25 Reviewed-on: https://github.com/flang-compiler/f18/pull/162 Tree-same-pre-rewrite: false
This commit is contained in:
parent
ab9d0987a2
commit
adc597b032
|
@ -48,7 +48,10 @@ int CFI_allocate(CFI_cdesc_t *descriptor, const CFI_index_t lower_bounds[],
|
|||
if (descriptor->rank > CFI_MAX_RANK) {
|
||||
return CFI_INVALID_RANK;
|
||||
}
|
||||
// TODO: CFI_INVALID_TYPE?
|
||||
if (descriptor->type < CFI_type_signed_char ||
|
||||
descriptor->type > CFI_type_struct) {
|
||||
return CFI_INVALID_TYPE;
|
||||
}
|
||||
if (descriptor->type != CFI_type_cptr) {
|
||||
elem_len = descriptor->elem_len;
|
||||
if (elem_len <= 0) {
|
||||
|
@ -72,6 +75,7 @@ int CFI_allocate(CFI_cdesc_t *descriptor, const CFI_index_t lower_bounds[],
|
|||
return CFI_ERROR_MEM_ALLOCATION;
|
||||
}
|
||||
descriptor->base_addr = p;
|
||||
descriptor->elem_len = elem_len;
|
||||
return CFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -92,6 +96,48 @@ int CFI_deallocate(CFI_cdesc_t *descriptor) {
|
|||
return CFI_SUCCESS;
|
||||
}
|
||||
|
||||
static constexpr std::size_t MinElemLen(CFI_type_t type) {
|
||||
std::size_t minElemLen{0};
|
||||
switch (type) {
|
||||
case CFI_type_signed_char: minElemLen = sizeof(signed char); break;
|
||||
case CFI_type_short: minElemLen = sizeof(short); break;
|
||||
case CFI_type_int: minElemLen = sizeof(int); break;
|
||||
case CFI_type_long: minElemLen = sizeof(long); break;
|
||||
case CFI_type_long_long: minElemLen = sizeof(long long); break;
|
||||
case CFI_type_size_t: minElemLen = sizeof(std::size_t); break;
|
||||
case CFI_type_int8_t: minElemLen = sizeof(std::int8_t); break;
|
||||
case CFI_type_int16_t: minElemLen = sizeof(std::int16_t); break;
|
||||
case CFI_type_int32_t: minElemLen = sizeof(std::int32_t); break;
|
||||
case CFI_type_int64_t: minElemLen = sizeof(std::int64_t); break;
|
||||
case CFI_type_int128_t: minElemLen = 2 * sizeof(std::int64_t); break;
|
||||
case CFI_type_int_least8_t: minElemLen = sizeof(std::int_least8_t); break;
|
||||
case CFI_type_int_least16_t: minElemLen = sizeof(std::int_least16_t); break;
|
||||
case CFI_type_int_least32_t: minElemLen = sizeof(std::int_least32_t); break;
|
||||
case CFI_type_int_least64_t: minElemLen = sizeof(std::int_least64_t); break;
|
||||
case CFI_type_int_least128_t:
|
||||
minElemLen = 2 * sizeof(std::int_least64_t);
|
||||
break;
|
||||
case CFI_type_int_fast8_t: minElemLen = sizeof(std::int_fast8_t); break;
|
||||
case CFI_type_int_fast16_t: minElemLen = sizeof(std::int_fast16_t); break;
|
||||
case CFI_type_int_fast32_t: minElemLen = sizeof(std::int_fast32_t); break;
|
||||
case CFI_type_int_fast64_t: minElemLen = sizeof(std::int_fast64_t); break;
|
||||
case CFI_type_intmax_t: minElemLen = sizeof(std::intmax_t); break;
|
||||
case CFI_type_intptr_t: minElemLen = sizeof(std::intptr_t); break;
|
||||
case CFI_type_ptrdiff_t: minElemLen = sizeof(std::ptrdiff_t); break;
|
||||
case CFI_type_float: minElemLen = sizeof(float); break;
|
||||
case CFI_type_double: minElemLen = sizeof(double); break;
|
||||
case CFI_type_long_double: minElemLen = sizeof(long double); break;
|
||||
case CFI_type_float_Complex: minElemLen = 2 * sizeof(float); break;
|
||||
case CFI_type_double_Complex: minElemLen = 2 * sizeof(double); break;
|
||||
case CFI_type_long_double_Complex:
|
||||
minElemLen = 2 * sizeof(long double);
|
||||
break;
|
||||
case CFI_type_Bool: minElemLen = 1; break;
|
||||
case CFI_type_char: minElemLen = sizeof(char); break;
|
||||
}
|
||||
return minElemLen;
|
||||
}
|
||||
|
||||
int CFI_establish(CFI_cdesc_t *descriptor, void *base_addr,
|
||||
CFI_attribute_t attribute, CFI_type_t type, std::size_t elem_len,
|
||||
CFI_rank_t rank, const CFI_index_t extents[]) {
|
||||
|
@ -107,9 +153,14 @@ int CFI_establish(CFI_cdesc_t *descriptor, void *base_addr,
|
|||
if (rank > 0 && base_addr != nullptr && extents == nullptr) {
|
||||
return CFI_INVALID_EXTENT;
|
||||
}
|
||||
if (type != CFI_type_struct && type != CFI_type_other &&
|
||||
type != CFI_type_cptr) {
|
||||
// TODO: force value of elem_len
|
||||
if (type < CFI_type_signed_char || type > CFI_type_struct) {
|
||||
return CFI_INVALID_TYPE;
|
||||
}
|
||||
std::size_t minElemLen{MinElemLen(type)};
|
||||
if (minElemLen > 0) {
|
||||
elem_len = minElemLen;
|
||||
} else if (elem_len <= 0) {
|
||||
return CFI_INVALID_ELEM_LEN;
|
||||
}
|
||||
descriptor->base_addr = base_addr;
|
||||
descriptor->elem_len = elem_len;
|
||||
|
|
|
@ -15,31 +15,108 @@
|
|||
// TODO: Not complete; exists to check compilability of descriptor.h
|
||||
|
||||
#include "descriptor.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace Fortran::runtime {
|
||||
|
||||
Descriptor::Descriptor(const DerivedTypeSpecialization &dts, int rank) {
|
||||
raw_.base_addr = nullptr;
|
||||
raw_.elem_len = dts.SizeInBytes();
|
||||
raw_.version = CFI_VERSION;
|
||||
raw_.rank = rank;
|
||||
raw_.type = CFI_type_struct;
|
||||
raw_.attribute = ADDENDUM;
|
||||
Addendum()->set_derivedTypeSpecialization(&dts);
|
||||
TypeCode::TypeCode(TypeCode::Form f, int kind) {
|
||||
switch (f) {
|
||||
case Form::Integer:
|
||||
switch (kind) {
|
||||
case 1: raw_ = CFI_type_int8_t; break;
|
||||
case 2: raw_ = CFI_type_int16_t; break;
|
||||
case 4: raw_ = CFI_type_int32_t; break;
|
||||
case 8: raw_ = CFI_type_int64_t; break;
|
||||
case 16: raw_ = CFI_type_int128_t; break;
|
||||
}
|
||||
break;
|
||||
case Form::Real:
|
||||
switch (kind) {
|
||||
case 4: raw_ = CFI_type_float; break;
|
||||
case 8: raw_ = CFI_type_double; break;
|
||||
case 10:
|
||||
case 16: raw_ = CFI_type_long_double; break;
|
||||
}
|
||||
break;
|
||||
case Form::Complex:
|
||||
switch (kind) {
|
||||
case 4: raw_ = CFI_type_float_Complex; break;
|
||||
case 8: raw_ = CFI_type_double_Complex; break;
|
||||
case 10:
|
||||
case 16: raw_ = CFI_type_long_double_Complex; break;
|
||||
}
|
||||
break;
|
||||
case Form::Character:
|
||||
if (kind == 1) {
|
||||
raw_ = CFI_type_cptr;
|
||||
}
|
||||
break;
|
||||
case Form::Logical:
|
||||
switch (kind) {
|
||||
case 1: raw_ = CFI_type_Bool; break;
|
||||
case 2: raw_ = CFI_type_int16_t; break;
|
||||
case 4: raw_ = CFI_type_int32_t; break;
|
||||
case 8: raw_ = CFI_type_int64_t; break;
|
||||
}
|
||||
break;
|
||||
case Form::Derived: raw_ = CFI_type_struct; break;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t Descriptor::SizeInBytes() const {
|
||||
std::size_t DescriptorAddendum::SizeInBytes() const {
|
||||
return SizeInBytes(derivedTypeSpecialization_->derivedType().lenParameters());
|
||||
}
|
||||
|
||||
void DescriptorView::SetDerivedTypeSpecialization(
|
||||
const DerivedTypeSpecialization &dts) {
|
||||
raw_.attribute |= ADDENDUM;
|
||||
Addendum()->set_derivedTypeSpecialization(dts);
|
||||
}
|
||||
|
||||
void DescriptorView::SetLenParameterValue(int which, TypeParameterValue x) {
|
||||
raw_.attribute |= ADDENDUM;
|
||||
Addendum()->SetLenParameterValue(which, x);
|
||||
}
|
||||
|
||||
std::size_t DescriptorView::SizeInBytes() const {
|
||||
const DescriptorAddendum *addendum{Addendum()};
|
||||
return sizeof *this + raw_.rank * sizeof(Dimension) +
|
||||
(addendum ? addendum->SizeOfAddendumInBytes() : 0);
|
||||
return sizeof *this - sizeof(Dimension) + raw_.rank * sizeof(Dimension) +
|
||||
(addendum ? addendum->SizeInBytes() : 0);
|
||||
}
|
||||
|
||||
std::int64_t TypeParameter::KindParameterValue(
|
||||
int DescriptorView::Establish(TypeCode t, std::size_t elementBytes, void *p,
|
||||
int rank, const SubscriptValue *extent) {
|
||||
return CFI_establish(
|
||||
&raw_, p, CFI_attribute_other, t.raw(), elementBytes, rank, extent);
|
||||
}
|
||||
|
||||
int DescriptorView::Establish(TypeCode::Form f, int kind, void *p, int rank,
|
||||
const SubscriptValue *extent) {
|
||||
std::size_t elementBytes = kind;
|
||||
if (f == TypeCode::Form::Complex) {
|
||||
elementBytes *= 2;
|
||||
}
|
||||
return ISO::CFI_establish(&raw_, p, CFI_attribute_other,
|
||||
TypeCode(f, kind).raw(), elementBytes, rank, extent);
|
||||
}
|
||||
|
||||
int DescriptorView::Establish(const DerivedTypeSpecialization &dts, void *p,
|
||||
int rank, const SubscriptValue *extent) {
|
||||
int result{ISO::CFI_establish(
|
||||
&raw_, p, ADDENDUM, CFI_type_struct, dts.SizeInBytes(), rank, extent)};
|
||||
if (result == CFI_SUCCESS) {
|
||||
Addendum()->set_derivedTypeSpecialization(dts);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TypeParameterValue TypeParameter::KindParameterValue(
|
||||
const DerivedTypeSpecialization &specialization) const {
|
||||
return specialization.KindParameterValue(which_);
|
||||
}
|
||||
|
||||
std::int64_t TypeParameter::Value(const Descriptor &descriptor) const {
|
||||
TypeParameterValue TypeParameter::Value(
|
||||
const DescriptorView &descriptor) const {
|
||||
const DescriptorAddendum &addendum{*descriptor.Addendum()};
|
||||
if (isLenTypeParameter_) {
|
||||
return addendum.LenParameterValue(which_);
|
||||
|
@ -47,4 +124,64 @@ std::int64_t TypeParameter::Value(const Descriptor &descriptor) const {
|
|||
return KindParameterValue(*addendum.derivedTypeSpecialization());
|
||||
}
|
||||
}
|
||||
|
||||
bool DerivedType::IsNonTrivial() const {
|
||||
if (kindParameters_ > 0 || lenParameters_ > 0 || typeBoundProcedures_ > 0 ||
|
||||
definedAssignments_ > 0 || finalSubroutine_.host != 0) {
|
||||
return true;
|
||||
}
|
||||
for (int j{0}; j < components_; ++j) {
|
||||
if (component_[j].IsDescriptor()) {
|
||||
return true;
|
||||
}
|
||||
if (const DescriptorView *
|
||||
staticDescriptor{component_[j].staticDescriptor()}) {
|
||||
if (const DescriptorAddendum * addendum{staticDescriptor->Addendum()}) {
|
||||
if (const DerivedTypeSpecialization *
|
||||
dts{addendum->derivedTypeSpecialization()}) {
|
||||
if (dts->derivedType().IsNonTrivial()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Object::~Object() {
|
||||
if (p_ != nullptr) {
|
||||
// TODO final procedure calls and component destruction
|
||||
delete reinterpret_cast<char *>(p_);
|
||||
p_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool Object::Create(
|
||||
TypeCode::Form f, int kind, int rank, const SubscriptValue *extent) {
|
||||
if (f == TypeCode::Form::Character || f == TypeCode::Form::Derived) {
|
||||
// TODO support these...
|
||||
return false;
|
||||
}
|
||||
std::size_t descriptorBytes{DescriptorView::SizeInBytes(rank)};
|
||||
std::size_t elementBytes = kind;
|
||||
if (f == TypeCode::Form::Complex) {
|
||||
elementBytes *= 2;
|
||||
}
|
||||
std::size_t elements{1};
|
||||
for (int j{0}; j < rank; ++j) {
|
||||
if (extent[j] < 0) {
|
||||
return false;
|
||||
}
|
||||
elements *= static_cast<std::size_t>(extent[j]);
|
||||
}
|
||||
std::size_t totalBytes{descriptorBytes + elements * elementBytes};
|
||||
char *p{reinterpret_cast<char *>(std::malloc(totalBytes))};
|
||||
if (p == nullptr) {
|
||||
return false;
|
||||
}
|
||||
p_ = reinterpret_cast<DescriptorView *>(p);
|
||||
p_->Establish(f, kind, p + descriptorBytes, rank, extent);
|
||||
return true;
|
||||
}
|
||||
} // namespace Fortran::runtime
|
||||
|
|
|
@ -31,17 +31,21 @@
|
|||
namespace Fortran::runtime {
|
||||
|
||||
class DerivedTypeSpecialization;
|
||||
class DescriptorAddendum;
|
||||
|
||||
using TypeParameterValue = ISO::CFI_index_t;
|
||||
using SubscriptValue = ISO::CFI_index_t;
|
||||
|
||||
// A C++ view of the sole interoperable standard descriptor (ISO_cdesc_t)
|
||||
// and its type and per-dimension information.
|
||||
|
||||
class TypeCode {
|
||||
public:
|
||||
enum class Form { Integer, Real, Complex, Logical, Character, Derived };
|
||||
enum class Form { Integer, Real, Complex, Character, Logical, Derived };
|
||||
|
||||
TypeCode() {}
|
||||
explicit TypeCode(ISO::CFI_type_t t) : raw_{t} {}
|
||||
TypeCode(Form, int);
|
||||
|
||||
int raw() const { return raw_; }
|
||||
|
||||
constexpr bool IsValid() const {
|
||||
|
@ -57,13 +61,11 @@ public:
|
|||
return raw_ >= CFI_type_float_Complex &&
|
||||
raw_ <= CFI_type_long_double_Complex;
|
||||
}
|
||||
constexpr bool IsLogical() const { return raw_ == CFI_type_Bool; }
|
||||
constexpr bool IsCharacter() const { return raw_ == CFI_type_cptr; }
|
||||
constexpr bool IsLogical() const { return raw_ == CFI_type_Bool; }
|
||||
constexpr bool IsDerived() const { return raw_ == CFI_type_struct; }
|
||||
|
||||
constexpr bool IsIntrinsic() const {
|
||||
return IsValid() && !IsDerived();
|
||||
}
|
||||
constexpr bool IsIntrinsic() const { return IsValid() && !IsDerived(); }
|
||||
|
||||
constexpr Form GetForm() const {
|
||||
if (IsInteger()) {
|
||||
|
@ -75,12 +77,12 @@ public:
|
|||
if (IsComplex()) {
|
||||
return Form::Complex;
|
||||
}
|
||||
if (IsLogical()) {
|
||||
return Form::Logical;
|
||||
}
|
||||
if (IsCharacter()) {
|
||||
return Form::Character;
|
||||
}
|
||||
if (IsLogical()) {
|
||||
return Form::Logical;
|
||||
}
|
||||
return Form::Derived;
|
||||
}
|
||||
|
||||
|
@ -90,39 +92,78 @@ private:
|
|||
|
||||
class Dimension {
|
||||
public:
|
||||
std::int64_t LowerBound() const { return raw_.lower_bound; }
|
||||
std::int64_t Extent() const { return raw_.extent; }
|
||||
std::int64_t UpperBound() const { return LowerBound() + Extent() - 1; }
|
||||
std::int64_t ByteStride() const { return raw_.sm; }
|
||||
SubscriptValue LowerBound() const { return raw_.lower_bound; }
|
||||
SubscriptValue Extent() const { return raw_.extent; }
|
||||
SubscriptValue UpperBound() const { return LowerBound() + Extent() - 1; }
|
||||
SubscriptValue ByteStride() const { return raw_.sm; }
|
||||
|
||||
private:
|
||||
ISO::CFI_dim_t raw_;
|
||||
};
|
||||
static_assert(sizeof(Dimension) == sizeof(ISO::CFI_dim_t));
|
||||
|
||||
class Descriptor {
|
||||
// The storage for this object follows the last used dim[] entry in a
|
||||
// DescriptorView (CFI_cdesc_t) generic descriptor; this is why that class
|
||||
// cannot be defined as a derivation or encapsulation of the standard
|
||||
// argument descriptor. Space matters here, since dynamic descriptors
|
||||
// can serve as components of derived type instances. The presence of
|
||||
// this structure is implied by (CFI_cdesc_t.attribute & ADDENDUM) != 0,
|
||||
// and the number of elements in the len_[] array is determined by
|
||||
// DerivedType::lenParameters().
|
||||
class DescriptorAddendum {
|
||||
public:
|
||||
Descriptor(TypeCode t, std::size_t elementBytes, int rank = 0) {
|
||||
raw_.base_addr = nullptr;
|
||||
raw_.elem_len = elementBytes;
|
||||
raw_.version = CFI_VERSION;
|
||||
raw_.rank = rank;
|
||||
raw_.type = t.raw();
|
||||
raw_.attribute = 0;
|
||||
}
|
||||
Descriptor(const DerivedTypeSpecialization &, int rank = 0);
|
||||
explicit DescriptorAddendum(const DerivedTypeSpecialization &dts)
|
||||
: derivedTypeSpecialization_{&dts} {}
|
||||
|
||||
void Check() const;
|
||||
|
||||
template<typename A> A &Element(std::size_t offset = 0) const {
|
||||
auto p = reinterpret_cast<char *>(raw_.base_addr);
|
||||
return *reinterpret_cast<A *>(p + offset);
|
||||
DescriptorAddendum &set_derivedTypeSpecialization(
|
||||
const DerivedTypeSpecialization &dts) {
|
||||
derivedTypeSpecialization_ = &dts;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const DerivedTypeSpecialization *derivedTypeSpecialization() const {
|
||||
return derivedTypeSpecialization_;
|
||||
}
|
||||
|
||||
TypeParameterValue LenParameterValue(int which) const { return len_[which]; }
|
||||
static constexpr std::size_t SizeInBytes(int lenParameters) {
|
||||
return sizeof(DescriptorAddendum) - sizeof(TypeParameterValue) +
|
||||
lenParameters * sizeof(TypeParameterValue);
|
||||
}
|
||||
std::size_t SizeInBytes() const;
|
||||
|
||||
void SetLenParameterValue(int which, TypeParameterValue x) {
|
||||
len_[which] = x;
|
||||
}
|
||||
|
||||
private:
|
||||
const DerivedTypeSpecialization *derivedTypeSpecialization_{nullptr};
|
||||
TypeParameterValue len_[1]; // must be the last component
|
||||
// The LEN type parameter values can also include captured values of
|
||||
// specification expressions that were used for bounds and for LEN type
|
||||
// parameters of components. The values have been truncated to the LEN
|
||||
// type parameter's type, if shorter than 64 bits, then sign-extended.
|
||||
};
|
||||
|
||||
// A C++ view of a standard descriptor object. Do not use for actually
|
||||
// allocating a descriptor, as its size cannot be known at compilation
|
||||
// time -- see Descriptor below for that.
|
||||
class DescriptorView {
|
||||
public:
|
||||
DescriptorView() = delete;
|
||||
~DescriptorView() = delete;
|
||||
|
||||
ISO::CFI_cdesc_t &raw() { return raw_; }
|
||||
const ISO::CFI_cdesc_t &raw() const { return raw_; }
|
||||
std::size_t ElementBytes() const { return raw_.elem_len; }
|
||||
int rank() const { return raw_.rank; }
|
||||
TypeCode type() const { return TypeCode{raw_.type}; }
|
||||
|
||||
DescriptorView &set_base_addr(void *p) {
|
||||
raw_.base_addr = p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IsPointer() const {
|
||||
return (raw_.attribute & CFI_attribute_pointer) != 0;
|
||||
}
|
||||
|
@ -151,6 +192,12 @@ public:
|
|||
return *reinterpret_cast<const Dimension *>(&raw_.dim[dim]);
|
||||
}
|
||||
|
||||
std::size_t SubscriptByteOffset(
|
||||
int dim, SubscriptValue subscriptValue) const {
|
||||
const Dimension &dimension{GetDimension(dim)};
|
||||
return (subscriptValue - dimension.LowerBound()) * dimension.ByteStride();
|
||||
}
|
||||
|
||||
DescriptorAddendum *Addendum() {
|
||||
if ((raw_.attribute & ADDENDUM) != 0) {
|
||||
return reinterpret_cast<DescriptorAddendum *>(&GetDimension(rank()));
|
||||
|
@ -167,8 +214,36 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void SetDerivedTypeSpecialization(const DerivedTypeSpecialization &);
|
||||
|
||||
void SetLenParameterValue(int, TypeParameterValue);
|
||||
|
||||
static constexpr std::size_t SizeInBytes(
|
||||
int rank, bool nontrivialType = false, int lengthTypeParameters = 0) {
|
||||
std::size_t bytes{sizeof(DescriptorView) - sizeof(Dimension)};
|
||||
bytes += rank * sizeof(Dimension);
|
||||
if (nontrivialType || lengthTypeParameters > 0) {
|
||||
bytes += DescriptorAddendum::SizeInBytes(lengthTypeParameters);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
std::size_t SizeInBytes() const;
|
||||
|
||||
void Check() const;
|
||||
|
||||
int Establish(TypeCode t, std::size_t elementBytes, void *p = nullptr,
|
||||
int rank = 0, const SubscriptValue *extent = nullptr);
|
||||
int Establish(TypeCode::Form f, int kind, void *p = nullptr, int rank = 0,
|
||||
const SubscriptValue *extent = nullptr);
|
||||
int Establish(const DerivedTypeSpecialization &, void *p = nullptr,
|
||||
int rank = 0, const SubscriptValue *extent = nullptr);
|
||||
// TODO: creation of sections
|
||||
|
||||
template<typename A> A &Element(std::size_t offset = 0) const {
|
||||
auto p = reinterpret_cast<char *>(raw_.base_addr);
|
||||
return *reinterpret_cast<A *>(p + offset);
|
||||
}
|
||||
|
||||
private:
|
||||
// These values must coexist with the ISO_Fortran_binding.h definitions
|
||||
// for CFI_attribute_... values and fit in the "attribute" field of
|
||||
|
@ -187,7 +262,7 @@ private:
|
|||
|
||||
ISO::CFI_cdesc_t raw_;
|
||||
};
|
||||
static_assert(sizeof(Descriptor) == sizeof(ISO::CFI_cdesc_t));
|
||||
static_assert(sizeof(DescriptorView) == sizeof(ISO::CFI_cdesc_t));
|
||||
|
||||
// Static type information is suitable for loading in a read-only section.
|
||||
// Information about intrinsic types is inferable from raw CFI_type_t
|
||||
|
@ -200,18 +275,19 @@ public:
|
|||
const char *name() const { return name_; }
|
||||
const TypeCode typeCode() const { return typeCode_; }
|
||||
bool isLenTypeParameter() const { return isLenTypeParameter_; }
|
||||
std::size_t which() const { return which_; }
|
||||
std::int64_t defaultValue() const { return defaultValue_; }
|
||||
int which() const { return which_; }
|
||||
TypeParameterValue defaultValue() const { return defaultValue_; }
|
||||
|
||||
std::int64_t KindParameterValue(const DerivedTypeSpecialization &) const;
|
||||
std::int64_t Value(const Descriptor &) const;
|
||||
TypeParameterValue KindParameterValue(
|
||||
const DerivedTypeSpecialization &) const;
|
||||
TypeParameterValue Value(const DescriptorView &) const;
|
||||
|
||||
private:
|
||||
const char *name_;
|
||||
TypeCode typeCode_; // INTEGER, but not necessarily default kind
|
||||
bool isLenTypeParameter_; // whether value is in dynamic descriptor
|
||||
std::size_t which_; // index of this parameter in kind/len array
|
||||
std::int64_t defaultValue_;
|
||||
int which_; // index of this parameter in kind/len array
|
||||
TypeParameterValue defaultValue_;
|
||||
};
|
||||
|
||||
// Components that have any need for a descriptor will either reference
|
||||
|
@ -227,7 +303,7 @@ class Component {
|
|||
public:
|
||||
const char *name() const { return name_; }
|
||||
TypeCode typeCode() const { return typeCode_; }
|
||||
const Descriptor *staticDescriptor() const { return staticDescriptor_; }
|
||||
const DescriptorView *staticDescriptor() const { return staticDescriptor_; }
|
||||
bool IsParent() const { return (flags_ & PARENT) != 0; }
|
||||
bool IsPrivate() const { return (flags_ & PRIVATE) != 0; }
|
||||
bool IsDescriptor() const { return (flags_ & IS_DESCRIPTOR) != 0; }
|
||||
|
@ -237,7 +313,7 @@ private:
|
|||
const char *name_{nullptr};
|
||||
std::uint32_t flags_{0};
|
||||
TypeCode typeCode_{CFI_type_other};
|
||||
const Descriptor *staticDescriptor_{nullptr};
|
||||
const DescriptorView *staticDescriptor_{nullptr};
|
||||
};
|
||||
|
||||
struct ExecutableCode {
|
||||
|
@ -267,20 +343,19 @@ struct DefinedAssignment {
|
|||
// the execution of FINAL subroutines.
|
||||
class DerivedType {
|
||||
public:
|
||||
DerivedType(const char *n, std::size_t kps, std::size_t lps,
|
||||
const TypeParameter *tp, std::size_t cs, const Component *ca,
|
||||
std::size_t tbps, const TypeBoundProcedure *tbp, std::size_t das,
|
||||
DerivedType(const char *n, int kps, int lps, const TypeParameter *tp, int cs,
|
||||
const Component *ca, int tbps, const TypeBoundProcedure *tbp, int das,
|
||||
const DefinedAssignment *da)
|
||||
: name_{n}, kindParameters_{kps}, lenParameters_{lps}, components_{cs},
|
||||
typeParameter_{tp}, typeBoundProcedure_{tbp}, definedAssignments_{das},
|
||||
definedAssignment_{da} {}
|
||||
typeParameter_{tp}, typeBoundProcedures_{tbps}, typeBoundProcedure_{tbp},
|
||||
definedAssignments_{das}, definedAssignment_{da} {}
|
||||
|
||||
const char *name() const { return name_; }
|
||||
std::size_t kindParameters() const { return kindParameters_; }
|
||||
std::size_t lenParameters() const { return lenParameters_; }
|
||||
int kindParameters() const { return kindParameters_; }
|
||||
int lenParameters() const { return lenParameters_; }
|
||||
const TypeParameter &typeParameter(int n) const { return typeParameter_[n]; }
|
||||
std::size_t components() const { return components_; }
|
||||
std::size_t typeBoundProcedures() const { return typeBoundProcedures_; }
|
||||
int components() const { return components_; }
|
||||
int typeBoundProcedures() const { return typeBoundProcedures_; }
|
||||
const TypeBoundProcedure &typeBoundProcedure(int n) const {
|
||||
return typeBoundProcedure_[n];
|
||||
}
|
||||
|
@ -302,6 +377,7 @@ public:
|
|||
bool AnyPrivate() const;
|
||||
bool IsSequence() const { return (flags_ & SEQUENCE) != 0; }
|
||||
bool IsBindC() const { return (flags_ & BIND_C) != 0; }
|
||||
bool IsNonTrivial() const;
|
||||
|
||||
// TODO: assignment
|
||||
// TODO: finalization
|
||||
|
@ -309,19 +385,19 @@ public:
|
|||
private:
|
||||
enum Flag { SEQUENCE = 1, BIND_C = 2 };
|
||||
|
||||
const char *name_; // NUL-terminated constant text
|
||||
const char *name_{""}; // NUL-terminated constant text
|
||||
std::uint64_t flags_{0}; // needed for IsSameType() correct semantics
|
||||
std::size_t kindParameters_;
|
||||
std::size_t lenParameters_;
|
||||
std::size_t components_; // *not* including type parameters
|
||||
std::size_t typeBoundProcedures_;
|
||||
const TypeParameter *typeParameter_; // array
|
||||
const Component *component_; // array
|
||||
const TypeBoundProcedure
|
||||
*typeBoundProcedure_; // array of overridable TBP bindings
|
||||
int kindParameters_{0};
|
||||
int lenParameters_{0};
|
||||
int components_{0}; // *not* including type parameters
|
||||
const TypeParameter *typeParameter_{nullptr}; // array
|
||||
const Component *component_{nullptr}; // array
|
||||
int typeBoundProcedures_{0};
|
||||
const TypeBoundProcedure *typeBoundProcedure_{
|
||||
nullptr}; // array of overridable TBP bindings
|
||||
ExecutableCode finalSubroutine_; // can be null
|
||||
std::size_t definedAssignments_;
|
||||
const DefinedAssignment *definedAssignment_; // array
|
||||
int definedAssignments_{0};
|
||||
const DefinedAssignment *definedAssignment_{nullptr}; // array
|
||||
};
|
||||
|
||||
class ComponentSpecialization {
|
||||
|
@ -332,12 +408,12 @@ public:
|
|||
template<typename A> const A *Locate(const char *instance) const {
|
||||
return reinterpret_cast<const A *>(instance + offset_);
|
||||
}
|
||||
const Descriptor *GetDescriptor(
|
||||
const DescriptorView *GetDescriptorView(
|
||||
const Component &c, const char *instance) const {
|
||||
if (const Descriptor * staticDescriptor{c.staticDescriptor()}) {
|
||||
if (const DescriptorView * staticDescriptor{c.staticDescriptor()}) {
|
||||
return staticDescriptor;
|
||||
} else if (c.IsDescriptor()) {
|
||||
return Locate<const Descriptor>(instance);
|
||||
return Locate<const DescriptorView>(instance);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -354,14 +430,14 @@ private:
|
|||
class DerivedTypeSpecialization {
|
||||
public:
|
||||
DerivedTypeSpecialization(const DerivedType &dt, std::size_t n,
|
||||
const char *init, const std::int64_t *kp,
|
||||
const char *init, const TypeParameterValue *kp,
|
||||
const ComponentSpecialization *cs)
|
||||
: derivedType_{dt}, bytes_{n}, initializer_{init}, kindParameterValue_{kp},
|
||||
componentSpecialization_{cs} {}
|
||||
const DerivedType &derivedType() const { return derivedType_; }
|
||||
|
||||
std::size_t SizeInBytes() const { return bytes_; }
|
||||
std::int64_t KindParameterValue(int n) const {
|
||||
TypeParameterValue KindParameterValue(int n) const {
|
||||
return kindParameterValue_[n];
|
||||
}
|
||||
const ComponentSpecialization &GetComponent(int n) const {
|
||||
|
@ -376,53 +452,10 @@ private:
|
|||
const DerivedType &derivedType_;
|
||||
std::size_t bytes_; // allocation size of one scalar instance, w/ alignment
|
||||
const char *initializer_; // can be null; includes base components
|
||||
const std::int64_t *kindParameterValue_; // array
|
||||
const TypeParameterValue *kindParameterValue_; // array
|
||||
const ComponentSpecialization *componentSpecialization_; // array
|
||||
};
|
||||
|
||||
// The storage for this object follows the last used dim[] entry in a
|
||||
// Descriptor (CFI_cdesc_t) generic descriptor; that is why this class
|
||||
// cannot be defined as a derivation or encapsulation of the standard
|
||||
// argument descriptor. Space matters here, since dynamic descriptors
|
||||
// can serve as components of derived type instances. The presence of
|
||||
// this structure is implied by (CFI_cdesc_t.attribute & ADDENDUM) != 0,
|
||||
// and the number of elements in the len_[] array is determined by
|
||||
// DerivedType::lenParameters().
|
||||
class DescriptorAddendum {
|
||||
public:
|
||||
explicit DescriptorAddendum(const DerivedTypeSpecialization *dts)
|
||||
: derivedTypeSpecialization_{dts} {}
|
||||
|
||||
DescriptorAddendum &set_derivedTypeSpecialization(
|
||||
const DerivedTypeSpecialization *dts) {
|
||||
derivedTypeSpecialization_ = dts;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const DerivedTypeSpecialization *derivedTypeSpecialization() const {
|
||||
return derivedTypeSpecialization_;
|
||||
}
|
||||
|
||||
std::int64_t LenParameterValue(std::size_t n) const { return len_[n]; }
|
||||
std::size_t SizeOfAddendumInBytes() const {
|
||||
return sizeof *this - sizeof len_[0] +
|
||||
derivedTypeSpecialization_->derivedType().lenParameters() *
|
||||
sizeof len_[0];
|
||||
}
|
||||
|
||||
void SetLenParameterValue(std::size_t which, std::int64_t x) {
|
||||
len_[which] = x;
|
||||
}
|
||||
|
||||
private:
|
||||
const DerivedTypeSpecialization *derivedTypeSpecialization_{nullptr};
|
||||
std::int64_t len_[1]; // must be the last component
|
||||
// The LEN type parameter values can also include captured values of
|
||||
// specification expressions that were used for bounds and for LEN type
|
||||
// parameters of components. The values have been truncated to the LEN
|
||||
// type parameter's type, if shorter than 64 bits, then sign-extended.
|
||||
};
|
||||
|
||||
// Procedure pointers have static links for host association.
|
||||
// TODO: define the target data structure of that static link
|
||||
struct ProcedurePointer {
|
||||
|
@ -432,5 +465,56 @@ struct ProcedurePointer {
|
|||
|
||||
// TODO: coarray hooks
|
||||
|
||||
template<int MAX_RANK = CFI_MAX_RANK,
|
||||
bool NONTRIVIAL_DERIVED_TYPE_ALLOWED = false, int MAX_LEN_PARMS = 0>
|
||||
class alignas(DescriptorView) Descriptor {
|
||||
public:
|
||||
static constexpr int maxRank{MAX_RANK};
|
||||
static constexpr int maxLengthTypeParameters{MAX_LEN_PARMS};
|
||||
static constexpr bool hasAddendum{
|
||||
NONTRIVIAL_DERIVED_TYPE_ALLOWED || MAX_LEN_PARMS > 0};
|
||||
|
||||
Descriptor(TypeCode t, std::size_t elementBytes, int rank = maxRank,
|
||||
const SubscriptValue *extent = nullptr) {
|
||||
View().Establish(t, elementBytes, rank, extent);
|
||||
}
|
||||
Descriptor(TypeCode::Form f, int kind, int rank = maxRank,
|
||||
const SubscriptValue *extent = nullptr) {
|
||||
View().Establish(f, kind, rank, extent);
|
||||
}
|
||||
Descriptor(const DerivedTypeSpecialization &dts, int rank = maxRank,
|
||||
const SubscriptValue *extent = nullptr) {
|
||||
View().Establish(dts, rank, extent);
|
||||
}
|
||||
|
||||
DescriptorView &View() {
|
||||
return *reinterpret_cast<DescriptorView *>(storage_);
|
||||
}
|
||||
const DescriptorView &View() const {
|
||||
return *reinterpret_cast<const DescriptorView *>(storage_);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr std::size_t byteSize{DescriptorView::SizeInBytes(
|
||||
maxRank, hasAddendum, maxLengthTypeParameters)};
|
||||
char storage_[byteSize];
|
||||
};
|
||||
|
||||
// A owning pointer to a whole object whose data are contiguous with and
|
||||
// preceded in memory by a descriptor.
|
||||
class Object {
|
||||
public:
|
||||
~Object();
|
||||
bool Create(TypeCode::Form f, int kind, int rank = 0,
|
||||
const SubscriptValue *extent = nullptr);
|
||||
bool Create(const DerivedTypeSpecialization &, int rank = 0,
|
||||
const SubscriptValue *lenParamsAndExtents = nullptr);
|
||||
bool Exists() const { return p_ != nullptr; }
|
||||
const DescriptorView &descriptorView() const { return *p_; }
|
||||
|
||||
private:
|
||||
DescriptorView *p_;
|
||||
};
|
||||
|
||||
} // namespace Fortran::runtime
|
||||
#endif // FORTRAN_RUNTIME_DESCRIPTOR_H_
|
||||
|
|
Loading…
Reference in New Issue