From 7b542380a3a9dde11a8cd5ac5d6566e6eca81149 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Wed, 16 May 2018 16:17:09 -0700 Subject: [PATCH] [flang] Separate generic from specialized parts of derived types and their components. Original-commit: flang-compiler/f18@b578f607bebcee5b75703cbe04d7e8e5ddebe077 Reviewed-on: https://github.com/flang-compiler/f18/pull/92 Tree-same-pre-rewrite: false --- flang/runtime/descriptor.h | 162 ++++++++++++++++++++++++++++++--------------- 1 file changed, 110 insertions(+), 52 deletions(-) diff --git a/flang/runtime/descriptor.h b/flang/runtime/descriptor.h index d2fb602..51b1e79 100644 --- a/flang/runtime/descriptor.h +++ b/flang/runtime/descriptor.h @@ -37,6 +37,7 @@ namespace Fortran::runtime { using DefaultKindInteger = std::int32_t; class DerivedType; +class DerivedTypeSpecialization; class DescriptorAddendum; // A C++ view of the ISO descriptor and its type and per-dimension information. @@ -114,7 +115,7 @@ public: raw_.type = t.raw(); raw_.attribute = 0; } - Descriptor(const DerivedType &, int rank = 0); + Descriptor(const DerivedTypeSpecialization &, int rank = 0); void Check() const; @@ -185,18 +186,19 @@ private: // Information about derived types and their KIND parameter specializations // appears in the compiled program units that define or specialize the types. -class DerivedTypeParameter { +class TypeParameter { public: const char *name() const { return name_; } const TypeCode type() const { return typeCode_; } std::int64_t Value(const DescriptorAddendum *) const; std::int64_t Value(const Descriptor *) const; + std::int64_t Value(const DerivedTypeSpecialization *) const; private: const char *name_; TypeCode typeCode_; // not necessarily default INTEGER - bool isLenTypeParameter_; // if true, value is in dynamic descriptor - std::int64_t value_; // truncated to type then sign-extended + bool isLenTypeParameter_; // whether value is in dynamic descriptor + std::int64_t defaultValue_; }; // Components that have any need for a descriptor will either reference @@ -211,36 +213,25 @@ private: class Component { public: const char *name() const { return name_; } - template A *Locate(char *instance) const { - return reinterpret_cast(instance + offset_); - } - template const A *Locate(const char *instance) const { - return reinterpret_cast(instance + offset_); - } TypeCode typeCode() const { return typeCode_; } + const Descriptor *staticDescriptor() const { return staticDescriptor_; } + bool IsParent() const { return (flags_ & PARENT) != 0; } bool IsPrivate() const { return (flags_ & PRIVATE) != 0; } - const Descriptor *GetDescriptor(const char *instance) const { - if (staticDescriptor_ != nullptr) { - return staticDescriptor_; - } else if ((flags_ & IS_DESCRIPTOR) != 0) { - return Locate(instance); - } else { - return nullptr; - } - } + bool IsDescriptor() const { return (flags_ & IS_DESCRIPTOR) != 0; } private: - enum Flag { PRIVATE = 1, IS_DESCRIPTOR = 2 }; - + enum Flag { PARENT = 1, PRIVATE = 2, IS_DESCRIPTOR = 4 }; const char *name_{nullptr}; - std::size_t offset_{0}; // relative to start of derived type instance std::uint32_t flags_{0}; TypeCode typeCode_{CFI_type_other}; const Descriptor *staticDescriptor_{nullptr}; }; struct ExecutableCode { - std::intptr_t host, device; + ExecutableCode() {} + ExecutableCode(const ExecutableCode &) = default; + std::intptr_t host{0}; + std::intptr_t device{0}; }; struct TypeBoundProcedure { @@ -253,53 +244,116 @@ struct ProcedurePointer { void *staticLink; }; -// This static representation of a derived type specialization includes -// the values of all its KIND type parameters, and reflects those values -// in the values of array bounds and static derived type descriptors that -// appear in the static descriptors of the components. +// This static description of a derived type is not specialized by +// the values of kind type parameters. All specializations share +// this information. // Extended derived types have the EXTENDS flag set and place their base // component first in the component descriptions, which is significant for // 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, const ExecutableCode &a) + : name_{n}, kindParameters_{kps}, lenParameters_{lps}, components_{cs}, + typeParameter_{tp}, typeBoundProcedure_{tbp}, assignment_{a} {} + const char *name() const { return name_; } - std::size_t SizeInBytes() const { return bytes_; } - const char *initializer() const { return initializer_; } std::size_t kindParameters() const { return kindParameters_; } - const DerivedTypeParameter &kindParameter(int n) const { - return kindParameter_[n]; - } std::size_t lenParameters() const { return lenParameters_; } + const TypeParameter &typeParameter(int n) const { return typeParameter_[n]; } std::size_t components() const { return components_; } - const Component &component(int n) const { return component_[n]; } std::size_t typeBoundProcedures() const { return typeBoundProcedures_; } - const ExecutableCode &typeBoundProcedure(int n) const { + const TypeBoundProcedure &typeBoundProcedure(int n) const { return typeBoundProcedure_[n]; } - bool IsSameType(const DerivedType &); - // TODO: default initialization - // TODO: sourced allocation initialization + DerivedType &set_sequence() { + flags_ |= SEQUENCE; + return *this; + } + DerivedType &set_bind_c() { + flags_ |= BIND_C; + return *this; + } + + bool Extends() const { return components_ > 0 && component_[0].IsParent(); } + bool AnyPrivate() const; + bool IsSequence() const { return (flags_ & SEQUENCE) != 0; } + bool IsBindC() const { return (flags_ & BIND_C) != 0; } + // TODO: assignment // TODO: finalization private: - enum Flag { EXTENDS = 1, SEQUENCE = 2, BIND = 4, ANY_PRIVATE = 8 }; + enum Flag { SEQUENCE = 1, BIND_C = 2 }; const char *name_; // NUL-terminated constant text - std::size_t bytes_; // allocation size of one scalar instance, w/ alignment - std::uint64_t flags_; // needed for IsSameType() correct semantics - const char *initializer_; // can be null; includes base components + std::uint64_t flags_{0}; // needed for IsSameType() correct semantics std::size_t kindParameters_; - const DerivedTypeParameter *kindParameter_; // array - std::size_t lenParameters_; // count only; values are in descriptor + std::size_t lenParameters_; std::size_t components_; // *not* including type parameters - const Component *component_; // array std::size_t typeBoundProcedures_; - const ExecutableCode + const TypeParameter *typeParameter_; // array + const Component *component_; // array + const TypeBoundProcedure *typeBoundProcedure_; // array of overridable TBP bindings - ExecutableCode finalSubroutine_; // resolved at compilation, can be null - ExecutableCode assignment_; // resolved at compilation, must not be null + ExecutableCode finalSubroutine_; // can be null + ExecutableCode assignment_; // must not be null +}; + +class ComponentSpecialization { +public: + template A *Locate(char *instance) const { + return reinterpret_cast(instance + offset_); + } + template const A *Locate(const char *instance) const { + return reinterpret_cast(instance + offset_); + } + const Descriptor *GetDescriptor( + const Component &c, const char *instance) const { + if (const Descriptor * staticDescriptor{c.staticDescriptor()}) { + return staticDescriptor; + } else if (c.IsDescriptor()) { + return Locate(instance); + } else { + return nullptr; + } + } + +private: + std::size_t offset_{0}; // relative to start of derived type instance +}; + +// This static representation of a derived type specialization includes +// the values of all its KIND type parameters, and reflects those values +// in the values of array bounds and static derived type descriptors that +// appear in the static descriptors of the components. +class DerivedTypeSpecialization { +public: + DerivedTypeSpecialization(const DerivedType &dt, std::size_t n, + const char *init, const std::int64_t *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 { + return kindParameterValue_[n]; + } + const ComponentSpecialization &componentSpecialization(int n) const { + return componentSpecialization_[n]; + } + bool IsSameType(const DerivedTypeSpecialization &); + // TODO: initialization + // TODO: sourced allocation initialization + +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 ComponentSpecialization *componentSpecialization_; // array }; // The storage for this object follows the last used dim[] entry in a @@ -309,20 +363,24 @@ private: // 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(). +// DerivedType::lenParameters(). class DescriptorAddendum { public: - explicit DescriptorAddendum(const DerivedType *dt) : derivedType_{dt} {} + explicit DescriptorAddendum(const DerivedTypeSpecialization *dts) + : derivedTypeSpecialization_{dts} {} - const DerivedType *derivedType() const { return derivedType_; } + const DerivedTypeSpecialization *derivedTypeSpecialization() const { + return derivedTypeSpecialization_; + } std::int64_t GetLenParameterValue(std::size_t n) const { return len_[n]; } std::size_t SizeOfAddendumInBytes() const { return sizeof *this - sizeof len_[0] + - derivedType_->lenParameters() * sizeof len_[0]; + derivedTypeSpecialization_->derivedType().lenParameters() * + sizeof len_[0]; } private: - const DerivedType *derivedType_{nullptr}; + 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 -- 2.7.4