Index: flang/runtime/transformational.h =================================================================== --- flang/runtime/transformational.h +++ flang/runtime/transformational.h @@ -23,14 +23,14 @@ namespace Fortran::runtime { -// TODO: redo API, put under extern "C" -OwningPtr 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); Index: flang/runtime/transformational.cpp =================================================================== --- flang/runtime/transformational.cpp +++ flang/runtime/transformational.cpp @@ -350,9 +350,9 @@ } } -} // extern "C" - TODO put Reshape under extern "C" +// RESHAPE // F2018 16.9.163 -OwningPtr 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,11 @@ RUNTIME_CHECK(terminator, order->GetDimension(0).Extent() == resultRank); std::uint64_t values{0}; SubscriptValue orderSubscript{order->GetDimension(0).LowerBound()}; + auto addr = order->OffsetElement(orderSubscript); + std::size_t orderElementBytes{order->ElementBytes()}; for (SubscriptValue j{0}; j < resultRank; ++j, ++orderSubscript) { - auto k{GetInt64(order->OffsetElement(orderSubscript), - shapeElementBytes, terminator)}; + addr += orderSubscript * orderElementBytes; + auto k{GetInt64(addr, 1, terminator)}; RUNTIME_CHECK( terminator, k >= 1 && k <= resultRank && !((values >> k) & 1)); values |= std::uint64_t{1} << k; @@ -408,64 +410,33 @@ } } - // Create and populate the result's descriptor. - const DescriptorAddendum *sourceAddendum{source.Addendum()}; - const typeInfo::DerivedType *sourceDerivedType{ - sourceAddendum ? sourceAddendum->derivedType() : nullptr}; - OwningPtr 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) { + if (pad && 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, Index: flang/unittests/Evaluate/reshape.cpp =================================================================== --- flang/unittests/Evaluate/reshape.cpp +++ flang/unittests/Evaluate/reshape.cpp @@ -54,9 +54,10 @@ MATCH(2, pad.GetDimension(1).Extent()); MATCH(3, pad.GetDimension(2).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, nullptr, __FILE__, __LINE__); result->Check(); MATCH(sizeof(std::int32_t), result->ElementBytes()); MATCH(2, result->rank());