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