brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.1 KiB · 6572584 Raw
266 lines · cpp
1//===-- 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-exception6//7//===----------------------------------------------------------------------===//8 9#include "gtest/gtest.h"10#include "flang-rt/runtime/descriptor.h"11#include "flang-rt/runtime/tools.h"12#include "flang-rt/runtime/type-code.h"13#include "flang/Common/ISO_Fortran_binding_wrapper.h"14#include "flang/Runtime/allocatable.h"15#include "flang/Runtime/cpp-type.h"16#include "flang/Runtime/temporary-stack.h"17#include <vector>18 19using namespace Fortran::runtime;20 21// true if two descriptors are otherwise identical, except for different data22// pointers. The pointed-to elements are bit for bit identical.23static 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();27 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);33 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);37 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);46  }47}48 49TEST(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};55 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);61 62  inputDesc.Allocate(kNoAsyncObject);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;67  }68 69  void *storage = RTNAME(CreateValueStack)(__FILE__, __LINE__);70  ASSERT_NE(storage, nullptr);71 72  RTNAME(PushValue)(storage, inputDesc);73 74  RTNAME(ValueAt)(storage, 0, outputDesc);75  descriptorAlmostEqual(inputDesc, outputDesc);76 77  RTNAME(PopValue)(storage, outputDesc2);78  descriptorAlmostEqual(inputDesc, outputDesc2);79 80  RTNAME(DestroyValueStack)(storage);81}82 83static unsigned max(unsigned x, unsigned y) {84  if (x > y) {85    return x;86  }87  return y;88}89 90TEST(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];95 96  std::vector<OwningPtr<Descriptor>> inputDescriptors;97  inputDescriptors.reserve(numToTest);98 99  void *storage = RTNAME(CreateValueStack)(__FILE__, __LINE__);100  ASSERT_NE(storage, nullptr);101 102  // create descriptors with and without adendums103  auto getAdendum = [](unsigned i) { return i % 2; };104  // create descriptors with varying ranks105  auto getRank = [](unsigned i) { return max(i % 8, 1); };106 107  // push descriptors of varying sizes and contents108  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;113    }114 115    const OwningPtr<Descriptor> &desc =116        inputDescriptors.emplace_back(Descriptor::Create(code, elementBytes,117            nullptr, rank, extent, CFI_attribute_allocatable, adendum));118 119    // Descriptor::Establish doesn't initialise the extents if baseaddr is null120    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;125    }126    desc->Allocate(kNoAsyncObject);127 128    // fill the array with some data to test129    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;133    }134 135    RTNAME(PushValue)(storage, *desc.get());136  }137 138  const TypeCode boolCode{CFI_type_Bool};139  // peek and test each descriptor140  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);144 145    // buffer to return the descriptor into146    OwningPtr<Descriptor> out = Descriptor::Create(147        boolCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);148 149    (void)input;150    RTNAME(ValueAt)(storage, i, *out.get());151    descriptorAlmostEqual(*input, *out);152  }153 154  // pop and test each descriptor155  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);159 160    // buffer to return the descriptor into161    OwningPtr<Descriptor> out = Descriptor::Create(162        boolCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);163 164    RTNAME(PopValue)(storage, *out.get());165    descriptorAlmostEqual(*input, *out);166  }167 168  RTNAME(DestroyValueStack)(storage);169}170 171TEST(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};177 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);183 184  void *storage = RTNAME(CreateDescriptorStack)(__FILE__, __LINE__);185  ASSERT_NE(storage, nullptr);186 187  RTNAME(PushDescriptor)(storage, inputDesc);188 189  RTNAME(DescriptorAt)(storage, 0, outputDesc);190  ASSERT_EQ(191      memcmp(&inputDesc, &outputDesc, testDescriptorStorage[0].byteSize), 0);192 193  RTNAME(PopDescriptor)(storage, outputDesc2);194  ASSERT_EQ(195      memcmp(&inputDesc, &outputDesc2, testDescriptorStorage[0].byteSize), 0);196 197  RTNAME(DestroyDescriptorStack)(storage);198}199 200TEST(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];206 207  std::vector<OwningPtr<Descriptor>> inputDescriptors;208  inputDescriptors.reserve(numToTest);209 210  void *storage = RTNAME(CreateDescriptorStack)(__FILE__, __LINE__);211  ASSERT_NE(storage, nullptr);212 213  // create descriptors with and without adendums214  auto getAdendum = [](unsigned i) { return i % 2; };215  // create descriptors with varying ranks216  auto getRank = [](unsigned i) { return max(i % CFI_MAX_RANK, 1); };217 218  // push descriptors of varying sizes and contents219  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);224    }225 226    // varying pointers227    void *const ptr = reinterpret_cast<void *>(ptrBase + i * elementBytes);228 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());233  }234 235  const TypeCode intCode{CFI_type_int8_t};236  // peek and test each descriptor237  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);241 242    // buffer to return the descriptor into243    OwningPtr<Descriptor> out = Descriptor::Create(244        intCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);245 246    RTNAME(DescriptorAt)(storage, i, *out.get());247    ASSERT_EQ(memcmp(input.get(), out.get(), input->SizeInBytes()), 0);248  }249 250  // pop and test each descriptor251  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);255 256    // buffer to return the descriptor into257    OwningPtr<Descriptor> out = Descriptor::Create(258        intCode, 1, nullptr, rank, extent, CFI_attribute_other, adendum);259 260    RTNAME(PopDescriptor)(storage, *out.get());261    ASSERT_EQ(memcmp(input.get(), out.get(), input->SizeInBytes()), 0);262  }263 264  RTNAME(DestroyDescriptorStack)(storage);265}266