Skip to content

Commit b01ac51

Browse files
authored
[flang][runtime] add SHAPE runtime interface (#94702)
Add SHAPE runtime API (will be used for assumed-rank, lowering is generating other cases inline). I tried to make it in a way were there is no dynamic allocation in the runtime/deallocation expected to be inserted by inline code for arrays that we know are small (lowering will just always stack allocate a rank 15 array to avoid dynamic stack allocation or heap allocation).
1 parent 97b12df commit b01ac51

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

flang/include/flang/Runtime/inquiry.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,18 @@ extern "C" {
2323

2424
std::int64_t RTDECL(LboundDim)(const Descriptor &array, int dim,
2525
const char *sourceFile = nullptr, int line = 0);
26-
void RTDECL(Ubound)(Descriptor &result, const Descriptor &array, int kind,
27-
const char *sourceFile = nullptr, int line = 0);
26+
27+
void RTDECL(Shape)(void *result, const Descriptor &array, int kind);
28+
2829
std::int64_t RTDECL(Size)(
2930
const Descriptor &array, const char *sourceFile = nullptr, int line = 0);
31+
3032
std::int64_t RTDECL(SizeDim)(const Descriptor &array, int dim,
3133
const char *sourceFile = nullptr, int line = 0);
3234

35+
void RTDECL(Ubound)(Descriptor &result, const Descriptor &array, int kind,
36+
const char *sourceFile = nullptr, int line = 0);
37+
3338
} // extern "C"
3439
} // namespace Fortran::runtime
3540
#endif // FORTRAN_RUNTIME_INQUIRY_H_

flang/runtime/inquiry.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@
1818

1919
namespace Fortran::runtime {
2020

21+
template <int KIND> struct RawStoreIntegerAt {
22+
RT_API_ATTRS void operator()(
23+
void *contiguousIntegerArray, std::size_t at, std::int64_t value) const {
24+
reinterpret_cast<Fortran::runtime::CppTypeFor<
25+
Fortran::common::TypeCategory::Integer, KIND> *>(
26+
contiguousIntegerArray)[at] = value;
27+
}
28+
};
29+
2130
extern "C" {
2231
std::int64_t RTDEF(LboundDim)(
2332
const Descriptor &array, int dim, const char *sourceFile, int line) {
@@ -76,5 +85,15 @@ std::int64_t RTDEF(SizeDim)(
7685
return static_cast<std::int64_t>(dimension.Extent());
7786
}
7887

88+
void RTDEF(Shape)(void *result, const Descriptor &array, int kind) {
89+
Terminator terminator{__FILE__, __LINE__};
90+
INTERNAL_CHECK(array.rank() <= common::maxRank);
91+
for (SubscriptValue i{0}; i < array.rank(); ++i) {
92+
const Dimension &dimension{array.GetDimension(i)};
93+
Fortran::runtime::ApplyIntegerKind<RawStoreIntegerAt, void>(
94+
kind, terminator, result, i, dimension.Extent());
95+
}
96+
}
97+
7998
} // extern "C"
8099
} // namespace Fortran::runtime

flang/unittests/Runtime/Inquiry.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,34 @@ TEST(Inquiry, Size) {
7676
EXPECT_EQ(RTNAME(SizeDim)(*array, 2, __FILE__, __LINE__), std::int64_t{3});
7777
EXPECT_EQ(RTNAME(Size)(*array, __FILE__, __LINE__), std::int64_t{6});
7878
}
79+
80+
TEST(Inquiry, Shape) {
81+
// ARRAY 1 3 5
82+
// 2 4 6
83+
auto array{MakeArray<TypeCategory::Integer, 4>(
84+
std::vector<int>{2, 3}, std::vector<std::int32_t>{1, 2, 3, 4, 5, 6})};
85+
86+
// SHAPE(ARRAY, KIND=1)
87+
auto int8Result{
88+
MakeArray<TypeCategory::Integer, 1>(std::vector<int>{array->rank()},
89+
std::vector<std::int8_t>(array->rank(), 0))};
90+
RTNAME(Shape)(int8Result->raw().base_addr, *array, /*KIND=*/1);
91+
EXPECT_EQ(*int8Result->ZeroBasedIndexedElement<std::int8_t>(0), 2);
92+
EXPECT_EQ(*int8Result->ZeroBasedIndexedElement<std::int8_t>(1), 3);
93+
94+
// SHAPE(ARRAY, KIND=4)
95+
auto int32Result{
96+
MakeArray<TypeCategory::Integer, 4>(std::vector<int>{array->rank()},
97+
std::vector<std::int32_t>(array->rank(), 0))};
98+
RTNAME(Shape)(int32Result->raw().base_addr, *array, /*KIND=*/4);
99+
EXPECT_EQ(*int32Result->ZeroBasedIndexedElement<std::int32_t>(0), 2);
100+
EXPECT_EQ(*int32Result->ZeroBasedIndexedElement<std::int32_t>(1), 3);
101+
102+
// SHAPE(ARRAY, KIND=8)
103+
auto int64Result{
104+
MakeArray<TypeCategory::Integer, 8>(std::vector<int>{array->rank()},
105+
std::vector<std::int64_t>(array->rank(), 0))};
106+
RTNAME(Shape)(int64Result->raw().base_addr, *array, /*KIND=*/8);
107+
EXPECT_EQ(*int64Result->ZeroBasedIndexedElement<std::int64_t>(0), 2);
108+
EXPECT_EQ(*int64Result->ZeroBasedIndexedElement<std::int64_t>(1), 3);
109+
}

0 commit comments

Comments
 (0)