1c1db35f0Speter klausler //===-- runtime/allocatable.cpp -------------------------------------------===//
24d54bb7aSpeter klausler //
34d54bb7aSpeter klausler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44d54bb7aSpeter klausler // See https://llvm.org/LICENSE.txt for license information.
54d54bb7aSpeter klausler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64d54bb7aSpeter klausler //
74d54bb7aSpeter klausler //===----------------------------------------------------------------------===//
84d54bb7aSpeter klausler
9*830c0b90SPeter Klausler #include "flang/Runtime/allocatable.h"
10a48e4168Speter klausler #include "derived.h"
118df28f0aSpeter klausler #include "stat.h"
124d54bb7aSpeter klausler #include "terminator.h"
13a48e4168Speter klausler #include "type-info.h"
14*830c0b90SPeter Klausler #include "flang/Runtime/assign.h"
154d54bb7aSpeter klausler
164d54bb7aSpeter klausler namespace Fortran::runtime {
174d54bb7aSpeter klausler extern "C" {
184d54bb7aSpeter klausler
RTNAME(AllocatableInitIntrinsic)198df28f0aSpeter klausler void RTNAME(AllocatableInitIntrinsic)(Descriptor &descriptor,
208df28f0aSpeter klausler TypeCategory category, int kind, int rank, int corank) {
218df28f0aSpeter klausler INTERNAL_CHECK(corank == 0);
228df28f0aSpeter klausler descriptor.Establish(TypeCode{category, kind},
238df28f0aSpeter klausler Descriptor::BytesFor(category, kind), nullptr, rank, nullptr,
248df28f0aSpeter klausler CFI_attribute_allocatable);
254d54bb7aSpeter klausler }
264d54bb7aSpeter klausler
RTNAME(AllocatableInitCharacter)278df28f0aSpeter klausler void RTNAME(AllocatableInitCharacter)(Descriptor &descriptor,
288df28f0aSpeter klausler SubscriptValue length, int kind, int rank, int corank) {
298df28f0aSpeter klausler INTERNAL_CHECK(corank == 0);
308df28f0aSpeter klausler descriptor.Establish(
318df28f0aSpeter klausler kind, length, nullptr, rank, nullptr, CFI_attribute_allocatable);
324d54bb7aSpeter klausler }
334d54bb7aSpeter klausler
RTNAME(AllocatableInitDerived)348df28f0aSpeter klausler void RTNAME(AllocatableInitDerived)(Descriptor &descriptor,
354fede8bcSpeter klausler const typeInfo::DerivedType &derivedType, int rank, int corank) {
368df28f0aSpeter klausler INTERNAL_CHECK(corank == 0);
378df28f0aSpeter klausler descriptor.Establish(
388df28f0aSpeter klausler derivedType, nullptr, rank, nullptr, CFI_attribute_allocatable);
394d54bb7aSpeter klausler }
404d54bb7aSpeter klausler
RTNAME(MoveAlloc)414d54bb7aSpeter klausler int RTNAME(MoveAlloc)(Descriptor &to, const Descriptor & /*from*/,
42170e9061Speter klausler bool /*hasStat*/, const Descriptor * /*errMsg*/,
43170e9061Speter klausler const char * /*sourceFile*/, int /*sourceLine*/) {
44a48e4168Speter klausler INTERNAL_CHECK(false); // TODO: MoveAlloc is not yet implemented
458df28f0aSpeter klausler return StatOk;
464d54bb7aSpeter klausler }
474d54bb7aSpeter klausler
RTNAME(AllocatableSetBounds)488df28f0aSpeter klausler void RTNAME(AllocatableSetBounds)(Descriptor &descriptor, int zeroBasedDim,
498df28f0aSpeter klausler SubscriptValue lower, SubscriptValue upper) {
508df28f0aSpeter klausler INTERNAL_CHECK(zeroBasedDim >= 0 && zeroBasedDim < descriptor.rank());
518df28f0aSpeter klausler descriptor.GetDimension(zeroBasedDim).SetBounds(lower, upper);
528df28f0aSpeter klausler // The byte strides are computed when the object is allocated.
538df28f0aSpeter klausler }
548df28f0aSpeter klausler
RTNAME(AllocatableSetDerivedLength)55ad424cf1Speter klausler void RTNAME(AllocatableSetDerivedLength)(
56ad424cf1Speter klausler Descriptor &descriptor, int which, SubscriptValue x) {
57ad424cf1Speter klausler DescriptorAddendum *addendum{descriptor.Addendum()};
58ad424cf1Speter klausler INTERNAL_CHECK(addendum != nullptr);
59ad424cf1Speter klausler addendum->SetLenParameterValue(which, x);
60ad424cf1Speter klausler }
61ad424cf1Speter klausler
RTNAME(AllocatableApplyMold)62ad424cf1Speter klausler void RTNAME(AllocatableApplyMold)(
63ad424cf1Speter klausler Descriptor &descriptor, const Descriptor &mold) {
64ad424cf1Speter klausler descriptor = mold;
65ad424cf1Speter klausler descriptor.set_base_addr(nullptr);
66ad424cf1Speter klausler descriptor.raw().attribute = CFI_attribute_allocatable;
67ad424cf1Speter klausler }
68ad424cf1Speter klausler
RTNAME(AllocatableAllocate)698df28f0aSpeter klausler int RTNAME(AllocatableAllocate)(Descriptor &descriptor, bool hasStat,
70170e9061Speter klausler const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
718df28f0aSpeter klausler Terminator terminator{sourceFile, sourceLine};
728df28f0aSpeter klausler if (!descriptor.IsAllocatable()) {
738df28f0aSpeter klausler return ReturnError(terminator, StatInvalidDescriptor, errMsg, hasStat);
748df28f0aSpeter klausler }
758df28f0aSpeter klausler if (descriptor.IsAllocated()) {
768df28f0aSpeter klausler return ReturnError(terminator, StatBaseNotNull, errMsg, hasStat);
778df28f0aSpeter klausler }
78a48e4168Speter klausler int stat{ReturnError(terminator, descriptor.Allocate(), errMsg, hasStat)};
79a48e4168Speter klausler if (stat == StatOk) {
80a48e4168Speter klausler if (const DescriptorAddendum * addendum{descriptor.Addendum()}) {
81a48e4168Speter klausler if (const auto *derived{addendum->derivedType()}) {
82a48e4168Speter klausler if (!derived->noInitializationNeeded()) {
83a48e4168Speter klausler stat = Initialize(descriptor, *derived, terminator, hasStat, errMsg);
84a48e4168Speter klausler }
85a48e4168Speter klausler }
86a48e4168Speter klausler }
87a48e4168Speter klausler }
88a48e4168Speter klausler return stat;
898df28f0aSpeter klausler }
908df28f0aSpeter klausler
RTNAME(AllocatableDeallocate)918df28f0aSpeter klausler int RTNAME(AllocatableDeallocate)(Descriptor &descriptor, bool hasStat,
92170e9061Speter klausler const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
938df28f0aSpeter klausler Terminator terminator{sourceFile, sourceLine};
948df28f0aSpeter klausler if (!descriptor.IsAllocatable()) {
958df28f0aSpeter klausler return ReturnError(terminator, StatInvalidDescriptor, errMsg, hasStat);
968df28f0aSpeter klausler }
978df28f0aSpeter klausler if (!descriptor.IsAllocated()) {
988df28f0aSpeter klausler return ReturnError(terminator, StatBaseNull, errMsg, hasStat);
998df28f0aSpeter klausler }
100a48e4168Speter klausler return ReturnError(terminator, descriptor.Destroy(true), errMsg, hasStat);
101a48e4168Speter klausler }
102a48e4168Speter klausler
RTNAME(AllocatableDeallocateNoFinal)103a48e4168Speter klausler void RTNAME(AllocatableDeallocateNoFinal)(
104a48e4168Speter klausler Descriptor &descriptor, const char *sourceFile, int sourceLine) {
105a48e4168Speter klausler Terminator terminator{sourceFile, sourceLine};
106a48e4168Speter klausler if (!descriptor.IsAllocatable()) {
107a48e4168Speter klausler ReturnError(terminator, StatInvalidDescriptor);
108a48e4168Speter klausler } else if (!descriptor.IsAllocated()) {
109a48e4168Speter klausler ReturnError(terminator, StatBaseNull);
110a48e4168Speter klausler } else {
111a48e4168Speter klausler ReturnError(terminator, descriptor.Destroy(false));
112a48e4168Speter klausler }
1134d54bb7aSpeter klausler }
114ad424cf1Speter klausler
115ad424cf1Speter klausler // TODO: AllocatableCheckLengthParameter, AllocatableAllocateSource
1164d54bb7aSpeter klausler }
1174d54bb7aSpeter klausler } // namespace Fortran::runtime
118