2021-05-20 10:37:03 -07:00
|
|
|
//===-- runtime/allocatable.cpp -------------------------------------------===//
|
2020-03-30 16:37:30 -07: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
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
2021-09-01 16:00:53 -07:00
|
|
|
#include "flang/Runtime/allocatable.h"
|
2023-02-01 15:25:54 -08:00
|
|
|
#include "assign-impl.h"
|
2021-07-19 11:53:20 -07:00
|
|
|
#include "derived.h"
|
2020-11-10 15:13:02 -08:00
|
|
|
#include "stat.h"
|
2020-03-30 16:37:30 -07:00
|
|
|
#include "terminator.h"
|
2021-07-19 11:53:20 -07:00
|
|
|
#include "type-info.h"
|
2023-08-22 18:13:04 -07:00
|
|
|
#include "flang/ISO_Fortran_binding_wrapper.h"
|
2023-01-09 15:13:58 +00:00
|
|
|
#include "flang/Runtime/assign.h"
|
|
|
|
|
#include "flang/Runtime/descriptor.h"
|
2020-03-30 16:37:30 -07:00
|
|
|
|
|
|
|
|
namespace Fortran::runtime {
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
2020-11-10 15:13:02 -08:00
|
|
|
void RTNAME(AllocatableInitIntrinsic)(Descriptor &descriptor,
|
|
|
|
|
TypeCategory category, int kind, int rank, int corank) {
|
|
|
|
|
INTERNAL_CHECK(corank == 0);
|
|
|
|
|
descriptor.Establish(TypeCode{category, kind},
|
|
|
|
|
Descriptor::BytesFor(category, kind), nullptr, rank, nullptr,
|
|
|
|
|
CFI_attribute_allocatable);
|
2020-03-30 16:37:30 -07:00
|
|
|
}
|
|
|
|
|
|
2020-11-10 15:13:02 -08:00
|
|
|
void RTNAME(AllocatableInitCharacter)(Descriptor &descriptor,
|
|
|
|
|
SubscriptValue length, int kind, int rank, int corank) {
|
|
|
|
|
INTERNAL_CHECK(corank == 0);
|
|
|
|
|
descriptor.Establish(
|
|
|
|
|
kind, length, nullptr, rank, nullptr, CFI_attribute_allocatable);
|
2020-03-30 16:37:30 -07:00
|
|
|
}
|
|
|
|
|
|
2020-11-10 15:13:02 -08:00
|
|
|
void RTNAME(AllocatableInitDerived)(Descriptor &descriptor,
|
2020-12-07 14:46:24 -08:00
|
|
|
const typeInfo::DerivedType &derivedType, int rank, int corank) {
|
2020-11-10 15:13:02 -08:00
|
|
|
INTERNAL_CHECK(corank == 0);
|
|
|
|
|
descriptor.Establish(
|
|
|
|
|
derivedType, nullptr, rank, nullptr, CFI_attribute_allocatable);
|
2020-03-30 16:37:30 -07:00
|
|
|
}
|
|
|
|
|
|
2023-03-20 10:00:08 +01:00
|
|
|
void RTNAME(AllocatableInitIntrinsicForAllocate)(Descriptor &descriptor,
|
|
|
|
|
TypeCategory category, int kind, int rank, int corank) {
|
|
|
|
|
if (descriptor.IsAllocated()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
RTNAME(AllocatableInitIntrinsic)(descriptor, category, kind, rank, corank);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTNAME(AllocatableInitCharacterForAllocate)(Descriptor &descriptor,
|
|
|
|
|
SubscriptValue length, int kind, int rank, int corank) {
|
|
|
|
|
if (descriptor.IsAllocated()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
RTNAME(AllocatableInitCharacter)(descriptor, length, kind, rank, corank);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTNAME(AllocatableInitDerivedForAllocate)(Descriptor &descriptor,
|
|
|
|
|
const typeInfo::DerivedType &derivedType, int rank, int corank) {
|
|
|
|
|
if (descriptor.IsAllocated()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
RTNAME(AllocatableInitDerived)(descriptor, derivedType, rank, corank);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-01 09:44:39 +01:00
|
|
|
std::int32_t RTNAME(MoveAlloc)(Descriptor &to, Descriptor &from,
|
|
|
|
|
const typeInfo::DerivedType *derivedType, bool hasStat,
|
2023-01-09 15:13:58 +00:00
|
|
|
const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
|
|
|
|
|
Terminator terminator{sourceFile, sourceLine};
|
|
|
|
|
|
|
|
|
|
// If to and from are the same allocatable they must not be allocated
|
|
|
|
|
// and nothing should be done.
|
|
|
|
|
if (from.raw().base_addr == to.raw().base_addr && from.IsAllocated()) {
|
2023-01-30 15:48:45 +00:00
|
|
|
return ReturnError(
|
|
|
|
|
terminator, StatMoveAllocSameAllocatable, errMsg, hasStat);
|
2023-01-09 15:13:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (to.IsAllocated()) {
|
2023-07-29 08:34:14 -07:00
|
|
|
int stat{
|
|
|
|
|
to.Destroy(/*finalize=*/true, /*destroyPointers=*/false, &terminator)};
|
2023-01-09 15:13:58 +00:00
|
|
|
if (stat != StatOk) {
|
|
|
|
|
return ReturnError(terminator, stat, errMsg, hasStat);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If from isn't allocated, the standard defines that nothing should be done.
|
|
|
|
|
if (from.IsAllocated()) {
|
|
|
|
|
to = from;
|
|
|
|
|
from.raw().base_addr = nullptr;
|
2023-03-01 09:44:39 +01:00
|
|
|
|
|
|
|
|
// Carry over the dynamic type.
|
|
|
|
|
if (auto *toAddendum{to.Addendum()}) {
|
|
|
|
|
if (const auto *fromAddendum{from.Addendum()}) {
|
|
|
|
|
if (const auto *derived{fromAddendum->derivedType()}) {
|
|
|
|
|
toAddendum->set_derivedType(derived);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reset from dynamic type if needed.
|
|
|
|
|
if (auto *fromAddendum{from.Addendum()}) {
|
|
|
|
|
if (derivedType) {
|
|
|
|
|
fromAddendum->set_derivedType(derivedType);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-09 15:13:58 +00:00
|
|
|
}
|
2023-03-01 09:44:39 +01:00
|
|
|
|
2020-11-10 15:13:02 -08:00
|
|
|
return StatOk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTNAME(AllocatableSetBounds)(Descriptor &descriptor, int zeroBasedDim,
|
|
|
|
|
SubscriptValue lower, SubscriptValue upper) {
|
|
|
|
|
INTERNAL_CHECK(zeroBasedDim >= 0 && zeroBasedDim < descriptor.rank());
|
|
|
|
|
descriptor.GetDimension(zeroBasedDim).SetBounds(lower, upper);
|
|
|
|
|
// The byte strides are computed when the object is allocated.
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-16 10:42:17 -07:00
|
|
|
void RTNAME(AllocatableSetDerivedLength)(
|
|
|
|
|
Descriptor &descriptor, int which, SubscriptValue x) {
|
|
|
|
|
DescriptorAddendum *addendum{descriptor.Addendum()};
|
|
|
|
|
INTERNAL_CHECK(addendum != nullptr);
|
|
|
|
|
addendum->SetLenParameterValue(which, x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTNAME(AllocatableApplyMold)(
|
2023-02-02 10:23:06 +01:00
|
|
|
Descriptor &descriptor, const Descriptor &mold, int rank) {
|
2023-01-17 15:51:04 +01:00
|
|
|
if (descriptor.IsAllocated()) {
|
|
|
|
|
// 9.7.1.3 Return so the error can be emitted by AllocatableAllocate.
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-10-17 08:20:38 -07:00
|
|
|
descriptor.ApplyMold(mold, rank);
|
2021-07-16 10:42:17 -07:00
|
|
|
}
|
|
|
|
|
|
2020-11-10 15:13:02 -08:00
|
|
|
int RTNAME(AllocatableAllocate)(Descriptor &descriptor, bool hasStat,
|
2021-03-12 13:33:50 -08:00
|
|
|
const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
|
2020-11-10 15:13:02 -08:00
|
|
|
Terminator terminator{sourceFile, sourceLine};
|
|
|
|
|
if (!descriptor.IsAllocatable()) {
|
|
|
|
|
return ReturnError(terminator, StatInvalidDescriptor, errMsg, hasStat);
|
|
|
|
|
}
|
|
|
|
|
if (descriptor.IsAllocated()) {
|
|
|
|
|
return ReturnError(terminator, StatBaseNotNull, errMsg, hasStat);
|
|
|
|
|
}
|
2021-07-19 11:53:20 -07:00
|
|
|
int stat{ReturnError(terminator, descriptor.Allocate(), errMsg, hasStat)};
|
|
|
|
|
if (stat == StatOk) {
|
|
|
|
|
if (const DescriptorAddendum * addendum{descriptor.Addendum()}) {
|
|
|
|
|
if (const auto *derived{addendum->derivedType()}) {
|
|
|
|
|
if (!derived->noInitializationNeeded()) {
|
|
|
|
|
stat = Initialize(descriptor, *derived, terminator, hasStat, errMsg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return stat;
|
2020-03-30 16:37:30 -07:00
|
|
|
}
|
|
|
|
|
|
2023-01-13 20:40:51 +08:00
|
|
|
int RTNAME(AllocatableAllocateSource)(Descriptor &alloc,
|
|
|
|
|
const Descriptor &source, bool hasStat, const Descriptor *errMsg,
|
|
|
|
|
const char *sourceFile, int sourceLine) {
|
|
|
|
|
int stat{RTNAME(AllocatableAllocate)(
|
|
|
|
|
alloc, hasStat, errMsg, sourceFile, sourceLine)};
|
|
|
|
|
if (stat == StatOk) {
|
|
|
|
|
Terminator terminator{sourceFile, sourceLine};
|
2023-02-01 21:09:02 +08:00
|
|
|
DoFromSourceAssign(alloc, source, terminator);
|
2023-01-13 20:40:51 +08:00
|
|
|
}
|
|
|
|
|
return stat;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 15:13:02 -08:00
|
|
|
int RTNAME(AllocatableDeallocate)(Descriptor &descriptor, bool hasStat,
|
2021-03-12 13:33:50 -08:00
|
|
|
const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
|
2020-11-10 15:13:02 -08:00
|
|
|
Terminator terminator{sourceFile, sourceLine};
|
|
|
|
|
if (!descriptor.IsAllocatable()) {
|
|
|
|
|
return ReturnError(terminator, StatInvalidDescriptor, errMsg, hasStat);
|
|
|
|
|
}
|
|
|
|
|
if (!descriptor.IsAllocated()) {
|
|
|
|
|
return ReturnError(terminator, StatBaseNull, errMsg, hasStat);
|
|
|
|
|
}
|
2023-07-29 08:34:14 -07:00
|
|
|
return ReturnError(terminator,
|
|
|
|
|
descriptor.Destroy(
|
|
|
|
|
/*finalize=*/true, /*destroyPointers=*/false, &terminator),
|
|
|
|
|
errMsg, hasStat);
|
2021-07-19 11:53:20 -07:00
|
|
|
}
|
|
|
|
|
|
2023-01-12 11:12:00 +01:00
|
|
|
int RTNAME(AllocatableDeallocatePolymorphic)(Descriptor &descriptor,
|
|
|
|
|
const typeInfo::DerivedType *derivedType, bool hasStat,
|
|
|
|
|
const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
|
|
|
|
|
int stat{RTNAME(AllocatableDeallocate)(
|
|
|
|
|
descriptor, hasStat, errMsg, sourceFile, sourceLine)};
|
|
|
|
|
if (stat == StatOk) {
|
2023-10-17 08:20:38 -07:00
|
|
|
if (DescriptorAddendum * addendum{descriptor.Addendum()}) {
|
2023-01-18 18:52:44 +01:00
|
|
|
addendum->set_derivedType(derivedType);
|
2023-10-17 08:20:38 -07:00
|
|
|
descriptor.raw().type = derivedType ? CFI_type_struct : CFI_type_other;
|
2023-01-18 18:52:44 +01:00
|
|
|
} else {
|
|
|
|
|
// Unlimited polymorphic descriptors initialized with
|
|
|
|
|
// AllocatableInitIntrinsic do not have an addendum. Make sure the
|
|
|
|
|
// derivedType is null in that case.
|
|
|
|
|
INTERNAL_CHECK(!derivedType);
|
2023-10-17 08:20:38 -07:00
|
|
|
descriptor.raw().type = CFI_type_other;
|
2023-01-18 18:52:44 +01:00
|
|
|
}
|
2023-01-12 11:12:00 +01:00
|
|
|
}
|
|
|
|
|
return stat;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-19 11:53:20 -07:00
|
|
|
void RTNAME(AllocatableDeallocateNoFinal)(
|
|
|
|
|
Descriptor &descriptor, const char *sourceFile, int sourceLine) {
|
|
|
|
|
Terminator terminator{sourceFile, sourceLine};
|
|
|
|
|
if (!descriptor.IsAllocatable()) {
|
|
|
|
|
ReturnError(terminator, StatInvalidDescriptor);
|
|
|
|
|
} else if (!descriptor.IsAllocated()) {
|
|
|
|
|
ReturnError(terminator, StatBaseNull);
|
|
|
|
|
} else {
|
2023-07-29 08:34:14 -07:00
|
|
|
ReturnError(terminator,
|
|
|
|
|
descriptor.Destroy(
|
|
|
|
|
/*finalize=*/false, /*destroyPointers=*/false, &terminator));
|
2021-07-19 11:53:20 -07:00
|
|
|
}
|
2020-03-30 16:37:30 -07:00
|
|
|
}
|
2021-07-16 10:42:17 -07:00
|
|
|
|
2023-01-13 20:40:51 +08:00
|
|
|
// TODO: AllocatableCheckLengthParameter
|
2020-03-30 16:37:30 -07:00
|
|
|
}
|
|
|
|
|
} // namespace Fortran::runtime
|