blob: 843f9165f8554a4d7777b74498145f487c977986 [file] [log] [blame]
peter klauslerad424cf2021-07-16 17:42:171//===-- runtime/pointer.cpp -----------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
Peter Klausler830c0b92021-09-01 23:00:539#include "flang/Runtime/pointer.h"
peter klauslera48e4162021-07-19 18:53:2010#include "derived.h"
peter klauslerad424cf2021-07-16 17:42:1711#include "stat.h"
12#include "terminator.h"
13#include "tools.h"
peter klauslera48e4162021-07-19 18:53:2014#include "type-info.h"
peter klauslerad424cf2021-07-16 17:42:1715
16namespace Fortran::runtime {
17extern "C" {
18
19void RTNAME(PointerNullifyIntrinsic)(Descriptor &pointer, TypeCategory category,
20 int kind, int rank, int corank) {
21 INTERNAL_CHECK(corank == 0);
22 pointer.Establish(TypeCode{category, kind},
23 Descriptor::BytesFor(category, kind), nullptr, rank, nullptr,
24 CFI_attribute_pointer);
25}
26
27void RTNAME(PointerNullifyCharacter)(Descriptor &pointer, SubscriptValue length,
28 int kind, int rank, int corank) {
29 INTERNAL_CHECK(corank == 0);
30 pointer.Establish(
31 kind, length, nullptr, rank, nullptr, CFI_attribute_pointer);
32}
33
34void RTNAME(PointerNullifyDerived)(Descriptor &pointer,
35 const typeInfo::DerivedType &derivedType, int rank, int corank) {
36 INTERNAL_CHECK(corank == 0);
37 pointer.Establish(derivedType, nullptr, rank, nullptr, CFI_attribute_pointer);
38}
39
40void RTNAME(PointerSetBounds)(Descriptor &pointer, int zeroBasedDim,
41 SubscriptValue lower, SubscriptValue upper) {
42 INTERNAL_CHECK(zeroBasedDim >= 0 && zeroBasedDim < pointer.rank());
43 pointer.GetDimension(zeroBasedDim).SetBounds(lower, upper);
44 // The byte strides are computed when the pointer is allocated.
45}
46
47// TODO: PointerSetCoBounds
48
49void RTNAME(PointerSetDerivedLength)(
50 Descriptor &pointer, int which, SubscriptValue x) {
51 DescriptorAddendum *addendum{pointer.Addendum()};
52 INTERNAL_CHECK(addendum != nullptr);
53 addendum->SetLenParameterValue(which, x);
54}
55
56void RTNAME(PointerApplyMold)(Descriptor &pointer, const Descriptor &mold) {
57 pointer = mold;
58 pointer.set_base_addr(nullptr);
59 pointer.raw().attribute = CFI_attribute_pointer;
60}
61
62void RTNAME(PointerAssociateScalar)(Descriptor &pointer, void *target) {
63 pointer.set_base_addr(target);
64}
65
66void RTNAME(PointerAssociate)(Descriptor &pointer, const Descriptor &target) {
67 pointer = target;
68 pointer.raw().attribute = CFI_attribute_pointer;
69}
70
71void RTNAME(PointerAssociateLowerBounds)(Descriptor &pointer,
72 const Descriptor &target, const Descriptor &lowerBounds) {
73 pointer = target;
74 pointer.raw().attribute = CFI_attribute_pointer;
75 int rank{pointer.rank()};
76 Terminator terminator{__FILE__, __LINE__};
77 std::size_t boundElementBytes{lowerBounds.ElementBytes()};
78 for (int j{0}; j < rank; ++j) {
Peter Klausler3b615872022-03-09 21:43:5479 Dimension &dim{pointer.GetDimension(j)};
80 dim.SetLowerBound(dim.Extent() == 0
81 ? 1
82 : GetInt64(lowerBounds.ZeroBasedIndexedElement<const char>(j),
83 boundElementBytes, terminator));
peter klauslerad424cf2021-07-16 17:42:1784 }
85}
86
87void RTNAME(PointerAssociateRemapping)(Descriptor &pointer,
88 const Descriptor &target, const Descriptor &bounds, const char *sourceFile,
89 int sourceLine) {
90 pointer = target;
91 pointer.raw().attribute = CFI_attribute_pointer;
92 int rank{pointer.rank()};
93 Terminator terminator{sourceFile, sourceLine};
94 SubscriptValue byteStride{/*captured from first dimension*/};
95 std::size_t boundElementBytes{bounds.ElementBytes()};
96 for (int j{0}; j < rank; ++j) {
97 auto &dim{pointer.GetDimension(j)};
98 dim.SetBounds(GetInt64(bounds.ZeroBasedIndexedElement<const char>(2 * j),
99 boundElementBytes, terminator),
100 GetInt64(bounds.ZeroBasedIndexedElement<const char>(2 * j + 1),
101 boundElementBytes, terminator));
102 if (j == 0) {
103 byteStride = dim.ByteStride();
104 } else {
105 dim.SetByteStride(byteStride);
106 byteStride *= dim.Extent();
107 }
108 }
109 if (pointer.Elements() > target.Elements()) {
110 terminator.Crash("PointerAssociateRemapping: too many elements in remapped "
111 "pointer (%zd > %zd)",
112 pointer.Elements(), target.Elements());
113 }
114}
115
116int RTNAME(PointerAllocate)(Descriptor &pointer, bool hasStat,
117 const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
118 Terminator terminator{sourceFile, sourceLine};
119 if (!pointer.IsPointer()) {
120 return ReturnError(terminator, StatInvalidDescriptor, errMsg, hasStat);
121 }
peter klauslera48e4162021-07-19 18:53:20122 int stat{ReturnError(terminator, pointer.Allocate(), errMsg, hasStat)};
123 if (stat == StatOk) {
124 if (const DescriptorAddendum * addendum{pointer.Addendum()}) {
125 if (const auto *derived{addendum->derivedType()}) {
126 if (!derived->noInitializationNeeded()) {
127 stat = Initialize(pointer, *derived, terminator, hasStat, errMsg);
128 }
129 }
130 }
131 }
132 return stat;
peter klauslerad424cf2021-07-16 17:42:17133}
134
135int RTNAME(PointerDeallocate)(Descriptor &pointer, bool hasStat,
136 const Descriptor *errMsg, const char *sourceFile, int sourceLine) {
137 Terminator terminator{sourceFile, sourceLine};
138 if (!pointer.IsPointer()) {
139 return ReturnError(terminator, StatInvalidDescriptor, errMsg, hasStat);
140 }
141 if (!pointer.IsAllocated()) {
142 return ReturnError(terminator, StatBaseNull, errMsg, hasStat);
143 }
Jean Perier479eed12022-03-28 08:21:36144 return ReturnError(terminator, pointer.Destroy(true, true), errMsg, hasStat);
peter klauslerad424cf2021-07-16 17:42:17145}
146
147bool RTNAME(PointerIsAssociated)(const Descriptor &pointer) {
148 return pointer.raw().base_addr != nullptr;
149}
150
151bool RTNAME(PointerIsAssociatedWith)(
Jean Perier392cba82022-03-03 09:11:19152 const Descriptor &pointer, const Descriptor *target) {
153 if (!target) {
154 return pointer.raw().base_addr != nullptr;
155 }
156 if (!target->raw().base_addr || target->ElementBytes() == 0) {
157 return false;
158 }
peter klauslerad424cf2021-07-16 17:42:17159 int rank{pointer.rank()};
Jean Perier392cba82022-03-03 09:11:19160 if (pointer.raw().base_addr != target->raw().base_addr ||
161 pointer.ElementBytes() != target->ElementBytes() ||
162 rank != target->rank()) {
peter klauslerad424cf2021-07-16 17:42:17163 return false;
164 }
165 for (int j{0}; j < rank; ++j) {
166 const Dimension &pDim{pointer.GetDimension(j)};
Jean Perier392cba82022-03-03 09:11:19167 const Dimension &tDim{target->GetDimension(j)};
Peter Klauslere0e2a112022-06-13 15:56:09168 auto pExtent{pDim.Extent()};
169 if (pExtent == 0 || pExtent != tDim.Extent() ||
170 (pExtent != 1 && pDim.ByteStride() != tDim.ByteStride())) {
peter klauslerad424cf2021-07-16 17:42:17171 return false;
172 }
173 }
174 return true;
175}
176
177// TODO: PointerCheckLengthParameter, PointerAllocateSource
178
179} // extern "C"
180} // namespace Fortran::runtime