Change the flang reshape runtime routine interface to use a result

argument instead of a result result object.

Change the reshape flang unit test to use the new interface. Also, add an
order argument to exercise the order subscript code in the rehsape runtime
routine.

Differential Revision: https://reviews.llvm.org/D104586
This commit is contained in:
Mark Leair 2021-06-24 16:55:45 -07:00
parent d6a91f6c56
commit a103402288
3 changed files with 30 additions and 51 deletions

View File

@ -350,9 +350,9 @@ void RTNAME(Pack)(Descriptor &result, const Descriptor &source,
}
}
} // extern "C" - TODO put Reshape under extern "C"
// RESHAPE
// F2018 16.9.163
OwningPtr<Descriptor> RTNAME(Reshape)(const Descriptor &source,
void RTNAME(Reshape)(Descriptor &result, const Descriptor &source,
const Descriptor &shape, const Descriptor *pad, const Descriptor *order,
const char *sourceFile, int line) {
// Compute and check the rank of the result.
@ -394,9 +394,10 @@ OwningPtr<Descriptor> RTNAME(Reshape)(const Descriptor &source,
RUNTIME_CHECK(terminator, order->GetDimension(0).Extent() == resultRank);
std::uint64_t values{0};
SubscriptValue orderSubscript{order->GetDimension(0).LowerBound()};
std::size_t orderElementBytes{order->ElementBytes()};
for (SubscriptValue j{0}; j < resultRank; ++j, ++orderSubscript) {
auto k{GetInt64(order->OffsetElement<char>(orderSubscript),
shapeElementBytes, terminator)};
auto k{GetInt64(order->Element<char>(&orderSubscript), orderElementBytes,
terminator)};
RUNTIME_CHECK(
terminator, k >= 1 && k <= resultRank && !((values >> k) & 1));
values |= std::uint64_t{1} << k;
@ -408,64 +409,33 @@ OwningPtr<Descriptor> RTNAME(Reshape)(const Descriptor &source,
}
}
// Create and populate the result's descriptor.
const DescriptorAddendum *sourceAddendum{source.Addendum()};
const typeInfo::DerivedType *sourceDerivedType{
sourceAddendum ? sourceAddendum->derivedType() : nullptr};
OwningPtr<Descriptor> result;
if (sourceDerivedType) {
result = Descriptor::Create(*sourceDerivedType, nullptr, resultRank,
resultExtent, CFI_attribute_allocatable);
} else {
result = Descriptor::Create(source.type(), elementBytes, nullptr,
resultRank, resultExtent,
CFI_attribute_allocatable); // TODO rearrange these arguments
}
DescriptorAddendum *resultAddendum{result->Addendum()};
RUNTIME_CHECK(terminator, resultAddendum);
resultAddendum->flags() |= DescriptorAddendum::DoNotFinalize;
if (sourceDerivedType) {
std::size_t lenParameters{sourceAddendum->LenParameters()};
for (std::size_t j{0}; j < lenParameters; ++j) {
resultAddendum->SetLenParameterValue(
j, sourceAddendum->LenParameterValue(j));
}
}
// Allocate storage for the result's data.
for (int j{0}; j < resultRank; ++j) {
result->GetDimension(j).SetBounds(1, resultExtent[j]);
}
int status{result->Allocate()};
if (status != CFI_SUCCESS) {
terminator.Crash("RESHAPE: Allocate failed (error %d)", status);
}
// Allocate result descriptor
AllocateResult(
result, source, resultRank, resultExtent, terminator, "RESHAPE");
// Populate the result's elements.
SubscriptValue resultSubscript[maxRank];
result->GetLowerBounds(resultSubscript);
result.GetLowerBounds(resultSubscript);
SubscriptValue sourceSubscript[maxRank];
source.GetLowerBounds(sourceSubscript);
std::size_t resultElement{0};
std::size_t elementsFromSource{std::min(resultElements, sourceElements)};
for (; resultElement < elementsFromSource; ++resultElement) {
CopyElement(*result, resultSubscript, source, sourceSubscript, terminator);
CopyElement(result, resultSubscript, source, sourceSubscript, terminator);
source.IncrementSubscripts(sourceSubscript);
result->IncrementSubscripts(resultSubscript, dimOrder);
result.IncrementSubscripts(resultSubscript, dimOrder);
}
if (resultElement < resultElements) {
// Remaining elements come from the optional PAD= argument.
SubscriptValue padSubscript[maxRank];
pad->GetLowerBounds(padSubscript);
for (; resultElement < resultElements; ++resultElement) {
CopyElement(*result, resultSubscript, *pad, padSubscript, terminator);
CopyElement(result, resultSubscript, *pad, padSubscript, terminator);
pad->IncrementSubscripts(padSubscript);
result->IncrementSubscripts(resultSubscript, dimOrder);
result.IncrementSubscripts(resultSubscript, dimOrder);
}
}
return result;
}
extern "C" { // TODO - remove when Reshape is under extern "C"
// SPREAD
void RTNAME(Spread)(Descriptor &result, const Descriptor &source, int dim,

View File

@ -23,14 +23,13 @@
namespace Fortran::runtime {
// TODO: redo API, put under extern "C"
OwningPtr<Descriptor> RTNAME(Reshape)(const Descriptor &source,
extern "C" {
void RTNAME(Reshape)(Descriptor &result, const Descriptor &source,
const Descriptor &shape, const Descriptor *pad = nullptr,
const Descriptor *order = nullptr, const char *sourceFile = nullptr,
int line = 0);
extern "C" {
void RTNAME(Cshift)(Descriptor &result, const Descriptor &source,
const Descriptor &shift, int dim = 1, const char *sourceFile = nullptr,
int line = 0);

View File

@ -53,10 +53,22 @@ int main() {
MATCH(2, pad.GetDimension(0).Extent());
MATCH(2, pad.GetDimension(1).Extent());
MATCH(3, pad.GetDimension(2).Extent());
StaticDescriptor<1> orderDescriptor;
Descriptor &order{orderDescriptor.descriptor()};
static const std::int32_t orderData[]{1, 2};
static const SubscriptValue orderExtent[]{2};
order.Establish(TypeCategory::Integer, static_cast<int>(sizeof orderData[0]),
const_cast<void *>(reinterpret_cast<const void *>(orderData)), 1,
orderExtent, CFI_attribute_pointer);
orderDescriptor.Check();
order.Check();
MATCH(1, order.rank());
MATCH(2, order.GetDimension(0).Extent());
auto result{
RTNAME(Reshape)(*source, *shape, &pad, nullptr, __FILE__, __LINE__)};
auto result{Descriptor::Create(TypeCategory::Integer, sizeof(std::int32_t),
nullptr, 2, nullptr, CFI_attribute_allocatable)};
TEST(result.get() != nullptr);
RTNAME(Reshape)(*result, *source, *shape, &pad, &order, __FILE__, __LINE__);
result->Check();
MATCH(sizeof(std::int32_t), result->ElementBytes());
MATCH(2, result->rank());
@ -69,7 +81,5 @@ int main() {
MATCH(j, *result->Element<std::int32_t>(ss));
}
// TODO: test ORDER=
return testing::Complete();
}