CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
318 lines
13 KiB
C++
318 lines
13 KiB
C++
//===-- unittests/Runtime/Pointer.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 "flang-rt/runtime/descriptor.h"
|
|
#include "tools.h"
|
|
#include "gtest/gtest.h"
|
|
#include <regex>
|
|
|
|
using namespace Fortran::runtime;
|
|
|
|
TEST(Descriptor, FixedStride) {
|
|
StaticDescriptor<4> staticDesc[2];
|
|
Descriptor &descriptor{staticDesc[0].descriptor()};
|
|
using Type = std::int32_t;
|
|
Type data[8][8][8];
|
|
constexpr int four{static_cast<int>(sizeof data[0][0][0])};
|
|
TypeCode integer{TypeCategory::Integer, four};
|
|
// Scalar
|
|
descriptor.Establish(integer, four, data, 0);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), four);
|
|
// Empty vector
|
|
SubscriptValue extent[3]{0, 0, 0};
|
|
descriptor.Establish(integer, four, data, 1, extent);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);
|
|
// Contiguous vector (0:7:1)
|
|
extent[0] = 8;
|
|
descriptor.Establish(integer, four, data, 1, extent);
|
|
ASSERT_EQ(descriptor.rank(), 1);
|
|
ASSERT_EQ(descriptor.Elements(), 8u);
|
|
ASSERT_EQ(descriptor.ElementBytes(), static_cast<unsigned>(four));
|
|
ASSERT_EQ(descriptor.GetDimension(0).LowerBound(), 0);
|
|
ASSERT_EQ(descriptor.GetDimension(0).ByteStride(), four);
|
|
ASSERT_EQ(descriptor.GetDimension(0).Extent(), 8);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), four);
|
|
// Contiguous reverse vector (7:0:-1)
|
|
descriptor.GetDimension(0).SetByteStride(-four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), -four);
|
|
// Discontiguous vector (0:6:2)
|
|
descriptor.GetDimension(0).SetExtent(4);
|
|
descriptor.GetDimension(0).SetByteStride(2 * four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 2 * four);
|
|
// Empty matrix
|
|
extent[0] = 0;
|
|
descriptor.Establish(integer, four, data, 2, extent);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);
|
|
// Contiguous matrix (0:7, 0:7)
|
|
extent[0] = extent[1] = 8;
|
|
descriptor.Establish(integer, four, data, 2, extent);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), four);
|
|
// Contiguous row (0:7, 0)
|
|
descriptor.GetDimension(1).SetExtent(1);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), four);
|
|
// Contiguous column (0, 0:7)
|
|
descriptor.GetDimension(0).SetExtent(1);
|
|
descriptor.GetDimension(1).SetExtent(7);
|
|
descriptor.GetDimension(1).SetByteStride(8 * four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 8 * four);
|
|
// Contiguous reverse row (7:0:-1, 0)
|
|
descriptor.GetDimension(0).SetExtent(8);
|
|
descriptor.GetDimension(0).SetByteStride(-four);
|
|
descriptor.GetDimension(1).SetExtent(1);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), -four);
|
|
// Contiguous reverse column (0, 7:0:-1)
|
|
descriptor.GetDimension(0).SetExtent(1);
|
|
descriptor.GetDimension(0).SetByteStride(four);
|
|
descriptor.GetDimension(1).SetExtent(7);
|
|
descriptor.GetDimension(1).SetByteStride(8 * -four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 8 * -four);
|
|
// Discontiguous row (0:6:2, 0)
|
|
descriptor.GetDimension(0).SetExtent(4);
|
|
descriptor.GetDimension(0).SetByteStride(2 * four);
|
|
descriptor.GetDimension(1).SetExtent(1);
|
|
descriptor.GetDimension(1).SetByteStride(four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 2 * four);
|
|
// Discontiguous column (0, 0:6:2)
|
|
descriptor.GetDimension(0).SetExtent(1);
|
|
descriptor.GetDimension(0).SetByteStride(four);
|
|
descriptor.GetDimension(1).SetExtent(4);
|
|
descriptor.GetDimension(1).SetByteStride(8 * 2 * four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 8 * 2 * four);
|
|
// Discontiguous reverse row (7:1:-2, 0)
|
|
descriptor.GetDimension(0).SetExtent(4);
|
|
descriptor.GetDimension(0).SetByteStride(-2 * four);
|
|
descriptor.GetDimension(1).SetExtent(1);
|
|
descriptor.GetDimension(1).SetByteStride(four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), -2 * four);
|
|
// Discontiguous reverse column (0, 7:1:-2)
|
|
descriptor.GetDimension(0).SetExtent(1);
|
|
descriptor.GetDimension(0).SetByteStride(four);
|
|
descriptor.GetDimension(1).SetExtent(4);
|
|
descriptor.GetDimension(1).SetByteStride(8 * -2 * four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 8 * -2 * four);
|
|
// Discontiguous rows (0:6:2, 0:1)
|
|
descriptor.GetDimension(0).SetExtent(4);
|
|
descriptor.GetDimension(0).SetByteStride(2 * four);
|
|
descriptor.GetDimension(1).SetExtent(2);
|
|
descriptor.GetDimension(1).SetByteStride(8 * four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_FALSE(descriptor.FixedStride().has_value());
|
|
// Discontiguous columns (0:1, 0:6:2)
|
|
descriptor.GetDimension(0).SetExtent(2);
|
|
descriptor.GetDimension(0).SetByteStride(four);
|
|
descriptor.GetDimension(1).SetExtent(4);
|
|
descriptor.GetDimension(1).SetByteStride(8 * four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_FALSE(descriptor.FixedStride().has_value());
|
|
// Empty 3-D array
|
|
extent[0] = extent[1] = extent[2] = 0;
|
|
;
|
|
descriptor.Establish(integer, four, data, 3, extent);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);
|
|
// Contiguous 3-D array (0:7, 0:7, 0:7)
|
|
extent[0] = extent[1] = extent[2] = 8;
|
|
descriptor.Establish(integer, four, data, 3, extent);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), four);
|
|
// Discontiguous 3-D array (0:7, 0:6:2, 0:6:2)
|
|
descriptor.GetDimension(1).SetExtent(4);
|
|
descriptor.GetDimension(1).SetByteStride(8 * 2 * four);
|
|
descriptor.GetDimension(2).SetExtent(4);
|
|
descriptor.GetDimension(2).SetByteStride(8 * 8 * 2 * four);
|
|
EXPECT_FALSE(descriptor.IsContiguous());
|
|
EXPECT_FALSE(descriptor.FixedStride().has_value());
|
|
// Discontiguous-looking empty 3-D array (0:-1, 0:6:2, 0:6:2)
|
|
descriptor.GetDimension(0).SetExtent(0);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);
|
|
// Discontiguous-looking empty 3-D array (0:6:2, 0:-1, 0:6:2)
|
|
descriptor.GetDimension(0).SetExtent(4);
|
|
descriptor.GetDimension(0).SetByteStride(2 * four);
|
|
descriptor.GetDimension(1).SetExtent(0);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);
|
|
// Discontiguous-looking empty 3-D array (0:6:2, 0:6:2, 0:-1)
|
|
descriptor.GetDimension(1).SetExtent(4);
|
|
descriptor.GetDimension(1).SetExtent(8 * 2 * four);
|
|
descriptor.GetDimension(2).SetExtent(0);
|
|
EXPECT_TRUE(descriptor.IsContiguous());
|
|
EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);
|
|
}
|
|
|
|
// The test below uses file operations that have nuances across multiple
|
|
// platforms. Hence limit coverage by linux only unless wider coverage
|
|
// should be required.
|
|
#if defined(__linux__) && !defined(__ANDROID__)
|
|
TEST(Descriptor, Dump) {
|
|
StaticDescriptor<4> staticDesc[2];
|
|
Descriptor &descriptor{staticDesc[0].descriptor()};
|
|
using Type = std::int32_t;
|
|
Type data[8][8][8];
|
|
constexpr int four{static_cast<int>(sizeof data[0][0][0])};
|
|
TypeCode integer{TypeCategory::Integer, four};
|
|
// Scalar
|
|
descriptor.Establish(integer, four, data, 0);
|
|
FILE *tmpf{tmpfile()};
|
|
ASSERT_TRUE(tmpf) << "tmpfile returned NULL";
|
|
auto resetTmpFile = [tmpf]() {
|
|
fflush(tmpf);
|
|
rewind(tmpf);
|
|
ftruncate(fileno(tmpf), 0);
|
|
};
|
|
|
|
auto getAddrFilteredContent = [tmpf]() -> std::string {
|
|
rewind(tmpf);
|
|
std::ostringstream content;
|
|
char buffer[1024];
|
|
size_t bytes_read;
|
|
while ((bytes_read = fread(buffer, 1, sizeof(buffer), tmpf)) > 0) {
|
|
content.write(buffer, bytes_read);
|
|
}
|
|
|
|
return std::regex_replace(
|
|
std::regex_replace(content.str(), std::regex("Descriptor @.*:"),
|
|
"Descriptor @ [addr]:"),
|
|
std::regex("base_addr .*"), "base_addr [addr]");
|
|
};
|
|
|
|
descriptor.Dump(tmpf, /*dumpRawType=*/false);
|
|
// also dump as CFI type
|
|
descriptor.Dump(tmpf, /*dumpRawType=*/true);
|
|
std::string output{getAddrFilteredContent()};
|
|
ASSERT_STREQ(output.c_str(),
|
|
"Descriptor @ [addr]:\n"
|
|
" base_addr [addr]\n"
|
|
" elem_len 4\n"
|
|
" version 20240719\n"
|
|
" rank 0 (scalar)\n"
|
|
" type 9 \"INTEGER(kind=4)\"\n"
|
|
" attribute 0\n"
|
|
" extra 0\n"
|
|
" addendum 0\n"
|
|
" alloc_idx 0\n"
|
|
"Descriptor @ [addr]:\n"
|
|
" base_addr [addr]\n"
|
|
" elem_len 4\n"
|
|
" version 20240719\n"
|
|
" rank 0 (scalar)\n"
|
|
" type 9 \"CFI_type_int32_t\"\n"
|
|
" attribute 0\n"
|
|
" extra 0\n"
|
|
" addendum 0\n"
|
|
" alloc_idx 0\n");
|
|
|
|
// Contiguous matrix (0:7, 0:7)
|
|
SubscriptValue extent[3]{8, 8, 8};
|
|
descriptor.Establish(integer, four, data, 2, extent);
|
|
resetTmpFile();
|
|
descriptor.Dump(tmpf, /*dumpRawType=*/false);
|
|
output = getAddrFilteredContent();
|
|
ASSERT_STREQ(output.c_str(),
|
|
"Descriptor @ [addr]:\n"
|
|
" base_addr [addr]\n"
|
|
" elem_len 4\n"
|
|
" version 20240719\n"
|
|
" rank 2\n"
|
|
" type 9 \"INTEGER(kind=4)\"\n"
|
|
" attribute 0\n"
|
|
" extra 0\n"
|
|
" addendum 0\n"
|
|
" alloc_idx 0\n"
|
|
" dim[0] lower_bound 0\n"
|
|
" extent 8\n"
|
|
" sm 4\n"
|
|
" dim[1] lower_bound 0\n"
|
|
" extent 8\n"
|
|
" sm 32\n");
|
|
|
|
TypeCode real{TypeCategory::Real, four};
|
|
// Discontiguous real 3-D array (0:7, 0:6:2, 0:6:2)
|
|
descriptor.Establish(real, four, data, 3, extent);
|
|
descriptor.GetDimension(1).SetExtent(4);
|
|
descriptor.GetDimension(1).SetByteStride(8 * 2 * four);
|
|
descriptor.GetDimension(2).SetExtent(4);
|
|
descriptor.GetDimension(2).SetByteStride(8 * 8 * 2 * four);
|
|
|
|
resetTmpFile();
|
|
descriptor.Dump(tmpf, /*dumpRawType=*/false);
|
|
output = getAddrFilteredContent();
|
|
ASSERT_STREQ(output.c_str(),
|
|
"Descriptor @ [addr]:\n"
|
|
" base_addr [addr]\n"
|
|
" elem_len 4\n"
|
|
" version 20240719\n"
|
|
" rank 3\n"
|
|
" type 27 \"REAL(kind=4)\"\n"
|
|
" attribute 0\n"
|
|
" extra 0\n"
|
|
" addendum 0\n"
|
|
" alloc_idx 0\n"
|
|
" dim[0] lower_bound 0\n"
|
|
" extent 8\n"
|
|
" sm 4\n"
|
|
" dim[1] lower_bound 0\n"
|
|
" extent 4\n"
|
|
" sm 64\n"
|
|
" dim[2] lower_bound 0\n"
|
|
" extent 4\n"
|
|
" sm 512\n");
|
|
fclose(tmpf);
|
|
}
|
|
#endif // defined(__linux__) && !defined(__ANDROID__)
|
|
|
|
// Verify that Descriptor::BytesFor returns the correct storage size
|
|
// for Real and Complex types, especially for kind=10 where the x87
|
|
// 80-bit extended precision value is stored in a 16-byte container.
|
|
TEST(Descriptor, BytesForRealAndComplex) {
|
|
using TC = TypeCategory;
|
|
// Real kinds: storage size should account for container padding
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Real, 2), 2u);
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Real, 3), 2u);
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Real, 4), 4u);
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Real, 8), 8u);
|
|
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \
|
|
defined(_M_IX86)
|
|
// x87: 80-bit in 128-bit container
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Real, 10), 16u);
|
|
#endif
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Real, 16), 16u);
|
|
// Complex kinds: should be twice the Real storage size
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 2), 4u);
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 3), 4u);
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 4), 8u);
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 8), 16u);
|
|
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \
|
|
defined(_M_IX86)
|
|
// x87: 2 * 16 bytes
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 10), 32u);
|
|
#endif
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Complex, 16), 32u);
|
|
// Integer and Logical kinds: storage size equals the kind value
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Integer, 1), 1u);
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Integer, 4), 4u);
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Integer, 8), 8u);
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Logical, 1), 1u);
|
|
EXPECT_EQ(Descriptor::BytesFor(TC::Logical, 4), 4u);
|
|
}
|