From 6f9fa21d50f12cf2b2535f459f0fa30b5dcff857 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Wed, 1 Aug 2018 10:55:46 -0700 Subject: [PATCH] [flang] Move descriptor flags into addendum. Original-commit: flang-compiler/f18@f5839874efe072cdb6b542f7a156d5d4b0785d08 Reviewed-on: https://github.com/flang-compiler/f18/pull/162 Tree-same-pre-rewrite: false --- flang/include/flang/ISO_Fortran_binding.h | 1 + flang/runtime/descriptor.cc | 75 ++++++++++---------- flang/runtime/descriptor.h | 109 ++++++++++++------------------ 3 files changed, 84 insertions(+), 101 deletions(-) diff --git a/flang/include/flang/ISO_Fortran_binding.h b/flang/include/flang/ISO_Fortran_binding.h index 409951d..0c923f8 100644 --- a/flang/include/flang/ISO_Fortran_binding.h +++ b/flang/include/flang/ISO_Fortran_binding.h @@ -127,6 +127,7 @@ typedef struct CFI_cdesc_t { CFI_rank_t rank; /* [0 .. CFI_MAX_RANK] */ CFI_type_t type; CFI_attribute_t attribute; + unsigned char f18Addendum; CFI_dim_t dim[CFI_ISO_FORTRAN_BINDING_FLEXIBLE_ARRAY]; /* must appear last */ } CFI_cdesc_t; diff --git a/flang/runtime/descriptor.cc b/flang/runtime/descriptor.cc index 13e2a2b..2d34f0c 100644 --- a/flang/runtime/descriptor.cc +++ b/flang/runtime/descriptor.cc @@ -18,75 +18,79 @@ namespace Fortran::runtime { -Descriptor::~Descriptor() { assert(!(Attributes() & CREATED)); } +Descriptor::~Descriptor() { + // Descriptors created by Descriptor::Create() must be destroyed by + // Descriptor::Destroy(), not by the default destructor, so that + // the array variant operator delete[] is properly used. + assert(!(Addendum() && (Addendum()->flags() & DescriptorAddendum::Created))); +} int Descriptor::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 rank, const SubscriptValue *extent, ISO::CFI_attribute_t attribute, + bool addendum) { + int result{ + CFI_establish(&raw_, p, attribute, t.raw(), elementBytes, rank, extent)}; + raw_.f18Addendum = addendum; + return result; } -int Descriptor::Establish( - TypeCategory c, int kind, void *p, int rank, const SubscriptValue *extent) { +int Descriptor::Establish(TypeCategory c, int kind, void *p, int rank, + const SubscriptValue *extent, ISO::CFI_attribute_t attribute, + bool addendum) { std::size_t elementBytes = kind; if (c == TypeCategory::Complex) { elementBytes *= 2; } - return ISO::CFI_establish(&raw_, p, CFI_attribute_other, - TypeCode(c, kind).raw(), elementBytes, rank, extent); + int result{ISO::CFI_establish(&raw_, p, attribute, TypeCode(c, kind).raw(), + elementBytes, rank, extent)}; + raw_.f18Addendum = addendum; + return result; } -int Descriptor::Establish( - const DerivedType &dt, void *p, int rank, const SubscriptValue *extent) { +int Descriptor::Establish(const DerivedType &dt, void *p, int rank, + const SubscriptValue *extent, ISO::CFI_attribute_t attribute) { int result{ISO::CFI_establish( - &raw_, p, ADDENDUM, CFI_type_struct, dt.SizeInBytes(), rank, extent)}; + &raw_, p, attribute, CFI_type_struct, dt.SizeInBytes(), rank, extent)}; + raw_.f18Addendum = true; Addendum()->set_derivedType(dt); return result; } Descriptor *Descriptor::Create(TypeCode t, std::size_t elementBytes, void *p, - int rank, const SubscriptValue *extent) { + int rank, const SubscriptValue *extent, ISO::CFI_attribute_t attribute) { std::size_t bytes{SizeInBytes(rank)}; Descriptor *result{reinterpret_cast(new char[bytes])}; - result->Establish(t, elementBytes, p, rank, extent); - result->Attributes() |= CREATED; + result->Establish(t, elementBytes, p, rank, extent, attribute, true); + result->Addendum()->flags() |= DescriptorAddendum::Created; return result; } -Descriptor *Descriptor::Create( - TypeCategory c, int kind, void *p, int rank, const SubscriptValue *extent) { +Descriptor *Descriptor::Create(TypeCategory c, int kind, void *p, int rank, + const SubscriptValue *extent, ISO::CFI_attribute_t attribute) { std::size_t bytes{SizeInBytes(rank)}; Descriptor *result{reinterpret_cast(new char[bytes])}; - result->Establish(c, kind, p, rank, extent); - result->Attributes() |= CREATED; + result->Establish(c, kind, p, rank, extent, attribute, true); + result->Addendum()->flags() |= DescriptorAddendum::Created; return result; } -Descriptor *Descriptor::Create( - const DerivedType &dt, void *p, int rank, const SubscriptValue *extent) { +Descriptor *Descriptor::Create(const DerivedType &dt, void *p, int rank, + const SubscriptValue *extent, ISO::CFI_attribute_t attribute) { std::size_t bytes{SizeInBytes(rank, dt.IsNontrivial(), dt.lenParameters())}; Descriptor *result{reinterpret_cast(new char[bytes])}; - result->Establish(dt, p, rank, extent); - result->Attributes() |= CREATED; + result->Establish(dt, p, rank, extent, attribute); + result->Addendum()->flags() |= DescriptorAddendum::Created; return result; } void Descriptor::Destroy() { - if (Attributes() & CREATED) { - delete[] reinterpret_cast(this); + if (const DescriptorAddendum * addendum{Addendum()}) { + if (addendum->flags() & DescriptorAddendum::Created) { + delete[] reinterpret_cast(this); + } } } -void Descriptor::SetDerivedType(const DerivedType &dt) { - Attributes() |= ADDENDUM; - Addendum()->set_derivedType(dt); -} - -void Descriptor::SetLenParameterValue(int which, TypeParameterValue x) { - Attributes() |= ADDENDUM; - Addendum()->SetLenParameterValue(which, x); -} - std::size_t Descriptor::SizeInBytes() const { const DescriptorAddendum *addendum{Addendum()}; return sizeof *this - sizeof(Dimension) + raw_.rank * sizeof(Dimension) + @@ -98,9 +102,6 @@ void Descriptor::Check() const { } std::size_t DescriptorAddendum::SizeInBytes() const { - if (derivedType_ == nullptr) { - return 0; - } return SizeInBytes(derivedType_->lenParameters()); } } // namespace Fortran::runtime diff --git a/flang/runtime/descriptor.h b/flang/runtime/descriptor.h index af843d7..e89cece 100644 --- a/flang/runtime/descriptor.h +++ b/flang/runtime/descriptor.h @@ -38,7 +38,7 @@ using SubscriptValue = ISO::CFI_index_t; static constexpr int maxRank{CFI_MAX_RANK}; -// A C++ view of the sole interoperable standard descriptor (ISO_cdesc_t) +// A C++ view of the sole interoperable standard descriptor (ISO::CFI_cdesc_t) // and its type and per-dimension information. class Dimension { @@ -56,18 +56,30 @@ private: // Descriptor (CFI_cdesc_t) generic descriptor. Space matters here, since // descriptors serve as POINTER and ALLOCATABLE components of derived type // instances. The presence of this structure is implied by the flag -// (CFI_cdesc_t.attribute & ADDENDUM) != 0, and the number of elements in +// (CFI_cdesc_t.extra & ADDENDUM) != 0, and the number of elements in // the len_[] array is determined by DerivedType::lenParameters(). class DescriptorAddendum { public: - explicit DescriptorAddendum(const DerivedType &dt) : derivedType_{&dt} {} + enum Flags { + StaticDescriptor = 0x001, + ImplicitAllocatable = 0x002, // compiler-created allocatable + Created = 0x004, // allocated by Descriptor::Create() + DoNotFinalize = 0x008, // compiler temporary + Target = 0x010, // TARGET attribute + AllContiguous = 0x020, // all array elements are contiguous + LeadingDimensionContiguous = 0x040, // only leading dimension contiguous + }; - const DerivedType *derivedType() const { return derivedType_; } + explicit DescriptorAddendum(const DerivedType &dt, std::uint64_t flags = 0) + : derivedType_{&dt}, flags_{flags} {} + const DerivedType *derivedType() const { return derivedType_; } DescriptorAddendum &set_derivedType(const DerivedType &dt) { derivedType_ = &dt; return *this; } + std::uint64_t &flags() { return flags_; } + const std::uint64_t &flags() const { return flags_; } TypeParameterValue LenParameterValue(int which) const { return len_[which]; } static constexpr std::size_t SizeInBytes(int lenParameters) { @@ -82,6 +94,7 @@ public: private: const DerivedType *derivedType_{nullptr}; + std::uint64_t flags_{0}; 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 @@ -96,30 +109,37 @@ public: // a descriptor -- it is a dynamic view of the common descriptor format. // If used in a simple declaration of a local variable or dynamic allocation, // the size is going to be wrong, since the true size of a descriptor - // depends on the number of its dimensions and the presence of an addendum - // with derived type information. Use the class template StaticDescriptor - // (below) to declare a descriptor with type and rank that are known at - // compilation time. Use the Create() static member functions to - // dynamically allocate a descriptor when the type or rank are not known - // at compilation time. + // depends on the number of its dimensions and the presence of an addendum. + // Use the class template StaticDescriptor (below) to declare a descriptor + // whose type and rank are fixed and known at compilation time. Use the + // Create() static member functions otherwise to dynamically allocate a + // descriptor. Descriptor() = delete; ~Descriptor(); int Establish(TypeCode t, std::size_t elementBytes, void *p = nullptr, - int rank = maxRank, const SubscriptValue *extent = nullptr); + int rank = maxRank, const SubscriptValue *extent = nullptr, + ISO::CFI_attribute_t attribute = CFI_attribute_other, + bool addendum = false); int Establish(TypeCategory, int kind, void *p = nullptr, int rank = maxRank, - const SubscriptValue *extent = nullptr); + const SubscriptValue *extent = nullptr, + ISO::CFI_attribute_t attribute = CFI_attribute_other, + bool addendum = false); int Establish(const DerivedType &dt, void *p = nullptr, int rank = maxRank, - const SubscriptValue *extent = nullptr); + const SubscriptValue *extent = nullptr, + ISO::CFI_attribute_t attribute = CFI_attribute_other); static Descriptor *Create(TypeCode t, std::size_t elementBytes, void *p = nullptr, int rank = maxRank, - const SubscriptValue *extent = nullptr); + const SubscriptValue *extent = nullptr, + ISO::CFI_attribute_t attribute = CFI_attribute_other); static Descriptor *Create(TypeCategory, int kind, void *p = nullptr, - int rank = maxRank, const SubscriptValue *extent = nullptr); + int rank = maxRank, const SubscriptValue *extent = nullptr, + ISO::CFI_attribute_t attribute = CFI_attribute_other); static Descriptor *Create(const DerivedType &dt, void *p = nullptr, - int rank = maxRank, const SubscriptValue *extent = nullptr); + int rank = maxRank, const SubscriptValue *extent = nullptr, + ISO::CFI_attribute_t attribute = CFI_attribute_other); // Descriptor instances allocated via Create() above must be deallocated // by calling Destroy() so that operator delete[] is invoked. @@ -136,24 +156,10 @@ public: return *this; } - bool IsPointer() const { return (Attributes() & CFI_attribute_pointer) != 0; } + bool IsPointer() const { return raw_.attribute == CFI_attribute_pointer; } bool IsAllocatable() const { - return (Attributes() & CFI_attribute_allocatable) != 0; - } - bool IsImplicitlyAllocated() const { - return (Attributes() & IMPLICITLY_ALLOCATED) != 0; - } - bool IsDescriptorStatic() const { - return (Attributes() & STATIC_DESCRIPTOR) != 0; - } - bool IsTarget() const { - return (Attributes() & (CFI_attribute_pointer | TARGET)) != 0; + return raw_.attribute == CFI_attribute_allocatable; } - bool IsContiguous() const { return (Attributes() & CONTIGUOUS) != 0; } - bool IsColumnContiguous() const { - return (Attributes() & COLUMN_CONTIGUOUS) != 0; - } - bool IsTemporary() const { return (Attributes() & TEMPORARY) != 0; } Dimension &GetDimension(int dim) { return *reinterpret_cast(&raw_.dim[dim]); @@ -169,14 +175,14 @@ public: } DescriptorAddendum *Addendum() { - if ((Attributes() & ADDENDUM) != 0) { + if (raw_.f18Addendum != 0) { return reinterpret_cast(&GetDimension(rank())); } else { return nullptr; } } const DescriptorAddendum *Addendum() const { - if ((Attributes() & ADDENDUM) != 0) { + if (raw_.f18Addendum != 0) { return reinterpret_cast( &GetDimension(rank())); } else { @@ -184,15 +190,11 @@ public: } } - void SetDerivedType(const DerivedType &); - - void SetLenParameterValue(int, TypeParameterValue); - static constexpr std::size_t SizeInBytes( - int rank, bool nontrivialType = false, int lengthTypeParameters = 0) { + int rank, bool addendum = false, int lengthTypeParameters = 0) { std::size_t bytes{sizeof(Descriptor) - sizeof(Dimension)}; bytes += rank * sizeof(Dimension); - if (nontrivialType || lengthTypeParameters > 0) { + if (addendum || lengthTypeParameters > 0) { bytes += DescriptorAddendum::SizeInBytes(lengthTypeParameters); } return bytes; @@ -209,25 +211,6 @@ public: } private: - // These values must coexist with the ISO_Fortran_binding.h definitions - // for CFI_attribute_... values and fit in the "attribute" field of - // CFI_cdesc_t, which is 16 bits wide. - enum AdditionalAttributes { - // non-pointer nonallocatable derived type component implemented as - // an implicit allocatable due to dependence on LEN type parameters - IMPLICITLY_ALLOCATED = 0x8, // bounds depend on LEN type parameter - ADDENDUM = 0x10, // last dim[] entry is followed by DescriptorAddendum - STATIC_DESCRIPTOR = 0x20, // base_addr is null, get base address elsewhere - TARGET = 0x40, // TARGET attribute; also implied by CFI_attribute_pointer - CONTIGUOUS = 0x80, - COLUMN_CONTIGUOUS = 0x100, // first dimension is contiguous - TEMPORARY = 0x200, // compiler temp, do not finalize - CREATED = 0x400, // was allocated by Descriptor::Create() - }; - - ISO::CFI_attribute_t &Attributes() { return raw_.attribute; } - const ISO::CFI_attribute_t &Attributes() const { return raw_.attribute; } - ISO::CFI_cdesc_t raw_; }; static_assert(sizeof(Descriptor) == sizeof(ISO::CFI_cdesc_t)); @@ -239,17 +222,15 @@ static_assert(sizeof(Descriptor) == sizeof(ISO::CFI_cdesc_t)); // extract a reference to the Descriptor via the descriptor() accessor, // and then built a Descriptor therein via descriptor.Establish(). // e.g.: -// StaticDescriptor statDesc; +// StaticDescriptor statDesc; // Descriptor &descriptor{statDesc.descriptor()}; // descriptor.Establish( ... ); -template +template class alignas(Descriptor) StaticDescriptor { 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}; + static constexpr bool hasAddendum{ADDENDUM || MAX_LEN_PARMS > 0}; static constexpr std::size_t byteSize{ Descriptor::SizeInBytes(maxRank, hasAddendum, maxLengthTypeParameters)}; -- 2.7.4