From 6436c9b127f5d589a15619bb312ba692f98d6f1b Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Fri, 24 May 2024 06:54:56 -0700 Subject: [PATCH 1/2] [flang] add API to copy and update descriptors for assumed ranks --- flang/include/flang/Runtime/support.h | 15 +++++++ flang/runtime/support.cpp | 22 ++++++++++ flang/unittests/Runtime/CMakeLists.txt | 1 + flang/unittests/Runtime/Support.cpp | 58 ++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 flang/unittests/Runtime/Support.cpp diff --git a/flang/include/flang/Runtime/support.h b/flang/include/flang/Runtime/support.h index e7ae2154b2a72..7887308f02245 100644 --- a/flang/include/flang/Runtime/support.h +++ b/flang/include/flang/Runtime/support.h @@ -10,6 +10,7 @@ #ifndef FORTRAN_RUNTIME_SUPPORT_H_ #define FORTRAN_RUNTIME_SUPPORT_H_ +#include "flang/ISO_Fortran_binding_wrapper.h" #include "flang/Runtime/entry-names.h" #include #include @@ -18,11 +19,25 @@ namespace Fortran::runtime { class Descriptor; +namespace typeInfo { +class DerivedType; +} + +enum LowerBoundModifier : int { Preserve = 0, SetToOnes = 1, SetToZeroes = 2 }; + extern "C" { // Predicate: is the storage described by a Descriptor contiguous in memory? bool RTDECL(IsContiguous)(const Descriptor &); +// Copy "from" descriptor into "to" descriptor and update "to" dynamic type, +// CFI_attribute, and lower bounds according to the other arguments. +// "newDynamicType" may be a null pointer in which case "to" dynamic type is the +// one of "from". +void RTDECL(CopyAndUpdateDescriptor)(Descriptor &to, const Descriptor &from, + const typeInfo::DerivedType *newDynamicType, + ISO::CFI_attribute_t newAttribute, enum LowerBoundModifier newLowerBounds); + } // extern "C" } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_SUPPORT_H_ diff --git a/flang/runtime/support.cpp b/flang/runtime/support.cpp index 12135804f00e6..19e75429774b3 100644 --- a/flang/runtime/support.cpp +++ b/flang/runtime/support.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "flang/Runtime/support.h" +#include "type-info.h" #include "flang/Runtime/descriptor.h" namespace Fortran::runtime { @@ -17,6 +18,27 @@ bool RTDEF(IsContiguous)(const Descriptor &descriptor) { return descriptor.IsContiguous(); } +void RTDEF(CopyAndUpdateDescriptor)(Descriptor &to, const Descriptor &from, + const typeInfo::DerivedType *newDynamicType, + ISO::CFI_attribute_t newAttribute, enum LowerBoundModifier newLowerBounds) { + to = from; + if (newDynamicType) { + DescriptorAddendum *toAddendum{to.Addendum()}; + INTERNAL_CHECK(toAddendum); + toAddendum->set_derivedType(newDynamicType); + to.raw().elem_len = newDynamicType->sizeInBytes(); + } + to.raw().attribute = newAttribute; + if (newLowerBounds != LowerBoundModifier::Preserve) { + const ISO::CFI_index_t newLowerBound{ + newLowerBounds == LowerBoundModifier::SetToOnes ? 1 : 0}; + const int rank{to.rank()}; + for (int i = 0; i < rank; ++i) { + to.GetDimension(i).SetLowerBound(newLowerBound); + } + } +} + RT_EXT_API_GROUP_END } // extern "C" } // namespace Fortran::runtime diff --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt index f7caacad3a598..ed047b08ada35 100644 --- a/flang/unittests/Runtime/CMakeLists.txt +++ b/flang/unittests/Runtime/CMakeLists.txt @@ -25,6 +25,7 @@ add_flang_unittest(FlangRuntimeTests Reduction.cpp RuntimeCrashTest.cpp Stop.cpp + Support.cpp Time.cpp TemporaryStack.cpp Transformational.cpp diff --git a/flang/unittests/Runtime/Support.cpp b/flang/unittests/Runtime/Support.cpp new file mode 100644 index 0000000000000..fa2a233e1e654 --- /dev/null +++ b/flang/unittests/Runtime/Support.cpp @@ -0,0 +1,58 @@ +//===-- flang/unittests/Runtime/Support.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/Runtime/support.h" +#include "gtest/gtest.h" +#include "tools.h" +#include "flang/Runtime/descriptor.h" + +using namespace Fortran::runtime; +using Fortran::common::TypeCategory; +TEST(CopyAndUpdateDescriptor, Basic) { + auto x{MakeArray( + std::vector{2, 3}, std::vector{0, 1, 2, 3, 4, 5})}; + x->GetDimension(0).SetLowerBound(11); + x->GetDimension(1).SetLowerBound(12); + + StaticDescriptor<2, false> statDesc; + Descriptor &result{statDesc.descriptor()}; + + RTNAME(CopyAndUpdateDescriptor) + (result, *x, nullptr, CFI_attribute_pointer, LowerBoundModifier::Preserve); + ASSERT_EQ(result.rank(), 2); + EXPECT_EQ(result.raw().base_addr, x->raw().base_addr); + EXPECT_TRUE(result.IsPointer()); + EXPECT_EQ(result.GetDimension(0).Extent(), x->GetDimension(0).Extent()); + EXPECT_EQ( + result.GetDimension(0).LowerBound(), x->GetDimension(0).LowerBound()); + EXPECT_EQ(result.GetDimension(1).Extent(), x->GetDimension(1).Extent()); + EXPECT_EQ( + result.GetDimension(1).LowerBound(), x->GetDimension(1).LowerBound()); + + RTNAME(CopyAndUpdateDescriptor) + (result, *x, nullptr, CFI_attribute_allocatable, + LowerBoundModifier::SetToZeroes); + ASSERT_EQ(result.rank(), 2); + EXPECT_EQ(result.raw().base_addr, x->raw().base_addr); + EXPECT_TRUE(result.IsAllocatable()); + EXPECT_EQ(result.GetDimension(0).Extent(), x->GetDimension(0).Extent()); + EXPECT_EQ(result.GetDimension(0).LowerBound(), 0); + EXPECT_EQ(result.GetDimension(1).Extent(), x->GetDimension(1).Extent()); + EXPECT_EQ(result.GetDimension(1).LowerBound(), 0); + + RTNAME(CopyAndUpdateDescriptor) + (result, *x, nullptr, CFI_attribute_other, LowerBoundModifier::SetToOnes); + ASSERT_EQ(result.rank(), 2); + EXPECT_EQ(result.raw().base_addr, x->raw().base_addr); + EXPECT_FALSE(result.IsAllocatable()); + EXPECT_FALSE(result.IsPointer()); + EXPECT_EQ(result.GetDimension(0).Extent(), x->GetDimension(0).Extent()); + EXPECT_EQ(result.GetDimension(0).LowerBound(), 1); + EXPECT_EQ(result.GetDimension(1).Extent(), x->GetDimension(1).Extent()); + EXPECT_EQ(result.GetDimension(1).LowerBound(), 1); +} From e9055c9670013723625d267cfebfabdd0e53d9bc Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Fri, 24 May 2024 12:23:56 -0700 Subject: [PATCH 2/2] use an enum class --- flang/include/flang/Runtime/support.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flang/include/flang/Runtime/support.h b/flang/include/flang/Runtime/support.h index 7887308f02245..8bdf3b9fca83b 100644 --- a/flang/include/flang/Runtime/support.h +++ b/flang/include/flang/Runtime/support.h @@ -23,7 +23,11 @@ namespace typeInfo { class DerivedType; } -enum LowerBoundModifier : int { Preserve = 0, SetToOnes = 1, SetToZeroes = 2 }; +enum class LowerBoundModifier : int { + Preserve = 0, + SetToOnes = 1, + SetToZeroes = 2 +}; extern "C" {