1ad424cf1Speter klausler //===-- runtime/pointer.cpp -----------------------------------------------===//
2ad424cf1Speter klausler //
3ad424cf1Speter klausler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ad424cf1Speter klausler // See https://llvm.org/LICENSE.txt for license information.
5ad424cf1Speter klausler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ad424cf1Speter klausler //
7ad424cf1Speter klausler //===----------------------------------------------------------------------===//
8ad424cf1Speter klausler
9830c0b90SPeter Klausler #include "flang/Runtime/pointer.h"
10a48e4168Speter klausler #include "derived.h"
11ad424cf1Speter klausler #include "stat.h"
12ad424cf1Speter klausler #include "terminator.h"
13ad424cf1Speter klausler #include "tools.h"
14a48e4168Speter klausler #include "type-info.h"
15ad424cf1Speter klausler
16ad424cf1Speter klausler namespace Fortran::runtime {
17ad424cf1Speter klausler extern "C" {
18ad424cf1Speter klausler
RTNAME(PointerNullifyIntrinsic)19ad424cf1Speter klausler void RTNAME(PointerNullifyIntrinsic)(Descriptor &pointer, TypeCategory category,
20ad424cf1Speter klausler int kind, int rank, int corank) {
21ad424cf1Speter klausler INTERNAL_CHECK(corank == 0);
22ad424cf1Speter klausler pointer.Establish(TypeCode{category, kind},
23ad424cf1Speter klausler Descriptor::BytesFor(category, kind), nullptr, rank, nullptr,
24ad424cf1Speter klausler CFI_attribute_pointer);
25ad424cf1Speter klausler }
26ad424cf1Speter klausler
RTNAME(PointerNullifyCharacter)27ad424cf1Speter klausler void RTNAME(PointerNullifyCharacter)(Descriptor &pointer, SubscriptValue length,
28ad424cf1Speter klausler int kind, int rank, int corank) {
29ad424cf1Speter klausler INTERNAL_CHECK(corank == 0);
30ad424cf1Speter klausler pointer.Establish(
31ad424cf1Speter klausler kind, length, nullptr, rank, nullptr, CFI_attribute_pointer);
32ad424cf1Speter klausler }
33ad424cf1Speter klausler
RTNAME(PointerNullifyDerived)34ad424cf1Speter klausler void RTNAME(PointerNullifyDerived)(Descriptor &pointer,
35ad424cf1Speter klausler const typeInfo::DerivedType &derivedType, int rank, int corank) {
36ad424cf1Speter klausler INTERNAL_CHECK(corank == 0);
37ad424cf1Speter klausler pointer.Establish(derivedType, nullptr, rank, nullptr, CFI_attribute_pointer);
38ad424cf1Speter klausler }
39ad424cf1Speter klausler
RTNAME(PointerSetBounds)40ad424cf1Speter klausler void RTNAME(PointerSetBounds)(Descriptor &pointer, int zeroBasedDim,
41ad424cf1Speter klausler SubscriptValue lower, SubscriptValue upper) {
42ad424cf1Speter klausler INTERNAL_CHECK(zeroBasedDim >= 0 && zeroBasedDim < pointer.rank());
43ad424cf1Speter klausler pointer.GetDimension(zeroBasedDim).SetBounds(lower, upper);
44ad424cf1Speter klausler // The byte strides are computed when the pointer is allocated.
45ad424cf1Speter klausler }
46ad424cf1Speter klausler
47ad424cf1Speter klausler // TODO: PointerSetCoBounds
48ad424cf1Speter klausler
RTNAME(PointerSetDerivedLength)49ad424cf1Speter klausler void RTNAME(PointerSetDerivedLength)(
50ad424cf1Speter klausler Descriptor &pointer, int which, SubscriptValue x) {
51ad424cf1Speter klausler DescriptorAddendum *addendum{pointer.Addendum()};
52ad424cf1Speter klausler INTERNAL_CHECK(addendum != nullptr);
53ad424cf1Speter klausler addendum->SetLenParameterValue(which, x);
54ad424cf1Speter klausler }
55ad424cf1Speter klausler
RTNAME(PointerApplyMold)56ad424cf1Speter klausler void RTNAME(PointerApplyMold)(Descriptor &pointer, const Descriptor &mold) {
57ad424cf1Speter klausler pointer = mold;
58ad424cf1Speter klausler pointer.set_base_addr(nullptr);
59ad424cf1Speter klausler pointer.raw().attribute = CFI_attribute_pointer;
60ad424cf1Speter klausler }
61ad424cf1Speter klausler
RTNAME(PointerAssociateScalar)62ad424cf1Speter klausler void RTNAME(PointerAssociateScalar)(Descriptor &pointer, void *target) {
63ad424cf1Speter klausler pointer.set_base_addr(target);
64ad424cf1Speter klausler }
65ad424cf1Speter klausler
RTNAME(PointerAssociate)66ad424cf1Speter klausler void RTNAME(PointerAssociate)(Descriptor &pointer, const Descriptor &target) {
67ad424cf1Speter klausler pointer = target;
68ad424cf1Speter klausler pointer.raw().attribute = CFI_attribute_pointer;
69ad424cf1Speter klausler }
70ad424cf1Speter klausler
RTNAME(PointerAssociateLowerBounds)71ad424cf1Speter klausler void RTNAME(PointerAssociateLowerBounds)(Descriptor &pointer,
72ad424cf1Speter klausler const Descriptor &target, const Descriptor &lowerBounds) {
73ad424cf1Speter klausler pointer = target;
74ad424cf1Speter klausler pointer.raw().attribute = CFI_attribute_pointer;
75ad424cf1Speter klausler int rank{pointer.rank()};
76ad424cf1Speter klausler Terminator terminator{__FILE__, __LINE__};
77ad424cf1Speter klausler std::size_t boundElementBytes{lowerBounds.ElementBytes()};
78ad424cf1Speter klausler for (int j{0}; j < rank; ++j) {
793b61587cSPeter Klausler Dimension &dim{pointer.GetDimension(j)};
803b61587cSPeter Klausler dim.SetLowerBound(dim.Extent() == 0
813b61587cSPeter Klausler ? 1
823b61587cSPeter Klausler : GetInt64(lowerBounds.ZeroBasedIndexedElement<const char>(j),
83ad424cf1Speter klausler boundElementBytes, terminator));
84ad424cf1Speter klausler }
85ad424cf1Speter klausler }
86ad424cf1Speter klausler
RTNAME(PointerAssociateRemapping)87ad424cf1Speter klausler void RTNAME(PointerAssociateRemapping)(Descriptor &pointer,
88ad424cf1Speter klausler const Descriptor &target, const Descriptor &bounds, const char *sourceFile,
89ad424cf1Speter klausler int sourceLine) {
90ad424cf1Speter klausler pointer = target;
91ad424cf1Speter klausler pointer.raw().attribute = CFI_attribute_pointer;
92ad424cf1Speter klausler int rank{pointer.rank()};
93ad424cf1Speter klausler Terminator terminator{sourceFile, sourceLine};
94ad424cf1Speter klausler SubscriptValue byteStride{/*captured from first dimension*/};
95ad424cf1Speter klausler std::size_t boundElementBytes{bounds.ElementBytes()};
96ad424cf1Speter klausler for (int j{0}; j < rank; ++j) {
97ad424cf1Speter klausler auto &dim{pointer.GetDimension(j)};
98ad424cf1Speter klausler dim.SetBounds(GetInt64(bounds.ZeroBasedIndexedElement<const char>(2 * j),
99ad424cf1Speter klausler boundElementBytes, terminator),
100ad424cf1Speter klausler GetInt64(bounds.ZeroBasedIndexedElement<const char>(2 * j + 1),
101ad424cf1Speter klausler boundElementBytes, terminator));
102ad424cf1Speter klausler if (j == 0) {
103ad424cf1Speter klausler byteStride = dim.ByteStride();
104ad424cf1Speter klausler } else {
105ad424cf1Speter klausler dim.SetByteStride(byteStride);
106ad424cf1Speter klausler byteStride *= dim.Extent();
107ad424cf1Speter klausler }
108ad424cf1Speter klausler }
109ad424cf1Speter klausler if (pointer.Elements() > target.Elements()) {
110ad424cf1Speter klausler terminator.Crash("PointerAssociateRemapping: too many elements in remapped "
111ad424cf1Speter klausler "pointer (%zd > %zd)",
112ad424cf1Speter klausler pointer.Elements(), target.Elements());
113ad424cf1Speter klausler }
114ad424cf1Speter klausler }
115ad424cf1Speter klausler
RTNAME(PointerAllocate)116ad424cf1Speter klausler int RTNAME(PointerAllocate)(Descriptor &pointer, bool hasStat,
117ad424cf1Speter klausler const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
118ad424cf1Speter klausler Terminator terminator{sourceFile, sourceLine};
119ad424cf1Speter klausler if (!pointer.IsPointer()) {
120ad424cf1Speter klausler return ReturnError(terminator, StatInvalidDescriptor, errMsg, hasStat);
121ad424cf1Speter klausler }
122a48e4168Speter klausler int stat{ReturnError(terminator, pointer.Allocate(), errMsg, hasStat)};
123a48e4168Speter klausler if (stat == StatOk) {
124a48e4168Speter klausler if (const DescriptorAddendum * addendum{pointer.Addendum()}) {
125a48e4168Speter klausler if (const auto *derived{addendum->derivedType()}) {
126a48e4168Speter klausler if (!derived->noInitializationNeeded()) {
127a48e4168Speter klausler stat = Initialize(pointer, *derived, terminator, hasStat, errMsg);
128a48e4168Speter klausler }
129a48e4168Speter klausler }
130a48e4168Speter klausler }
131a48e4168Speter klausler }
132a48e4168Speter klausler return stat;
133ad424cf1Speter klausler }
134ad424cf1Speter klausler
RTNAME(PointerDeallocate)135ad424cf1Speter klausler int RTNAME(PointerDeallocate)(Descriptor &pointer, bool hasStat,
136ad424cf1Speter klausler const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
137ad424cf1Speter klausler Terminator terminator{sourceFile, sourceLine};
138ad424cf1Speter klausler if (!pointer.IsPointer()) {
139ad424cf1Speter klausler return ReturnError(terminator, StatInvalidDescriptor, errMsg, hasStat);
140ad424cf1Speter klausler }
141ad424cf1Speter klausler if (!pointer.IsAllocated()) {
142ad424cf1Speter klausler return ReturnError(terminator, StatBaseNull, errMsg, hasStat);
143ad424cf1Speter klausler }
144479eed18SJean Perier return ReturnError(terminator, pointer.Destroy(true, true), errMsg, hasStat);
145ad424cf1Speter klausler }
146ad424cf1Speter klausler
RTNAME(PointerIsAssociated)147ad424cf1Speter klausler bool RTNAME(PointerIsAssociated)(const Descriptor &pointer) {
148ad424cf1Speter klausler return pointer.raw().base_addr != nullptr;
149ad424cf1Speter klausler }
150ad424cf1Speter klausler
RTNAME(PointerIsAssociatedWith)151ad424cf1Speter klausler bool RTNAME(PointerIsAssociatedWith)(
152392cba86SJean Perier const Descriptor &pointer, const Descriptor *target) {
153392cba86SJean Perier if (!target) {
154392cba86SJean Perier return pointer.raw().base_addr != nullptr;
155392cba86SJean Perier }
156392cba86SJean Perier if (!target->raw().base_addr || target->ElementBytes() == 0) {
157392cba86SJean Perier return false;
158392cba86SJean Perier }
159ad424cf1Speter klausler int rank{pointer.rank()};
160392cba86SJean Perier if (pointer.raw().base_addr != target->raw().base_addr ||
161392cba86SJean Perier pointer.ElementBytes() != target->ElementBytes() ||
162392cba86SJean Perier rank != target->rank()) {
163ad424cf1Speter klausler return false;
164ad424cf1Speter klausler }
165ad424cf1Speter klausler for (int j{0}; j < rank; ++j) {
166ad424cf1Speter klausler const Dimension &pDim{pointer.GetDimension(j)};
167392cba86SJean Perier const Dimension &tDim{target->GetDimension(j)};
168*e0e2a117SPeter Klausler auto pExtent{pDim.Extent()};
169*e0e2a117SPeter Klausler if (pExtent == 0 || pExtent != tDim.Extent() ||
170*e0e2a117SPeter Klausler (pExtent != 1 && pDim.ByteStride() != tDim.ByteStride())) {
171ad424cf1Speter klausler return false;
172ad424cf1Speter klausler }
173ad424cf1Speter klausler }
174ad424cf1Speter klausler return true;
175ad424cf1Speter klausler }
176ad424cf1Speter klausler
177ad424cf1Speter klausler // TODO: PointerCheckLengthParameter, PointerAllocateSource
178ad424cf1Speter klausler
179ad424cf1Speter klausler } // extern "C"
180ad424cf1Speter klausler } // namespace Fortran::runtime
181