[PowerPC][NFC] Cleanup PPCCTRLoopsVerify pass
[llvm-project.git] / flang / runtime / descriptor.cpp
blobefcd61b50c4f4c9167b9efe6ad088d7618fcbbb9
1 //===-- runtime/descriptor.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 //===----------------------------------------------------------------------===//
9 #include "descriptor.h"
10 #include "derived.h"
11 #include "memory.h"
12 #include "terminator.h"
13 #include "type-info.h"
14 #include <cassert>
15 #include <cstdlib>
16 #include <cstring>
18 namespace Fortran::runtime {
20 Descriptor::Descriptor(const Descriptor &that) {
21 std::memcpy(this, &that, that.SizeInBytes());
24 Descriptor::~Descriptor() {
25 if (raw_.attribute != CFI_attribute_pointer) {
26 Deallocate();
30 void Descriptor::Establish(TypeCode t, std::size_t elementBytes, void *p,
31 int rank, const SubscriptValue *extent, ISO::CFI_attribute_t attribute,
32 bool addendum) {
33 Terminator terminator{__FILE__, __LINE__};
34 RUNTIME_CHECK(terminator,
35 ISO::CFI_establish(&raw_, p, attribute, t.raw(), elementBytes, rank,
36 extent) == CFI_SUCCESS);
37 raw_.f18Addendum = addendum;
38 DescriptorAddendum *a{Addendum()};
39 RUNTIME_CHECK(terminator, addendum == (a != nullptr));
40 if (a) {
41 new (a) DescriptorAddendum{};
45 void Descriptor::Establish(TypeCategory c, int kind, void *p, int rank,
46 const SubscriptValue *extent, ISO::CFI_attribute_t attribute,
47 bool addendum) {
48 Establish(TypeCode(c, kind), BytesFor(c, kind), p, rank, extent, attribute,
49 addendum);
52 void Descriptor::Establish(int characterKind, std::size_t characters, void *p,
53 int rank, const SubscriptValue *extent, ISO::CFI_attribute_t attribute,
54 bool addendum) {
55 Establish(TypeCode{TypeCategory::Character, characterKind},
56 characterKind * characters, p, rank, extent, attribute, addendum);
59 void Descriptor::Establish(const typeInfo::DerivedType &dt, void *p, int rank,
60 const SubscriptValue *extent, ISO::CFI_attribute_t attribute) {
61 Establish(CFI_type_struct, dt.sizeInBytes, p, rank, extent, attribute, true);
62 DescriptorAddendum *a{Addendum()};
63 Terminator terminator{__FILE__, __LINE__};
64 RUNTIME_CHECK(terminator, a != nullptr);
65 new (a) DescriptorAddendum{&dt};
68 OwningPtr<Descriptor> Descriptor::Create(TypeCode t, std::size_t elementBytes,
69 void *p, int rank, const SubscriptValue *extent,
70 ISO::CFI_attribute_t attribute, int derivedTypeLenParameters) {
71 std::size_t bytes{SizeInBytes(rank, true, derivedTypeLenParameters)};
72 Terminator terminator{__FILE__, __LINE__};
73 Descriptor *result{
74 reinterpret_cast<Descriptor *>(AllocateMemoryOrCrash(terminator, bytes))};
75 result->Establish(t, elementBytes, p, rank, extent, attribute, true);
76 return OwningPtr<Descriptor>{result};
79 OwningPtr<Descriptor> Descriptor::Create(TypeCategory c, int kind, void *p,
80 int rank, const SubscriptValue *extent, ISO::CFI_attribute_t attribute) {
81 return Create(
82 TypeCode(c, kind), BytesFor(c, kind), p, rank, extent, attribute);
85 OwningPtr<Descriptor> Descriptor::Create(int characterKind,
86 SubscriptValue characters, void *p, int rank, const SubscriptValue *extent,
87 ISO::CFI_attribute_t attribute) {
88 return Create(TypeCode{TypeCategory::Character, characterKind},
89 characterKind * characters, p, rank, extent, attribute);
92 OwningPtr<Descriptor> Descriptor::Create(const typeInfo::DerivedType &dt,
93 void *p, int rank, const SubscriptValue *extent,
94 ISO::CFI_attribute_t attribute) {
95 return Create(TypeCode{CFI_type_struct}, dt.sizeInBytes, p, rank, extent,
96 attribute, dt.LenParameters());
99 std::size_t Descriptor::SizeInBytes() const {
100 const DescriptorAddendum *addendum{Addendum()};
101 return sizeof *this - sizeof(Dimension) + raw_.rank * sizeof(Dimension) +
102 (addendum ? addendum->SizeInBytes() : 0);
105 std::size_t Descriptor::Elements() const {
106 int n{rank()};
107 std::size_t elements{1};
108 for (int j{0}; j < n; ++j) {
109 elements *= GetDimension(j).Extent();
111 return elements;
114 int Descriptor::Allocate() {
115 std::size_t byteSize{Elements() * ElementBytes()};
116 void *p{std::malloc(byteSize)};
117 if (!p && byteSize) {
118 return CFI_ERROR_MEM_ALLOCATION;
120 // TODO: image synchronization
121 // TODO: derived type initialization
122 raw_.base_addr = p;
123 if (int dims{rank()}) {
124 std::size_t stride{ElementBytes()};
125 for (int j{0}; j < dims; ++j) {
126 auto &dimension{GetDimension(j)};
127 dimension.SetByteStride(stride);
128 stride *= dimension.Extent();
131 return 0;
134 int Descriptor::Allocate(const SubscriptValue lb[], const SubscriptValue ub[]) {
135 int result{ISO::CFI_allocate(&raw_, lb, ub, ElementBytes())};
136 if (result == CFI_SUCCESS) {
137 // TODO: derived type initialization
139 return result;
142 int Descriptor::Deallocate(bool finalize) {
143 Destroy(finalize);
144 return ISO::CFI_deallocate(&raw_);
147 void Descriptor::Destroy(bool finalize) const {
148 if (const DescriptorAddendum * addendum{Addendum()}) {
149 if (const typeInfo::DerivedType * dt{addendum->derivedType()}) {
150 if (addendum->flags() & DescriptorAddendum::DoNotFinalize) {
151 finalize = false;
153 runtime::Destroy(*this, finalize, *dt);
158 bool Descriptor::IncrementSubscripts(
159 SubscriptValue *subscript, const int *permutation) const {
160 for (int j{0}; j < raw_.rank; ++j) {
161 int k{permutation ? permutation[j] : j};
162 const Dimension &dim{GetDimension(k)};
163 if (subscript[k]++ < dim.UpperBound()) {
164 return true;
166 subscript[k] = dim.LowerBound();
168 return false;
171 bool Descriptor::DecrementSubscripts(
172 SubscriptValue *subscript, const int *permutation) const {
173 for (int j{raw_.rank - 1}; j >= 0; --j) {
174 int k{permutation ? permutation[j] : j};
175 const Dimension &dim{GetDimension(k)};
176 if (--subscript[k] >= dim.LowerBound()) {
177 return true;
179 subscript[k] = dim.UpperBound();
181 return false;
184 std::size_t Descriptor::ZeroBasedElementNumber(
185 const SubscriptValue *subscript, const int *permutation) const {
186 std::size_t result{0};
187 std::size_t coefficient{1};
188 for (int j{0}; j < raw_.rank; ++j) {
189 int k{permutation ? permutation[j] : j};
190 const Dimension &dim{GetDimension(k)};
191 result += coefficient * (subscript[k] - dim.LowerBound());
192 coefficient *= dim.Extent();
194 return result;
197 bool Descriptor::SubscriptsForZeroBasedElementNumber(SubscriptValue *subscript,
198 std::size_t elementNumber, const int *permutation) const {
199 std::size_t coefficient{1};
200 std::size_t dimCoefficient[maxRank];
201 for (int j{0}; j < raw_.rank; ++j) {
202 int k{permutation ? permutation[j] : j};
203 const Dimension &dim{GetDimension(k)};
204 dimCoefficient[j] = coefficient;
205 coefficient *= dim.Extent();
207 if (elementNumber >= coefficient) {
208 return false; // out of range
210 for (int j{raw_.rank - 1}; j >= 0; --j) {
211 int k{permutation ? permutation[j] : j};
212 const Dimension &dim{GetDimension(k)};
213 std::size_t quotient{j ? elementNumber / dimCoefficient[j] : 0};
214 subscript[k] =
215 dim.LowerBound() + elementNumber - dimCoefficient[j] * quotient;
216 elementNumber = quotient;
218 return true;
221 void Descriptor::Check() const {
222 // TODO
225 void Descriptor::Dump(FILE *f) const {
226 std::fprintf(f, "Descriptor @ %p:\n", reinterpret_cast<const void *>(this));
227 std::fprintf(f, " base_addr %p\n", raw_.base_addr);
228 std::fprintf(f, " elem_len %zd\n", static_cast<std::size_t>(raw_.elem_len));
229 std::fprintf(f, " version %d\n", static_cast<int>(raw_.version));
230 std::fprintf(f, " rank %d\n", static_cast<int>(raw_.rank));
231 std::fprintf(f, " type %d\n", static_cast<int>(raw_.type));
232 std::fprintf(f, " attribute %d\n", static_cast<int>(raw_.attribute));
233 std::fprintf(f, " addendum %d\n", static_cast<int>(raw_.f18Addendum));
234 for (int j{0}; j < raw_.rank; ++j) {
235 std::fprintf(f, " dim[%d] lower_bound %jd\n", j,
236 static_cast<std::intmax_t>(raw_.dim[j].lower_bound));
237 std::fprintf(f, " extent %jd\n",
238 static_cast<std::intmax_t>(raw_.dim[j].extent));
239 std::fprintf(f, " sm %jd\n",
240 static_cast<std::intmax_t>(raw_.dim[j].sm));
242 if (const DescriptorAddendum * addendum{Addendum()}) {
243 addendum->Dump(f);
247 std::size_t DescriptorAddendum::SizeInBytes() const {
248 return SizeInBytes(LenParameters());
251 std::size_t DescriptorAddendum::LenParameters() const {
252 const auto *type{derivedType()};
253 return type ? type->LenParameters() : 0;
256 void DescriptorAddendum::Dump(FILE *f) const {
257 std::fprintf(
258 f, " derivedType @ %p\n", reinterpret_cast<const void *>(derivedType_));
259 std::fprintf(f, " flags 0x%jx\n", static_cast<std::intmax_t>(flags_));
260 // TODO: LEN parameter values
262 } // namespace Fortran::runtime