274 lines · cpp
1//===-- unittests/Runtime/Pointer.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 "flang-rt/runtime/descriptor.h"10#include "tools.h"11#include "gtest/gtest.h"12#include <regex>13 14using namespace Fortran::runtime;15 16TEST(Descriptor, FixedStride) {17 StaticDescriptor<4> staticDesc[2];18 Descriptor &descriptor{staticDesc[0].descriptor()};19 using Type = std::int32_t;20 Type data[8][8][8];21 constexpr int four{static_cast<int>(sizeof data[0][0][0])};22 TypeCode integer{TypeCategory::Integer, four};23 // Scalar24 descriptor.Establish(integer, four, data, 0);25 EXPECT_TRUE(descriptor.IsContiguous());26 EXPECT_EQ(descriptor.FixedStride().value_or(-666), four);27 // Empty vector28 SubscriptValue extent[3]{0, 0, 0};29 descriptor.Establish(integer, four, data, 1, extent);30 EXPECT_TRUE(descriptor.IsContiguous());31 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);32 // Contiguous vector (0:7:1)33 extent[0] = 8;34 descriptor.Establish(integer, four, data, 1, extent);35 ASSERT_EQ(descriptor.rank(), 1);36 ASSERT_EQ(descriptor.Elements(), 8u);37 ASSERT_EQ(descriptor.ElementBytes(), static_cast<unsigned>(four));38 ASSERT_EQ(descriptor.GetDimension(0).LowerBound(), 0);39 ASSERT_EQ(descriptor.GetDimension(0).ByteStride(), four);40 ASSERT_EQ(descriptor.GetDimension(0).Extent(), 8);41 EXPECT_TRUE(descriptor.IsContiguous());42 EXPECT_EQ(descriptor.FixedStride().value_or(-666), four);43 // Contiguous reverse vector (7:0:-1)44 descriptor.GetDimension(0).SetByteStride(-four);45 EXPECT_FALSE(descriptor.IsContiguous());46 EXPECT_EQ(descriptor.FixedStride().value_or(-666), -four);47 // Discontiguous vector (0:6:2)48 descriptor.GetDimension(0).SetExtent(4);49 descriptor.GetDimension(0).SetByteStride(2 * four);50 EXPECT_FALSE(descriptor.IsContiguous());51 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 2 * four);52 // Empty matrix53 extent[0] = 0;54 descriptor.Establish(integer, four, data, 2, extent);55 EXPECT_TRUE(descriptor.IsContiguous());56 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);57 // Contiguous matrix (0:7, 0:7)58 extent[0] = extent[1] = 8;59 descriptor.Establish(integer, four, data, 2, extent);60 EXPECT_TRUE(descriptor.IsContiguous());61 EXPECT_EQ(descriptor.FixedStride().value_or(-666), four);62 // Contiguous row (0:7, 0)63 descriptor.GetDimension(1).SetExtent(1);64 EXPECT_TRUE(descriptor.IsContiguous());65 EXPECT_EQ(descriptor.FixedStride().value_or(-666), four);66 // Contiguous column (0, 0:7)67 descriptor.GetDimension(0).SetExtent(1);68 descriptor.GetDimension(1).SetExtent(7);69 descriptor.GetDimension(1).SetByteStride(8 * four);70 EXPECT_FALSE(descriptor.IsContiguous());71 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 8 * four);72 // Contiguous reverse row (7:0:-1, 0)73 descriptor.GetDimension(0).SetExtent(8);74 descriptor.GetDimension(0).SetByteStride(-four);75 descriptor.GetDimension(1).SetExtent(1);76 EXPECT_FALSE(descriptor.IsContiguous());77 EXPECT_EQ(descriptor.FixedStride().value_or(-666), -four);78 // Contiguous reverse column (0, 7:0:-1)79 descriptor.GetDimension(0).SetExtent(1);80 descriptor.GetDimension(0).SetByteStride(four);81 descriptor.GetDimension(1).SetExtent(7);82 descriptor.GetDimension(1).SetByteStride(8 * -four);83 EXPECT_FALSE(descriptor.IsContiguous());84 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 8 * -four);85 // Discontiguous row (0:6:2, 0)86 descriptor.GetDimension(0).SetExtent(4);87 descriptor.GetDimension(0).SetByteStride(2 * four);88 descriptor.GetDimension(1).SetExtent(1);89 descriptor.GetDimension(1).SetByteStride(four);90 EXPECT_FALSE(descriptor.IsContiguous());91 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 2 * four);92 // Discontiguous column (0, 0:6:2)93 descriptor.GetDimension(0).SetExtent(1);94 descriptor.GetDimension(0).SetByteStride(four);95 descriptor.GetDimension(1).SetExtent(4);96 descriptor.GetDimension(1).SetByteStride(8 * 2 * four);97 EXPECT_FALSE(descriptor.IsContiguous());98 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 8 * 2 * four);99 // Discontiguous reverse row (7:1:-2, 0)100 descriptor.GetDimension(0).SetExtent(4);101 descriptor.GetDimension(0).SetByteStride(-2 * four);102 descriptor.GetDimension(1).SetExtent(1);103 descriptor.GetDimension(1).SetByteStride(four);104 EXPECT_FALSE(descriptor.IsContiguous());105 EXPECT_EQ(descriptor.FixedStride().value_or(-666), -2 * four);106 // Discontiguous reverse column (0, 7:1:-2)107 descriptor.GetDimension(0).SetExtent(1);108 descriptor.GetDimension(0).SetByteStride(four);109 descriptor.GetDimension(1).SetExtent(4);110 descriptor.GetDimension(1).SetByteStride(8 * -2 * four);111 EXPECT_FALSE(descriptor.IsContiguous());112 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 8 * -2 * four);113 // Discontiguous rows (0:6:2, 0:1)114 descriptor.GetDimension(0).SetExtent(4);115 descriptor.GetDimension(0).SetByteStride(2 * four);116 descriptor.GetDimension(1).SetExtent(2);117 descriptor.GetDimension(1).SetByteStride(8 * four);118 EXPECT_FALSE(descriptor.IsContiguous());119 EXPECT_FALSE(descriptor.FixedStride().has_value());120 // Discontiguous columns (0:1, 0:6:2)121 descriptor.GetDimension(0).SetExtent(2);122 descriptor.GetDimension(0).SetByteStride(four);123 descriptor.GetDimension(1).SetExtent(4);124 descriptor.GetDimension(1).SetByteStride(8 * four);125 EXPECT_FALSE(descriptor.IsContiguous());126 EXPECT_FALSE(descriptor.FixedStride().has_value());127 // Empty 3-D array128 extent[0] = extent[1] = extent[2] = 0;129 ;130 descriptor.Establish(integer, four, data, 3, extent);131 EXPECT_TRUE(descriptor.IsContiguous());132 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);133 // Contiguous 3-D array (0:7, 0:7, 0:7)134 extent[0] = extent[1] = extent[2] = 8;135 descriptor.Establish(integer, four, data, 3, extent);136 EXPECT_TRUE(descriptor.IsContiguous());137 EXPECT_EQ(descriptor.FixedStride().value_or(-666), four);138 // Discontiguous 3-D array (0:7, 0:6:2, 0:6:2)139 descriptor.GetDimension(1).SetExtent(4);140 descriptor.GetDimension(1).SetByteStride(8 * 2 * four);141 descriptor.GetDimension(2).SetExtent(4);142 descriptor.GetDimension(2).SetByteStride(8 * 8 * 2 * four);143 EXPECT_FALSE(descriptor.IsContiguous());144 EXPECT_FALSE(descriptor.FixedStride().has_value());145 // Discontiguous-looking empty 3-D array (0:-1, 0:6:2, 0:6:2)146 descriptor.GetDimension(0).SetExtent(0);147 EXPECT_TRUE(descriptor.IsContiguous());148 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);149 // Discontiguous-looking empty 3-D array (0:6:2, 0:-1, 0:6:2)150 descriptor.GetDimension(0).SetExtent(4);151 descriptor.GetDimension(0).SetByteStride(2 * four);152 descriptor.GetDimension(1).SetExtent(0);153 EXPECT_TRUE(descriptor.IsContiguous());154 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);155 // Discontiguous-looking empty 3-D array (0:6:2, 0:6:2, 0:-1)156 descriptor.GetDimension(1).SetExtent(4);157 descriptor.GetDimension(1).SetExtent(8 * 2 * four);158 descriptor.GetDimension(2).SetExtent(0);159 EXPECT_TRUE(descriptor.IsContiguous());160 EXPECT_EQ(descriptor.FixedStride().value_or(-666), 0);161}162 163static std::string getAddrFilteredContent(FILE *fin) {164 rewind(fin);165 std::ostringstream content;166 char buffer[1024];167 size_t bytes_read;168 while ((bytes_read = fread(buffer, 1, sizeof(buffer), fin)) > 0) {169 content.write(buffer, bytes_read);170 }171 return std::regex_replace(172 content.str(), std::regex("(0x[0-9a-fA-F]*)"), "[address]");173}174 175TEST(Descriptor, Dump) {176 StaticDescriptor<4> staticDesc[2];177 Descriptor &descriptor{staticDesc[0].descriptor()};178 using Type = std::int32_t;179 Type data[8][8][8];180 constexpr int four{static_cast<int>(sizeof data[0][0][0])};181 TypeCode integer{TypeCategory::Integer, four};182 // Scalar183 descriptor.Establish(integer, four, data, 0);184 FILE *tmpf = tmpfile();185 ASSERT_TRUE(tmpf) << "tmpfile returned NULL";186 auto resetTmpFile = [tmpf]() {187 rewind(tmpf);188 ftruncate(fileno(tmpf), 0);189 };190 191 descriptor.Dump(tmpf, /*dumpRawType=*/false);192 // also dump as CFI type193 descriptor.Dump(tmpf, /*dumpRawType=*/true);194 std::string output = getAddrFilteredContent(tmpf);195 ASSERT_STREQ(output.c_str(),196 "Descriptor @ [address]:\n"197 " base_addr [address]\n"198 " elem_len 4\n"199 " version 20240719\n"200 " scalar\n"201 " type 9 \"INTEGER(kind=4)\"\n"202 " attribute 0\n"203 " extra 0\n"204 " addendum 0\n"205 " alloc_idx 0\n"206 "Descriptor @ [address]:\n"207 " base_addr [address]\n"208 " elem_len 4\n"209 " version 20240719\n"210 " scalar\n"211 " type 9 \"CFI_type_int32_t\"\n"212 " attribute 0\n"213 " extra 0\n"214 " addendum 0\n"215 " alloc_idx 0\n");216 217 // Contiguous matrix (0:7, 0:7)218 SubscriptValue extent[3]{8, 8, 8};219 descriptor.Establish(integer, four, data, 2, extent);220 resetTmpFile();221 descriptor.Dump(tmpf, /*dumpRawType=*/false);222 output = getAddrFilteredContent(tmpf);223 ASSERT_STREQ(output.c_str(),224 "Descriptor @ [address]:\n"225 " base_addr [address]\n"226 " elem_len 4\n"227 " version 20240719\n"228 " rank 2\n"229 " type 9 \"INTEGER(kind=4)\"\n"230 " attribute 0\n"231 " extra 0\n"232 " addendum 0\n"233 " alloc_idx 0\n"234 " dim[0] lower_bound 0\n"235 " extent 8\n"236 " sm 4\n"237 " dim[1] lower_bound 0\n"238 " extent 8\n"239 " sm 32\n");240 241 TypeCode real{TypeCategory::Real, four};242 // Discontiguous real 3-D array (0:7, 0:6:2, 0:6:2)243 descriptor.Establish(real, four, data, 3, extent);244 descriptor.GetDimension(1).SetExtent(4);245 descriptor.GetDimension(1).SetByteStride(8 * 2 * four);246 descriptor.GetDimension(2).SetExtent(4);247 descriptor.GetDimension(2).SetByteStride(8 * 8 * 2 * four);248 249 resetTmpFile();250 descriptor.Dump(tmpf, /*dumpRawType=*/false);251 output = getAddrFilteredContent(tmpf);252 ASSERT_STREQ(output.c_str(),253 "Descriptor @ [address]:\n"254 " base_addr [address]\n"255 " elem_len 4\n"256 " version 20240719\n"257 " rank 3\n"258 " type 27 \"REAL(kind=4)\"\n"259 " attribute 0\n"260 " extra 0\n"261 " addendum 0\n"262 " alloc_idx 0\n"263 " dim[0] lower_bound 0\n"264 " extent 8\n"265 " sm 4\n"266 " dim[1] lower_bound 0\n"267 " extent 4\n"268 " sm 64\n"269 " dim[2] lower_bound 0\n"270 " extent 4\n"271 " sm 512\n");272 fclose(tmpf);273}274