mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 17:36:36 +00:00

This reverts commit 6403287eff71a3d6f6c862346d6ed3f0f000eb70. This is failing on all but 1 of Linaro's flang builders. CMake Error at /home/tcwg-buildbot/worker/clang-aarch64-full-2stage/llvm/flang-rt/unittests/CMakeLists.txt:37 (message): Target llvm_gtest not found.
266 lines
9.1 KiB
C++
266 lines
9.1 KiB
C++
//===--- flang/unittests/Runtime/TemporaryStack.cpp -------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "tools.h"
|
|
#include "flang/ISO_Fortran_binding_wrapper.h"
|
|
#include "flang/Runtime/allocatable.h"
|
|
#include "flang/Runtime/cpp-type.h"
|
|
#include "flang/Runtime/descriptor.h"
|
|
#include "flang/Runtime/temporary-stack.h"
|
|
#include "flang/Runtime/type-code.h"
|
|
#include <vector>
|
|
|
|
using namespace Fortran::runtime;
|
|
|
|
// true if two descriptors are otherwise identical, except for different data
|
|
// pointers. The pointed-to elements are bit for bit identical.
|
|
static void descriptorAlmostEqual(
|
|
const Descriptor &lhs, const Descriptor &rhs) {
|
|
const Fortran::ISO::CFI_cdesc_t &lhsRaw = lhs.raw();
|
|
const Fortran::ISO::CFI_cdesc_t &rhsRaw = rhs.raw();
|
|
|
|
ASSERT_EQ(lhs.ElementBytes() == rhs.ElementBytes(), true);
|
|
ASSERT_EQ(lhsRaw.version == rhsRaw.version, true);
|
|
ASSERT_EQ(lhs.rank() == rhs.rank(), true);
|
|
ASSERT_EQ(lhs.type() == rhs.type(), true);
|
|
ASSERT_EQ(lhsRaw.attribute == rhsRaw.attribute, true);
|
|
|
|
ASSERT_EQ(memcmp(lhsRaw.dim, rhsRaw.dim, lhs.rank()) == 0, true);
|
|
const std::size_t bytes = lhs.Elements() * lhs.ElementBytes();
|
|
ASSERT_EQ(memcmp(lhsRaw.base_addr, rhsRaw.base_addr, bytes) == 0, true);
|
|
|
|
const DescriptorAddendum *lhsAdd = lhs.Addendum();
|
|
const DescriptorAddendum *rhsAdd = rhs.Addendum();
|
|
if (lhsAdd) {
|
|
ASSERT_NE(rhsAdd, nullptr);
|
|
ASSERT_EQ(lhsAdd->SizeInBytes() == rhsAdd->SizeInBytes(), true);
|
|
ASSERT_EQ(memcmp(lhsAdd, rhsAdd, lhsAdd->SizeInBytes()) == 0, true);
|
|
} else {
|
|
ASSERT_EQ(rhsAdd, nullptr);
|
|
}
|
|
}
|
|
|
|
TEST(TemporaryStack, ValueStackBasic) {
|
|
const TypeCode code{CFI_type_int32_t};
|
|
constexpr size_t elementBytes = 4;
|
|
constexpr size_t rank = 2;
|
|
void *const descriptorPtr = reinterpret_cast<void *>(0xdeadbeef);
|
|
const SubscriptValue extent[rank]{42, 24};
|
|
|
|
StaticDescriptor<rank> testDescriptorStorage[3];
|
|
Descriptor &inputDesc{testDescriptorStorage[0].descriptor()};
|
|
Descriptor &outputDesc{testDescriptorStorage[1].descriptor()};
|
|
Descriptor &outputDesc2{testDescriptorStorage[2].descriptor()};
|
|
inputDesc.Establish(code, elementBytes, descriptorPtr, rank, extent);
|
|
|
|
inputDesc.Allocate();
|
|
ASSERT_EQ(inputDesc.IsAllocated(), true);
|
|
uint32_t *inputData = static_cast<uint32_t *>(inputDesc.raw().base_addr);
|
|
for (std::size_t i = 0; i < inputDesc.Elements(); ++i) {
|
|
inputData[i] = i;
|
|
}
|
|
|
|
void *storage = RTNAME(CreateValueStack)(__FILE__, __LINE__);
|
|
ASSERT_NE(storage, nullptr);
|
|
|
|
RTNAME(PushValue)(storage, inputDesc);
|
|
|
|
RTNAME(ValueAt)(storage, 0, outputDesc);
|
|
descriptorAlmostEqual(inputDesc, outputDesc);
|
|
|
|
RTNAME(PopValue)(storage, outputDesc2);
|
|
descriptorAlmostEqual(inputDesc, outputDesc2);
|
|
|
|
RTNAME(DestroyValueStack)(storage);
|
|
}
|
|
|
|
static unsigned max(unsigned x, unsigned y) {
|
|
if (x > y) {
|
|
return x;
|
|
}
|
|
return y;
|
|
}
|
|
|
|
TEST(TemporaryStack, ValueStackMultiSize) {
|
|
constexpr unsigned numToTest = 42;
|
|
const TypeCode code{CFI_type_int32_t};
|
|
constexpr size_t elementBytes = 4;
|
|
SubscriptValue extent[CFI_MAX_RANK];
|
|
|
|
std::vector<OwningPtr<Descriptor>> inputDescriptors;
|
|
inputDescriptors.reserve(numToTest);
|
|
|
|
void *storage = RTNAME(CreateValueStack)(__FILE__, __LINE__);
|
|
ASSERT_NE(storage, nullptr);
|
|
|
|
// create descriptors with and without adendums
|
|
auto getAdendum = [](unsigned i) { return i % 2; };
|
|
// create descriptors with varying ranks
|
|
auto getRank = [](unsigned i) { return max(i % 8, 1); };
|
|
|
|
// push descriptors of varying sizes and contents
|
|
for (unsigned i = 0; i < numToTest; ++i) {
|
|
const bool adendum = getAdendum(i);
|
|
const size_t rank = getRank(i);
|
|
for (unsigned dim = 0; dim < rank; ++dim) {
|
|
extent[dim] = ((i + dim) % 8) + 1;
|
|
}
|
|
|
|
const OwningPtr<Descriptor> &desc =
|
|
inputDescriptors.emplace_back(Descriptor::Create(code, elementBytes,
|
|
nullptr, rank, extent, CFI_attribute_allocatable, adendum));
|
|
|
|
// Descriptor::Establish doesn't initialise the extents if baseaddr is null
|
|
for (unsigned dim = 0; dim < rank; ++dim) {
|
|
Fortran::ISO::CFI_dim_t &boxDims = desc->raw().dim[dim];
|
|
boxDims.lower_bound = 1;
|
|
boxDims.extent = extent[dim];
|
|
boxDims.sm = elementBytes;
|
|
}
|
|
desc->Allocate();
|
|
|
|
// fill the array with some data to test
|
|
for (uint32_t i = 0; i < desc->Elements(); ++i) {
|
|
uint32_t *data = static_cast<uint32_t *>(desc->raw().base_addr);
|
|
ASSERT_NE(data, nullptr);
|
|
data[i] = i;
|
|
}
|
|
|
|
RTNAME(PushValue)(storage, *desc.get());
|
|
}
|
|
|
|
const TypeCode boolCode{CFI_type_Bool};
|
|
// peek and test each descriptor
|
|
for (unsigned i = 0; i < numToTest; ++i) {
|
|
const OwningPtr<Descriptor> &input = inputDescriptors[i];
|
|
const bool adendum = getAdendum(i);
|
|
const size_t rank = getRank(i);
|
|
|
|
// buffer to return the descriptor into
|
|
OwningPtr<Descriptor> out = Descriptor::Create(
|
|
boolCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);
|
|
|
|
(void)input;
|
|
RTNAME(ValueAt)(storage, i, *out.get());
|
|
descriptorAlmostEqual(*input, *out);
|
|
}
|
|
|
|
// pop and test each descriptor
|
|
for (unsigned i = numToTest; i > 0; --i) {
|
|
const OwningPtr<Descriptor> &input = inputDescriptors[i - 1];
|
|
const bool adendum = getAdendum(i - 1);
|
|
const size_t rank = getRank(i - 1);
|
|
|
|
// buffer to return the descriptor into
|
|
OwningPtr<Descriptor> out = Descriptor::Create(
|
|
boolCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);
|
|
|
|
RTNAME(PopValue)(storage, *out.get());
|
|
descriptorAlmostEqual(*input, *out);
|
|
}
|
|
|
|
RTNAME(DestroyValueStack)(storage);
|
|
}
|
|
|
|
TEST(TemporaryStack, DescriptorStackBasic) {
|
|
const TypeCode code{CFI_type_Bool};
|
|
constexpr size_t elementBytes = 4;
|
|
constexpr size_t rank = 2;
|
|
void *const descriptorPtr = reinterpret_cast<void *>(0xdeadbeef);
|
|
const SubscriptValue extent[rank]{42, 24};
|
|
|
|
StaticDescriptor<rank> testDescriptorStorage[3];
|
|
Descriptor &inputDesc{testDescriptorStorage[0].descriptor()};
|
|
Descriptor &outputDesc{testDescriptorStorage[1].descriptor()};
|
|
Descriptor &outputDesc2{testDescriptorStorage[2].descriptor()};
|
|
inputDesc.Establish(code, elementBytes, descriptorPtr, rank, extent);
|
|
|
|
void *storage = RTNAME(CreateDescriptorStack)(__FILE__, __LINE__);
|
|
ASSERT_NE(storage, nullptr);
|
|
|
|
RTNAME(PushDescriptor)(storage, inputDesc);
|
|
|
|
RTNAME(DescriptorAt)(storage, 0, outputDesc);
|
|
ASSERT_EQ(
|
|
memcmp(&inputDesc, &outputDesc, testDescriptorStorage[0].byteSize), 0);
|
|
|
|
RTNAME(PopDescriptor)(storage, outputDesc2);
|
|
ASSERT_EQ(
|
|
memcmp(&inputDesc, &outputDesc2, testDescriptorStorage[0].byteSize), 0);
|
|
|
|
RTNAME(DestroyDescriptorStack)(storage);
|
|
}
|
|
|
|
TEST(TemporaryStack, DescriptorStackMultiSize) {
|
|
constexpr unsigned numToTest = 42;
|
|
const TypeCode code{CFI_type_Bool};
|
|
constexpr size_t elementBytes = 4;
|
|
const uintptr_t ptrBase = 0xdeadbeef;
|
|
SubscriptValue extent[CFI_MAX_RANK];
|
|
|
|
std::vector<OwningPtr<Descriptor>> inputDescriptors;
|
|
inputDescriptors.reserve(numToTest);
|
|
|
|
void *storage = RTNAME(CreateDescriptorStack)(__FILE__, __LINE__);
|
|
ASSERT_NE(storage, nullptr);
|
|
|
|
// create descriptors with and without adendums
|
|
auto getAdendum = [](unsigned i) { return i % 2; };
|
|
// create descriptors with varying ranks
|
|
auto getRank = [](unsigned i) { return max(i % CFI_MAX_RANK, 1); };
|
|
|
|
// push descriptors of varying sizes and contents
|
|
for (unsigned i = 0; i < numToTest; ++i) {
|
|
const bool adendum = getAdendum(i);
|
|
const size_t rank = getRank(i);
|
|
for (unsigned dim = 0; dim < rank; ++dim) {
|
|
extent[dim] = max(i - dim, 1);
|
|
}
|
|
|
|
// varying pointers
|
|
void *const ptr = reinterpret_cast<void *>(ptrBase + i * elementBytes);
|
|
|
|
const OwningPtr<Descriptor> &desc =
|
|
inputDescriptors.emplace_back(Descriptor::Create(code, elementBytes,
|
|
ptr, rank, extent, CFI_attribute_other, adendum));
|
|
RTNAME(PushDescriptor)(storage, *desc.get());
|
|
}
|
|
|
|
const TypeCode intCode{CFI_type_int8_t};
|
|
// peek and test each descriptor
|
|
for (unsigned i = 0; i < numToTest; ++i) {
|
|
const OwningPtr<Descriptor> &input = inputDescriptors[i];
|
|
const bool adendum = getAdendum(i);
|
|
const size_t rank = getRank(i);
|
|
|
|
// buffer to return the descriptor into
|
|
OwningPtr<Descriptor> out = Descriptor::Create(
|
|
intCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);
|
|
|
|
RTNAME(DescriptorAt)(storage, i, *out.get());
|
|
ASSERT_EQ(memcmp(input.get(), out.get(), input->SizeInBytes()), 0);
|
|
}
|
|
|
|
// pop and test each descriptor
|
|
for (unsigned i = numToTest; i > 0; --i) {
|
|
const OwningPtr<Descriptor> &input = inputDescriptors[i - 1];
|
|
const bool adendum = getAdendum(i - 1);
|
|
const size_t rank = getRank(i - 1);
|
|
|
|
// buffer to return the descriptor into
|
|
OwningPtr<Descriptor> out = Descriptor::Create(
|
|
intCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);
|
|
|
|
RTNAME(PopDescriptor)(storage, *out.get());
|
|
ASSERT_EQ(memcmp(input.get(), out.get(), input->SizeInBytes()), 0);
|
|
}
|
|
|
|
RTNAME(DestroyDescriptorStack)(storage);
|
|
}
|