2020-01-28 10:18:45 +08:00
|
|
|
//===-- runtime/descriptor.cpp --------------------------------------------===//
|
2018-05-17 01:22:33 +08:00
|
|
|
//
|
2019-12-21 04:52:07 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2018-05-17 01:22:33 +08:00
|
|
|
//
|
2020-01-11 04:12:03 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2018-05-17 01:22:33 +08:00
|
|
|
|
|
|
|
#include "descriptor.h"
|
2020-12-08 06:46:24 +08:00
|
|
|
#include "derived.h"
|
2020-02-14 06:41:56 +08:00
|
|
|
#include "memory.h"
|
|
|
|
#include "terminator.h"
|
2020-12-08 06:46:24 +08:00
|
|
|
#include "type-info.h"
|
2018-08-01 07:46:30 +08:00
|
|
|
#include <cassert>
|
2018-07-27 07:07:50 +08:00
|
|
|
#include <cstdlib>
|
2020-02-05 08:55:45 +08:00
|
|
|
#include <cstring>
|
2018-05-17 01:22:33 +08:00
|
|
|
|
|
|
|
namespace Fortran::runtime {
|
|
|
|
|
2020-02-05 08:55:45 +08:00
|
|
|
Descriptor::Descriptor(const Descriptor &that) {
|
|
|
|
std::memcpy(this, &that, that.SizeInBytes());
|
|
|
|
}
|
|
|
|
|
2018-08-02 01:55:46 +08:00
|
|
|
Descriptor::~Descriptor() {
|
2018-08-03 08:04:31 +08:00
|
|
|
if (raw_.attribute != CFI_attribute_pointer) {
|
|
|
|
Deallocate();
|
|
|
|
}
|
2018-08-02 01:55:46 +08:00
|
|
|
}
|
2018-07-27 07:07:50 +08:00
|
|
|
|
2018-08-03 02:45:11 +08:00
|
|
|
void Descriptor::Establish(TypeCode t, std::size_t elementBytes, void *p,
|
2018-08-02 01:55:46 +08:00
|
|
|
int rank, const SubscriptValue *extent, ISO::CFI_attribute_t attribute,
|
|
|
|
bool addendum) {
|
2020-02-14 06:41:56 +08:00
|
|
|
Terminator terminator{__FILE__, __LINE__};
|
2021-03-26 02:03:32 +08:00
|
|
|
// Subtle: the standard CFI_establish() function doesn't allow a zero
|
|
|
|
// elem_len argument in cases where elem_len is not ignored; and when it
|
|
|
|
// returns an error code (CFI_INVALID_ELEM_LEN in this case), it must not
|
|
|
|
// modify the descriptor. That design makes sense, maybe, for actual
|
|
|
|
// C interoperability, but we need to work around it here. A zero
|
|
|
|
// incoming element length is replaced by 4 so that it will be valid
|
|
|
|
// for all CHARACTER kinds.
|
|
|
|
std::size_t workaroundElemLen{elementBytes ? elementBytes : 4};
|
2020-02-14 06:41:56 +08:00
|
|
|
RUNTIME_CHECK(terminator,
|
2021-03-26 02:03:32 +08:00
|
|
|
ISO::CFI_establish(&raw_, p, attribute, t.raw(), workaroundElemLen, rank,
|
2020-02-14 06:41:56 +08:00
|
|
|
extent) == CFI_SUCCESS);
|
2021-03-26 02:03:32 +08:00
|
|
|
if (elementBytes == 0) {
|
|
|
|
raw_.elem_len = 0;
|
|
|
|
for (int j{0}; j < rank; ++j) {
|
|
|
|
GetDimension(j).SetByteStride(0);
|
|
|
|
}
|
|
|
|
}
|
2018-08-02 01:55:46 +08:00
|
|
|
raw_.f18Addendum = addendum;
|
2018-08-07 00:43:43 +08:00
|
|
|
DescriptorAddendum *a{Addendum()};
|
2020-02-14 06:41:56 +08:00
|
|
|
RUNTIME_CHECK(terminator, addendum == (a != nullptr));
|
2018-08-07 00:43:43 +08:00
|
|
|
if (a) {
|
|
|
|
new (a) DescriptorAddendum{};
|
2018-08-03 02:45:11 +08:00
|
|
|
}
|
2018-07-27 07:07:50 +08:00
|
|
|
}
|
|
|
|
|
2018-08-03 02:45:11 +08:00
|
|
|
void Descriptor::Establish(TypeCategory c, int kind, void *p, int rank,
|
2018-08-02 01:55:46 +08:00
|
|
|
const SubscriptValue *extent, ISO::CFI_attribute_t attribute,
|
|
|
|
bool addendum) {
|
[flang] More Fortran runtime support for CHARACTER operations
Summary:
- Remove C++ library dependence from lock.h
- Implement LEN_TRIM, REPEAT, ADJUSTL, ADJUSTR, MAX/MIN
intrinsic functions for CHARACTER
Reviewers: tskeith, PeteSteinfeld, sscalpone, schweitz, DavidTruby
Reviewed By: PeteSteinfeld
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D82054
2020-06-18 04:17:24 +08:00
|
|
|
Establish(TypeCode(c, kind), BytesFor(c, kind), p, rank, extent, attribute,
|
|
|
|
addendum);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Descriptor::Establish(int characterKind, std::size_t characters, void *p,
|
|
|
|
int rank, const SubscriptValue *extent, ISO::CFI_attribute_t attribute,
|
|
|
|
bool addendum) {
|
|
|
|
Establish(TypeCode{TypeCategory::Character, characterKind},
|
|
|
|
characterKind * characters, p, rank, extent, attribute, addendum);
|
2018-05-17 01:22:33 +08:00
|
|
|
}
|
|
|
|
|
2020-12-08 06:46:24 +08:00
|
|
|
void Descriptor::Establish(const typeInfo::DerivedType &dt, void *p, int rank,
|
2018-08-02 01:55:46 +08:00
|
|
|
const SubscriptValue *extent, ISO::CFI_attribute_t attribute) {
|
2020-12-08 06:46:24 +08:00
|
|
|
Establish(CFI_type_struct, dt.sizeInBytes, p, rank, extent, attribute, true);
|
2018-08-07 00:43:43 +08:00
|
|
|
DescriptorAddendum *a{Addendum()};
|
[flang] More Fortran runtime support for CHARACTER operations
Summary:
- Remove C++ library dependence from lock.h
- Implement LEN_TRIM, REPEAT, ADJUSTL, ADJUSTR, MAX/MIN
intrinsic functions for CHARACTER
Reviewers: tskeith, PeteSteinfeld, sscalpone, schweitz, DavidTruby
Reviewed By: PeteSteinfeld
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D82054
2020-06-18 04:17:24 +08:00
|
|
|
Terminator terminator{__FILE__, __LINE__};
|
|
|
|
RUNTIME_CHECK(terminator, a != nullptr);
|
2018-08-07 00:43:43 +08:00
|
|
|
new (a) DescriptorAddendum{&dt};
|
2018-07-27 07:07:50 +08:00
|
|
|
}
|
|
|
|
|
2020-02-14 06:41:56 +08:00
|
|
|
OwningPtr<Descriptor> Descriptor::Create(TypeCode t, std::size_t elementBytes,
|
|
|
|
void *p, int rank, const SubscriptValue *extent,
|
[flang] More Fortran runtime support for CHARACTER operations
Summary:
- Remove C++ library dependence from lock.h
- Implement LEN_TRIM, REPEAT, ADJUSTL, ADJUSTR, MAX/MIN
intrinsic functions for CHARACTER
Reviewers: tskeith, PeteSteinfeld, sscalpone, schweitz, DavidTruby
Reviewed By: PeteSteinfeld
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D82054
2020-06-18 04:17:24 +08:00
|
|
|
ISO::CFI_attribute_t attribute, int derivedTypeLenParameters) {
|
|
|
|
std::size_t bytes{SizeInBytes(rank, true, derivedTypeLenParameters)};
|
2020-02-14 06:41:56 +08:00
|
|
|
Terminator terminator{__FILE__, __LINE__};
|
|
|
|
Descriptor *result{
|
|
|
|
reinterpret_cast<Descriptor *>(AllocateMemoryOrCrash(terminator, bytes))};
|
2018-08-02 01:55:46 +08:00
|
|
|
result->Establish(t, elementBytes, p, rank, extent, attribute, true);
|
2020-02-14 06:41:56 +08:00
|
|
|
return OwningPtr<Descriptor>{result};
|
2018-07-27 07:07:50 +08:00
|
|
|
}
|
|
|
|
|
2020-02-14 06:41:56 +08:00
|
|
|
OwningPtr<Descriptor> Descriptor::Create(TypeCategory c, int kind, void *p,
|
|
|
|
int rank, const SubscriptValue *extent, ISO::CFI_attribute_t attribute) {
|
[flang] More Fortran runtime support for CHARACTER operations
Summary:
- Remove C++ library dependence from lock.h
- Implement LEN_TRIM, REPEAT, ADJUSTL, ADJUSTR, MAX/MIN
intrinsic functions for CHARACTER
Reviewers: tskeith, PeteSteinfeld, sscalpone, schweitz, DavidTruby
Reviewed By: PeteSteinfeld
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D82054
2020-06-18 04:17:24 +08:00
|
|
|
return Create(
|
|
|
|
TypeCode(c, kind), BytesFor(c, kind), p, rank, extent, attribute);
|
|
|
|
}
|
|
|
|
|
|
|
|
OwningPtr<Descriptor> Descriptor::Create(int characterKind,
|
|
|
|
SubscriptValue characters, void *p, int rank, const SubscriptValue *extent,
|
|
|
|
ISO::CFI_attribute_t attribute) {
|
|
|
|
return Create(TypeCode{TypeCategory::Character, characterKind},
|
|
|
|
characterKind * characters, p, rank, extent, attribute);
|
2018-07-27 07:07:50 +08:00
|
|
|
}
|
|
|
|
|
2020-12-08 06:46:24 +08:00
|
|
|
OwningPtr<Descriptor> Descriptor::Create(const typeInfo::DerivedType &dt,
|
|
|
|
void *p, int rank, const SubscriptValue *extent,
|
|
|
|
ISO::CFI_attribute_t attribute) {
|
|
|
|
return Create(TypeCode{CFI_type_struct}, dt.sizeInBytes, p, rank, extent,
|
|
|
|
attribute, dt.LenParameters());
|
2018-08-01 07:46:30 +08:00
|
|
|
}
|
2018-07-28 07:52:17 +08:00
|
|
|
|
|
|
|
std::size_t Descriptor::SizeInBytes() const {
|
|
|
|
const DescriptorAddendum *addendum{Addendum()};
|
|
|
|
return sizeof *this - sizeof(Dimension) + raw_.rank * sizeof(Dimension) +
|
|
|
|
(addendum ? addendum->SizeInBytes() : 0);
|
2018-05-17 01:22:33 +08:00
|
|
|
}
|
|
|
|
|
2018-08-03 02:45:11 +08:00
|
|
|
std::size_t Descriptor::Elements() const {
|
|
|
|
int n{rank()};
|
|
|
|
std::size_t elements{1};
|
|
|
|
for (int j{0}; j < n; ++j) {
|
|
|
|
elements *= GetDimension(j).Extent();
|
|
|
|
}
|
|
|
|
return elements;
|
|
|
|
}
|
|
|
|
|
2020-11-11 07:13:02 +08:00
|
|
|
int Descriptor::Allocate() {
|
|
|
|
std::size_t byteSize{Elements() * ElementBytes()};
|
|
|
|
void *p{std::malloc(byteSize)};
|
|
|
|
if (!p && byteSize) {
|
|
|
|
return CFI_ERROR_MEM_ALLOCATION;
|
|
|
|
}
|
|
|
|
// TODO: image synchronization
|
|
|
|
// TODO: derived type initialization
|
|
|
|
raw_.base_addr = p;
|
|
|
|
if (int dims{rank()}) {
|
|
|
|
std::size_t stride{ElementBytes()};
|
|
|
|
for (int j{0}; j < dims; ++j) {
|
|
|
|
auto &dimension{GetDimension(j)};
|
|
|
|
dimension.SetByteStride(stride);
|
|
|
|
stride *= dimension.Extent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
[flang] More Fortran runtime support for CHARACTER operations
Summary:
- Remove C++ library dependence from lock.h
- Implement LEN_TRIM, REPEAT, ADJUSTL, ADJUSTR, MAX/MIN
intrinsic functions for CHARACTER
Reviewers: tskeith, PeteSteinfeld, sscalpone, schweitz, DavidTruby
Reviewed By: PeteSteinfeld
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D82054
2020-06-18 04:17:24 +08:00
|
|
|
int Descriptor::Allocate(const SubscriptValue lb[], const SubscriptValue ub[]) {
|
|
|
|
int result{ISO::CFI_allocate(&raw_, lb, ub, ElementBytes())};
|
2018-08-03 08:04:31 +08:00
|
|
|
if (result == CFI_SUCCESS) {
|
|
|
|
// TODO: derived type initialization
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Descriptor::Deallocate(bool finalize) {
|
2020-12-08 06:46:24 +08:00
|
|
|
Destroy(finalize);
|
2018-08-03 08:04:31 +08:00
|
|
|
return ISO::CFI_deallocate(&raw_);
|
|
|
|
}
|
|
|
|
|
2020-12-08 06:46:24 +08:00
|
|
|
void Descriptor::Destroy(bool finalize) const {
|
|
|
|
if (const DescriptorAddendum * addendum{Addendum()}) {
|
|
|
|
if (const typeInfo::DerivedType * dt{addendum->derivedType()}) {
|
2018-08-03 08:04:31 +08:00
|
|
|
if (addendum->flags() & DescriptorAddendum::DoNotFinalize) {
|
|
|
|
finalize = false;
|
|
|
|
}
|
2020-12-08 06:46:24 +08:00
|
|
|
runtime::Destroy(*this, finalize, *dt);
|
2018-08-03 08:04:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-14 06:41:56 +08:00
|
|
|
bool Descriptor::IncrementSubscripts(
|
|
|
|
SubscriptValue *subscript, const int *permutation) const {
|
|
|
|
for (int j{0}; j < raw_.rank; ++j) {
|
|
|
|
int k{permutation ? permutation[j] : j};
|
|
|
|
const Dimension &dim{GetDimension(k)};
|
|
|
|
if (subscript[k]++ < dim.UpperBound()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
subscript[k] = dim.LowerBound();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Descriptor::DecrementSubscripts(
|
|
|
|
SubscriptValue *subscript, const int *permutation) const {
|
|
|
|
for (int j{raw_.rank - 1}; j >= 0; --j) {
|
|
|
|
int k{permutation ? permutation[j] : j};
|
|
|
|
const Dimension &dim{GetDimension(k)};
|
|
|
|
if (--subscript[k] >= dim.LowerBound()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
subscript[k] = dim.UpperBound();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t Descriptor::ZeroBasedElementNumber(
|
|
|
|
const SubscriptValue *subscript, const int *permutation) const {
|
|
|
|
std::size_t result{0};
|
|
|
|
std::size_t coefficient{1};
|
|
|
|
for (int j{0}; j < raw_.rank; ++j) {
|
|
|
|
int k{permutation ? permutation[j] : j};
|
|
|
|
const Dimension &dim{GetDimension(k)};
|
|
|
|
result += coefficient * (subscript[k] - dim.LowerBound());
|
|
|
|
coefficient *= dim.Extent();
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Descriptor::SubscriptsForZeroBasedElementNumber(SubscriptValue *subscript,
|
|
|
|
std::size_t elementNumber, const int *permutation) const {
|
|
|
|
std::size_t coefficient{1};
|
|
|
|
std::size_t dimCoefficient[maxRank];
|
|
|
|
for (int j{0}; j < raw_.rank; ++j) {
|
|
|
|
int k{permutation ? permutation[j] : j};
|
|
|
|
const Dimension &dim{GetDimension(k)};
|
|
|
|
dimCoefficient[j] = coefficient;
|
|
|
|
coefficient *= dim.Extent();
|
|
|
|
}
|
|
|
|
if (elementNumber >= coefficient) {
|
2020-03-29 12:00:16 +08:00
|
|
|
return false; // out of range
|
2020-02-14 06:41:56 +08:00
|
|
|
}
|
|
|
|
for (int j{raw_.rank - 1}; j >= 0; --j) {
|
|
|
|
int k{permutation ? permutation[j] : j};
|
|
|
|
const Dimension &dim{GetDimension(k)};
|
|
|
|
std::size_t quotient{j ? elementNumber / dimCoefficient[j] : 0};
|
|
|
|
subscript[k] =
|
|
|
|
dim.LowerBound() + elementNumber - dimCoefficient[j] * quotient;
|
|
|
|
elementNumber = quotient;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-08-01 07:46:30 +08:00
|
|
|
void Descriptor::Check() const {
|
|
|
|
// TODO
|
2018-05-17 01:22:33 +08:00
|
|
|
}
|
2018-07-27 07:07:50 +08:00
|
|
|
|
2020-02-14 06:41:56 +08:00
|
|
|
void Descriptor::Dump(FILE *f) const {
|
|
|
|
std::fprintf(f, "Descriptor @ %p:\n", reinterpret_cast<const void *>(this));
|
|
|
|
std::fprintf(f, " base_addr %p\n", raw_.base_addr);
|
|
|
|
std::fprintf(f, " elem_len %zd\n", static_cast<std::size_t>(raw_.elem_len));
|
|
|
|
std::fprintf(f, " version %d\n", static_cast<int>(raw_.version));
|
|
|
|
std::fprintf(f, " rank %d\n", static_cast<int>(raw_.rank));
|
|
|
|
std::fprintf(f, " type %d\n", static_cast<int>(raw_.type));
|
|
|
|
std::fprintf(f, " attribute %d\n", static_cast<int>(raw_.attribute));
|
|
|
|
std::fprintf(f, " addendum %d\n", static_cast<int>(raw_.f18Addendum));
|
2018-08-03 08:04:31 +08:00
|
|
|
for (int j{0}; j < raw_.rank; ++j) {
|
2020-02-14 06:41:56 +08:00
|
|
|
std::fprintf(f, " dim[%d] lower_bound %jd\n", j,
|
|
|
|
static_cast<std::intmax_t>(raw_.dim[j].lower_bound));
|
|
|
|
std::fprintf(f, " extent %jd\n",
|
|
|
|
static_cast<std::intmax_t>(raw_.dim[j].extent));
|
|
|
|
std::fprintf(f, " sm %jd\n",
|
|
|
|
static_cast<std::intmax_t>(raw_.dim[j].sm));
|
2018-08-03 08:04:31 +08:00
|
|
|
}
|
|
|
|
if (const DescriptorAddendum * addendum{Addendum()}) {
|
2020-02-14 06:41:56 +08:00
|
|
|
addendum->Dump(f);
|
2018-08-03 08:04:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-01 07:46:30 +08:00
|
|
|
std::size_t DescriptorAddendum::SizeInBytes() const {
|
2018-08-03 02:45:11 +08:00
|
|
|
return SizeInBytes(LenParameters());
|
2018-07-27 07:07:50 +08:00
|
|
|
}
|
2018-08-03 08:04:31 +08:00
|
|
|
|
2020-12-08 06:46:24 +08:00
|
|
|
std::size_t DescriptorAddendum::LenParameters() const {
|
|
|
|
const auto *type{derivedType()};
|
|
|
|
return type ? type->LenParameters() : 0;
|
|
|
|
}
|
|
|
|
|
2020-02-14 06:41:56 +08:00
|
|
|
void DescriptorAddendum::Dump(FILE *f) const {
|
|
|
|
std::fprintf(
|
|
|
|
f, " derivedType @ %p\n", reinterpret_cast<const void *>(derivedType_));
|
|
|
|
std::fprintf(f, " flags 0x%jx\n", static_cast<std::intmax_t>(flags_));
|
2018-08-03 08:04:31 +08:00
|
|
|
// TODO: LEN parameter values
|
|
|
|
}
|
2020-03-29 12:00:16 +08:00
|
|
|
} // namespace Fortran::runtime
|