[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / flang / unittests / Runtime / TemporaryStack.cpp
blob0a9344969ca6bae1d79b6bb6bb42be694535f785
1 //===--- flang/unittests/Runtime/TemporaryStack.cpp -------------*- C++ -*-===//
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 "gtest/gtest.h"
10 #include "tools.h"
11 #include "flang/ISO_Fortran_binding_wrapper.h"
12 #include "flang/Runtime/allocatable.h"
13 #include "flang/Runtime/cpp-type.h"
14 #include "flang/Runtime/descriptor.h"
15 #include "flang/Runtime/temporary-stack.h"
16 #include "flang/Runtime/type-code.h"
17 #include <vector>
19 using namespace Fortran::runtime;
21 // true if two descriptors are otherwise identical, except for different data
22 // pointers. The pointed-to elements are bit for bit identical.
23 static void descriptorAlmostEqual(
24 const Descriptor &lhs, const Descriptor &rhs) {
25 const Fortran::ISO::CFI_cdesc_t &lhsRaw = lhs.raw();
26 const Fortran::ISO::CFI_cdesc_t &rhsRaw = rhs.raw();
28 ASSERT_EQ(lhs.ElementBytes() == rhs.ElementBytes(), true);
29 ASSERT_EQ(lhsRaw.version == rhsRaw.version, true);
30 ASSERT_EQ(lhs.rank() == rhs.rank(), true);
31 ASSERT_EQ(lhs.type() == rhs.type(), true);
32 ASSERT_EQ(lhsRaw.attribute == rhsRaw.attribute, true);
34 ASSERT_EQ(memcmp(lhsRaw.dim, rhsRaw.dim, lhs.rank()) == 0, true);
35 const std::size_t bytes = lhs.Elements() * lhs.ElementBytes();
36 ASSERT_EQ(memcmp(lhsRaw.base_addr, rhsRaw.base_addr, bytes) == 0, true);
38 const DescriptorAddendum *lhsAdd = lhs.Addendum();
39 const DescriptorAddendum *rhsAdd = rhs.Addendum();
40 if (lhsAdd) {
41 ASSERT_NE(rhsAdd, nullptr);
42 ASSERT_EQ(lhsAdd->SizeInBytes() == rhsAdd->SizeInBytes(), true);
43 ASSERT_EQ(memcmp(lhsAdd, rhsAdd, lhsAdd->SizeInBytes()) == 0, true);
44 } else {
45 ASSERT_EQ(rhsAdd, nullptr);
49 TEST(TemporaryStack, ValueStackBasic) {
50 const TypeCode code{CFI_type_int32_t};
51 constexpr size_t elementBytes = 4;
52 constexpr size_t rank = 2;
53 void *const descriptorPtr = reinterpret_cast<void *>(0xdeadbeef);
54 const SubscriptValue extent[rank]{42, 24};
56 StaticDescriptor<rank> testDescriptorStorage[3];
57 Descriptor &inputDesc{testDescriptorStorage[0].descriptor()};
58 Descriptor &outputDesc{testDescriptorStorage[1].descriptor()};
59 Descriptor &outputDesc2{testDescriptorStorage[2].descriptor()};
60 inputDesc.Establish(code, elementBytes, descriptorPtr, rank, extent);
62 inputDesc.Allocate();
63 ASSERT_EQ(inputDesc.IsAllocated(), true);
64 uint32_t *inputData = static_cast<uint32_t *>(inputDesc.raw().base_addr);
65 for (std::size_t i = 0; i < inputDesc.Elements(); ++i) {
66 inputData[i] = i;
69 void *storage = RTNAME(CreateValueStack)(__FILE__, __LINE__);
70 ASSERT_NE(storage, nullptr);
72 RTNAME(PushValue)(storage, inputDesc);
74 RTNAME(ValueAt)(storage, 0, outputDesc);
75 descriptorAlmostEqual(inputDesc, outputDesc);
77 RTNAME(PopValue)(storage, outputDesc2);
78 descriptorAlmostEqual(inputDesc, outputDesc2);
80 RTNAME(DestroyValueStack)(storage);
83 static unsigned max(unsigned x, unsigned y) {
84 if (x > y) {
85 return x;
87 return y;
90 TEST(TemporaryStack, ValueStackMultiSize) {
91 constexpr unsigned numToTest = 42;
92 const TypeCode code{CFI_type_int32_t};
93 constexpr size_t elementBytes = 4;
94 SubscriptValue extent[CFI_MAX_RANK];
96 std::vector<OwningPtr<Descriptor>> inputDescriptors;
97 inputDescriptors.reserve(numToTest);
99 void *storage = RTNAME(CreateValueStack)(__FILE__, __LINE__);
100 ASSERT_NE(storage, nullptr);
102 // create descriptors with and without adendums
103 auto getAdendum = [](unsigned i) { return i % 2; };
104 // create descriptors with varying ranks
105 auto getRank = [](unsigned i) { return max(i % 8, 1); };
107 // push descriptors of varying sizes and contents
108 for (unsigned i = 0; i < numToTest; ++i) {
109 const bool adendum = getAdendum(i);
110 const size_t rank = getRank(i);
111 for (unsigned dim = 0; dim < rank; ++dim) {
112 extent[dim] = ((i + dim) % 8) + 1;
115 const OwningPtr<Descriptor> &desc =
116 inputDescriptors.emplace_back(Descriptor::Create(code, elementBytes,
117 nullptr, rank, extent, CFI_attribute_allocatable, adendum));
119 // Descriptor::Establish doesn't initialise the extents if baseaddr is null
120 for (unsigned dim = 0; dim < rank; ++dim) {
121 Fortran::ISO::CFI_dim_t &boxDims = desc->raw().dim[dim];
122 boxDims.lower_bound = 1;
123 boxDims.extent = extent[dim];
124 boxDims.sm = elementBytes;
126 desc->Allocate();
128 // fill the array with some data to test
129 for (uint32_t i = 0; i < desc->Elements(); ++i) {
130 uint32_t *data = static_cast<uint32_t *>(desc->raw().base_addr);
131 ASSERT_NE(data, nullptr);
132 data[i] = i;
135 RTNAME(PushValue)(storage, *desc.get());
138 const TypeCode boolCode{CFI_type_Bool};
139 // peek and test each descriptor
140 for (unsigned i = 0; i < numToTest; ++i) {
141 const OwningPtr<Descriptor> &input = inputDescriptors[i];
142 const bool adendum = getAdendum(i);
143 const size_t rank = getRank(i);
145 // buffer to return the descriptor into
146 OwningPtr<Descriptor> out = Descriptor::Create(
147 boolCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);
149 (void)input;
150 RTNAME(ValueAt)(storage, i, *out.get());
151 descriptorAlmostEqual(*input, *out);
154 // pop and test each descriptor
155 for (unsigned i = numToTest; i > 0; --i) {
156 const OwningPtr<Descriptor> &input = inputDescriptors[i - 1];
157 const bool adendum = getAdendum(i - 1);
158 const size_t rank = getRank(i - 1);
160 // buffer to return the descriptor into
161 OwningPtr<Descriptor> out = Descriptor::Create(
162 boolCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);
164 RTNAME(PopValue)(storage, *out.get());
165 descriptorAlmostEqual(*input, *out);
168 RTNAME(DestroyValueStack)(storage);
171 TEST(TemporaryStack, DescriptorStackBasic) {
172 const TypeCode code{CFI_type_Bool};
173 constexpr size_t elementBytes = 4;
174 constexpr size_t rank = 2;
175 void *const descriptorPtr = reinterpret_cast<void *>(0xdeadbeef);
176 const SubscriptValue extent[rank]{42, 24};
178 StaticDescriptor<rank> testDescriptorStorage[3];
179 Descriptor &inputDesc{testDescriptorStorage[0].descriptor()};
180 Descriptor &outputDesc{testDescriptorStorage[1].descriptor()};
181 Descriptor &outputDesc2{testDescriptorStorage[2].descriptor()};
182 inputDesc.Establish(code, elementBytes, descriptorPtr, rank, extent);
184 void *storage = RTNAME(CreateDescriptorStack)(__FILE__, __LINE__);
185 ASSERT_NE(storage, nullptr);
187 RTNAME(PushDescriptor)(storage, inputDesc);
189 RTNAME(DescriptorAt)(storage, 0, outputDesc);
190 ASSERT_EQ(
191 memcmp(&inputDesc, &outputDesc, testDescriptorStorage[0].byteSize), 0);
193 RTNAME(PopDescriptor)(storage, outputDesc2);
194 ASSERT_EQ(
195 memcmp(&inputDesc, &outputDesc2, testDescriptorStorage[0].byteSize), 0);
197 RTNAME(DestroyDescriptorStack)(storage);
200 TEST(TemporaryStack, DescriptorStackMultiSize) {
201 constexpr unsigned numToTest = 42;
202 const TypeCode code{CFI_type_Bool};
203 constexpr size_t elementBytes = 4;
204 const uintptr_t ptrBase = 0xdeadbeef;
205 SubscriptValue extent[CFI_MAX_RANK];
207 std::vector<OwningPtr<Descriptor>> inputDescriptors;
208 inputDescriptors.reserve(numToTest);
210 void *storage = RTNAME(CreateDescriptorStack)(__FILE__, __LINE__);
211 ASSERT_NE(storage, nullptr);
213 // create descriptors with and without adendums
214 auto getAdendum = [](unsigned i) { return i % 2; };
215 // create descriptors with varying ranks
216 auto getRank = [](unsigned i) { return max(i % CFI_MAX_RANK, 1); };
218 // push descriptors of varying sizes and contents
219 for (unsigned i = 0; i < numToTest; ++i) {
220 const bool adendum = getAdendum(i);
221 const size_t rank = getRank(i);
222 for (unsigned dim = 0; dim < rank; ++dim) {
223 extent[dim] = max(i - dim, 1);
226 // varying pointers
227 void *const ptr = reinterpret_cast<void *>(ptrBase + i * elementBytes);
229 const OwningPtr<Descriptor> &desc =
230 inputDescriptors.emplace_back(Descriptor::Create(code, elementBytes,
231 ptr, rank, extent, CFI_attribute_other, adendum));
232 RTNAME(PushDescriptor)(storage, *desc.get());
235 const TypeCode intCode{CFI_type_int8_t};
236 // peek and test each descriptor
237 for (unsigned i = 0; i < numToTest; ++i) {
238 const OwningPtr<Descriptor> &input = inputDescriptors[i];
239 const bool adendum = getAdendum(i);
240 const size_t rank = getRank(i);
242 // buffer to return the descriptor into
243 OwningPtr<Descriptor> out = Descriptor::Create(
244 intCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);
246 RTNAME(DescriptorAt)(storage, i, *out.get());
247 ASSERT_EQ(memcmp(input.get(), out.get(), input->SizeInBytes()), 0);
250 // pop and test each descriptor
251 for (unsigned i = numToTest; i > 0; --i) {
252 const OwningPtr<Descriptor> &input = inputDescriptors[i - 1];
253 const bool adendum = getAdendum(i - 1);
254 const size_t rank = getRank(i - 1);
256 // buffer to return the descriptor into
257 OwningPtr<Descriptor> out = Descriptor::Create(
258 intCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);
260 RTNAME(PopDescriptor)(storage, *out.get());
261 ASSERT_EQ(memcmp(input.get(), out.get(), input->SizeInBytes()), 0);
264 RTNAME(DestroyDescriptorStack)(storage);