[flang] More descriptor work.

Original-commit: flang-compiler/f18@269cb52876
Reviewed-on: https://github.com/flang-compiler/f18/pull/92
This commit is contained in:
peter klausler 2018-05-17 11:32:23 -07:00
parent 588d36b2c6
commit 88e80408ae
3 changed files with 79 additions and 47 deletions

View File

@ -14,4 +14,5 @@
add_library(FortranRuntime
ISO_Fortran_binding.cc
descriptor.cc
)

View File

@ -18,36 +18,33 @@
namespace Fortran::runtime {
Descriptor::Descriptor(const DerivedType &t, int rank = 0) {
Descriptor::Descriptor(const DerivedTypeSpecialization &dts, int rank) {
raw_.base_addr = nullptr;
raw_.elem_len = t.SizeInBytes();
raw_.elem_len = dts.SizeInBytes();
raw_.version = CFI_VERSION;
raw_.rank = rank;
raw_.type = CFI_type_struct;
raw_.attribute = ADDENDUM;
new (GetAddendum()) DescriptorAddendum{t};
Addendum()->set_derivedTypeSpecialization(&dts);
}
std::size_t Descriptor::SizeInBytes() const {
const DescriptorAddendum *addendum{GetAddendum()};
const DescriptorAddendum *addendum{Addendum()};
return sizeof *this + raw_.rank * sizeof(Dimension) +
(addendum ? addendum->AddendumSizeInBytes() : 0);
(addendum ? addendum->SizeOfAddendumInBytes() : 0);
}
std::int64_t DerivedTypeParameter::Value(
const DescriptorAddendum *addendum) const {
if (isLenTypeParameter_) {
return addendum->GetLenParameterValue(value_);
} else {
return value_;
}
std::int64_t TypeParameter::KindParameterValue(
const DerivedTypeSpecialization &specialization) const {
return specialization.KindParameterValue(which_);
}
std::int64_t DerivedTypeParameter::Value(const Descriptor *descriptor) const {
std::int64_t TypeParameter::Value(const Descriptor &descriptor) const {
const DescriptorAddendum &addendum{*descriptor.Addendum()};
if (isLenTypeParameter_) {
return descriptor->GetAddendum()->GetLenTypeParameterValue(value_);
return addendum.LenParameterValue(which_);
} else {
return value_;
return KindParameterValue(*addendum.derivedTypeSpecialization());
}
}
} // namespace Fortran::runtime

View File

@ -16,13 +16,13 @@
#define FORTRAN_RUNTIME_DESCRIPTOR_H_
// Defines data structures used during execution of a Fortran program
// to implement pointers, allocatables, arguments, function results,
// and the special behaviors of instances of derived types.
// to implement nontrivial dummy arguments, pointers, allocatables,
// function results, and the special behaviors of instances of derived types.
// This header file includes and extends the published language
// interoperability header that is required by the Fortran 2018 standard
// as a subset of definitions suitable for exposure to user C/C++ code.
// User C code can depend on that ISO_Fortran_binding.h file, but should
// never reference this internal header.
// User C code is welcome to depend on that ISO_Fortran_binding.h file,
// but should never reference this internal header.
#include "../include/flang/ISO_Fortran_binding.h"
#include <cinttypes>
@ -31,16 +31,18 @@
namespace Fortran::runtime {
// Fortran requires that default INTEGER values occupy a single numeric
// storage unit, just like default REAL. So the default INTEGER type,
// which is what the type of an intrinsic type's KIND type parameter has,
// is basically forced to be a 32-bit int.
// storage unit, just like default REAL. Since there's no reasonable way
// that default REAL can be anything but 32-bit IEEE-754 today, the default
// INTEGER type is also forced; and default INTEGER is required to be the
// type of the kind type parameters of the intrinsic types.
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.
// This next section implements a C++ view of the sole interoperable
// descriptor (ISO_cdesc_t) and its type and per-dimension information.
class TypeCode {
public:
@ -102,8 +104,9 @@ public:
std::int64_t ByteStride() const { return raw_.sm; }
private:
ISO::CFI_dim_t raw_; // must be first and only member
ISO::CFI_dim_t raw_;
};
static_assert(sizeof(Dimension) == sizeof(ISO::CFI_dim_t));
class Descriptor {
public:
@ -134,25 +137,36 @@ public:
bool IsAllocatable() const {
return (raw_.attribute & CFI_attribute_allocatable) != 0;
}
bool IsLenParameterDependent() const {
return (raw_.attribute & LEN_PARAMETER_DEPENDENT) != 0;
bool IsImplicitlyAllocated() const {
return (raw_.attribute & IMPLICITLY_ALLOCATED) != 0;
}
bool IsStaticDescriptor() const {
bool IsDescriptorStatic() const {
return (raw_.attribute & STATIC_DESCRIPTOR) != 0;
}
bool IsTarget() const {
return (raw_.attribute & (CFI_attribute_pointer | TARGET)) != 0;
}
bool IsContiguous() const { return (raw_.attribute & CONTIGUOUS) != 0; }
bool IsNotFinalizable() const {
return (raw_.attribute & NOT_FINALIZABLE) != 0;
bool IsColumnContiguous() const {
return (raw_.attribute & COLUMN_CONTIGUOUS) != 0;
}
bool IsTemporary() const { return (raw_.attribute & TEMPORARY) != 0; }
Dimension &GetDimension(int dim) {
return *reinterpret_cast<Dimension *>(&raw_.dim[dim]);
}
const Dimension &GetDimension(int dim) const {
return *reinterpret_cast<const Dimension *>(&raw_.dim[dim]);
}
const DescriptorAddendum *GetAddendum() const {
DescriptorAddendum *Addendum() {
if ((raw_.attribute & ADDENDUM) != 0) {
return reinterpret_cast<DescriptorAddendum *>(&GetDimension(rank()));
} else {
return nullptr;
}
}
const DescriptorAddendum *Addendum() const {
if ((raw_.attribute & ADDENDUM) != 0) {
return reinterpret_cast<const DescriptorAddendum *>(
&GetDimension(rank()));
@ -165,22 +179,25 @@ public:
private:
// These values must coexist with the ISO_Fortran_binding.h definitions
// for CFI_attribute_...
// for CFI_attribute_... values and fit in the "attribute" field of
// CFI_cdesc_t.
enum AdditionalAttributes {
// non-pointer nonallocatable derived type component implemented as
// an implicit allocatable due to dependence on LEN type parameters
LEN_PARAMETER_DEPENDENT = 0x4, // implicitly allocated object
ADDENDUM = 0x8, // last dim[] entry is followed by DescriptorAddendum
STATIC_DESCRIPTOR = 0x10, // base_addr is null, get base address elsewhere
TARGET = 0x20, // TARGET attribute; also implied by CFI_attribute_pointer
CONTIGUOUS = 0x40,
NOT_FINALIZABLE = 0x80, // do not finalize, this is a compiler temp
IMPLICITLY_ALLOCATED = 0x100, // bounds depend on LEN type parameter
ADDENDUM = 0x200, // last dim[] entry is followed by DescriptorAddendum
STATIC_DESCRIPTOR = 0x400, // base_addr is null, get base address elsewhere
TARGET = 0x800, // TARGET attribute; also implied by CFI_attribute_pointer
CONTIGUOUS = 0x1000,
COLUMN_CONTIGUOUS = 0x2000, // first dimension is contiguous
TEMPORARY = 0x4000, // compiler temp, do not finalize
};
ISO::CFI_cdesc_t raw_; // must be first and only member
ISO::CFI_cdesc_t raw_;
};
static_assert(sizeof(Descriptor) == sizeof(ISO::CFI_cdesc_t));
// Static type information resides in a read-only section.
// Static type information is suitable for loading in a read-only section.
// Information about intrinsic types is inferable from raw CFI_type_t
// type codes (packaged as TypeCode above).
// Information about derived types and their KIND parameter specializations
@ -189,15 +206,19 @@ private:
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;
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_; }
std::int64_t KindParameterValue(const DerivedTypeSpecialization &) const;
std::int64_t Value(const Descriptor &) const;
private:
const char *name_;
TypeCode typeCode_; // not necessarily default INTEGER
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_;
};
@ -346,14 +367,16 @@ public:
: 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 {
const ComponentSpecialization &GetComponent(int n) const {
return componentSpecialization_[n];
}
bool IsSameType(const DerivedTypeSpecialization &);
bool IsSameType(const DerivedTypeSpecialization &) const;
// TODO: initialization
// TODO: sourced allocation initialization
@ -378,16 +401,27 @@ 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 GetLenParameterValue(std::size_t n) const { return len_[n]; }
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