[flang-commits] [flang] e3d6a3a - [flang][runtime] Support non contiguous array in Finalize/Initialize (#67295)

via flang-commits flang-commits at lists.llvm.org
Mon Sep 25 09:16:57 PDT 2023


Author: jeanPerier
Date: 2023-09-25T18:16:53+02:00
New Revision: e3d6a3ac6925862f5829e4883942be9eec591164

URL: https://github.com/llvm/llvm-project/commit/e3d6a3ac6925862f5829e4883942be9eec591164
DIFF: https://github.com/llvm/llvm-project/commit/e3d6a3ac6925862f5829e4883942be9eec591164.diff

LOG: [flang][runtime] Support non contiguous array in Finalize/Initialize (#67295)

Finalize/Initialize may be called on non contiguous arrays when dealing
with INTENT(OUT) dummies or non contiguous LHS. Update the related
element access to use indices instead of assuming contiguity and
manually computing the byte offset.

Also, the descriptor passed to parent type final routines should be set
to the parent type, otherwise descriptor.IsContiguous() may wrongfully
return true when finalizing parent components. Create a pointer to the
parent component when recursing in Finalize.

Added: 
    

Modified: 
    flang/include/flang/Runtime/descriptor.h
    flang/runtime/derived.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Runtime/descriptor.h b/flang/include/flang/Runtime/descriptor.h
index 62a8d123bf2ee06..32fb6d646d1bda7 100644
--- a/flang/include/flang/Runtime/descriptor.h
+++ b/flang/include/flang/Runtime/descriptor.h
@@ -250,6 +250,13 @@ class Descriptor {
     return OffsetElement<A>(SubscriptsToByteOffset(subscript));
   }
 
+  template <typename A>
+  RT_API_ATTRS A *ElementComponent(
+      const SubscriptValue subscript[], std::size_t componentOffset) const {
+    return OffsetElement<A>(
+        SubscriptsToByteOffset(subscript) + componentOffset);
+  }
+
   template <typename A>
   RT_API_ATTRS A *ZeroBasedIndexedElement(std::size_t n) const {
     SubscriptValue at[maxRank];

diff  --git a/flang/runtime/derived.cpp b/flang/runtime/derived.cpp
index 5edc47c4a948918..6e87e010df2edaf 100644
--- a/flang/runtime/derived.cpp
+++ b/flang/runtime/derived.cpp
@@ -19,7 +19,6 @@ int Initialize(const Descriptor &instance, const typeInfo::DerivedType &derived,
     Terminator &terminator, bool hasStat, const Descriptor *errMsg) {
   const Descriptor &componentDesc{derived.component()};
   std::size_t elements{instance.Elements()};
-  std::size_t byteStride{instance.ElementBytes()};
   int stat{StatOk};
   // Initialize data components in each element; the per-element iterations
   // constitute the inner loops, not the outer ones
@@ -27,11 +26,13 @@ int Initialize(const Descriptor &instance, const typeInfo::DerivedType &derived,
   for (std::size_t k{0}; k < myComponents; ++k) {
     const auto &comp{
         *componentDesc.ZeroBasedIndexedElement<typeInfo::Component>(k)};
+    SubscriptValue at[maxRank];
+    instance.GetLowerBounds(at);
     if (comp.genre() == typeInfo::Component::Genre::Allocatable ||
         comp.genre() == typeInfo::Component::Genre::Automatic) {
-      for (std::size_t j{0}; j < elements; ++j) {
-        Descriptor &allocDesc{*instance.OffsetElement<Descriptor>(
-            j * byteStride + comp.offset())};
+      for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
+        Descriptor &allocDesc{
+            *instance.ElementComponent<Descriptor>(at, comp.offset())};
         comp.EstablishDescriptor(allocDesc, instance, terminator);
         allocDesc.raw().attribute = CFI_attribute_allocatable;
         if (comp.genre() == typeInfo::Component::Genre::Automatic) {
@@ -55,17 +56,17 @@ int Initialize(const Descriptor &instance, const typeInfo::DerivedType &derived,
       // Explicit initialization of data pointers and
       // non-allocatable non-automatic components
       std::size_t bytes{comp.SizeInBytes(instance)};
-      for (std::size_t j{0}; j < elements; ++j) {
-        char *ptr{instance.ZeroBasedIndexedElement<char>(j) + comp.offset()};
+      for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
+        char *ptr{instance.ElementComponent<char>(at, comp.offset())};
         std::memcpy(ptr, init, bytes);
       }
     } else if (comp.genre() == typeInfo::Component::Genre::Pointer) {
       // Data pointers without explicit initialization are established
       // so that they are valid right-hand side targets of pointer
       // assignment statements.
-      for (std::size_t j{0}; j < elements; ++j) {
-        Descriptor &ptrDesc{*instance.OffsetElement<Descriptor>(
-            j * byteStride + comp.offset())};
+      for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
+        Descriptor &ptrDesc{
+            *instance.ElementComponent<Descriptor>(at, comp.offset())};
         comp.EstablishDescriptor(ptrDesc, instance, terminator);
         ptrDesc.raw().attribute = CFI_attribute_pointer;
       }
@@ -85,10 +86,10 @@ int Initialize(const Descriptor &instance, const typeInfo::DerivedType &derived,
       StaticDescriptor<maxRank, true, 0> staticDescriptor;
       Descriptor &compDesc{staticDescriptor.descriptor()};
       const typeInfo::DerivedType &compType{*comp.derivedType()};
-      for (std::size_t j{0}; j < elements; ++j) {
+      for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
         compDesc.Establish(compType,
-            instance.OffsetElement<char>(j * byteStride + comp.offset()),
-            comp.rank(), extent);
+            instance.ElementComponent<char>(at, comp.offset()), comp.rank(),
+            extent);
         stat = Initialize(compDesc, compType, terminator, hasStat, errMsg);
         if (stat != StatOk) {
           break;
@@ -102,9 +103,11 @@ int Initialize(const Descriptor &instance, const typeInfo::DerivedType &derived,
   for (std::size_t k{0}; k < myProcPtrs; ++k) {
     const auto &comp{
         *procPtrDesc.ZeroBasedIndexedElement<typeInfo::ProcPtrComponent>(k)};
-    for (std::size_t j{0}; j < elements; ++j) {
-      auto &pptr{*instance.OffsetElement<typeInfo::ProcedurePointer>(
-          j * byteStride + comp.offset)};
+    SubscriptValue at[maxRank];
+    instance.GetLowerBounds(at);
+    for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
+      auto &pptr{*instance.ElementComponent<typeInfo::ProcedurePointer>(
+          at, comp.offset)};
       pptr = comp.procInitialization;
     }
   }
@@ -129,8 +132,9 @@ static void CallFinalSubroutine(const Descriptor &descriptor,
     const typeInfo::DerivedType &derived, Terminator *terminator) {
   if (const auto *special{FindFinal(derived, descriptor.rank())}) {
     if (special->which() == typeInfo::SpecialBinding::Which::ElementalFinal) {
-      std::size_t byteStride{descriptor.ElementBytes()};
       std::size_t elements{descriptor.Elements()};
+      SubscriptValue at[maxRank];
+      descriptor.GetLowerBounds(at);
       if (special->IsArgDescriptor(0)) {
         StaticDescriptor<maxRank, true, 8 /*?*/> statDesc;
         Descriptor &elemDesc{statDesc.descriptor()};
@@ -138,15 +142,16 @@ static void CallFinalSubroutine(const Descriptor &descriptor,
         elemDesc.raw().attribute = CFI_attribute_pointer;
         elemDesc.raw().rank = 0;
         auto *p{special->GetProc<void (*)(const Descriptor &)>()};
-        for (std::size_t j{0}; j < elements; ++j) {
-          elemDesc.set_base_addr(
-              descriptor.OffsetElement<char>(j * byteStride));
+        for (std::size_t j{0}; j++ < elements;
+             descriptor.IncrementSubscripts(at)) {
+          elemDesc.set_base_addr(descriptor.Element<char>(at));
           p(elemDesc);
         }
       } else {
         auto *p{special->GetProc<void (*)(char *)>()};
-        for (std::size_t j{0}; j < elements; ++j) {
-          p(descriptor.OffsetElement<char>(j * byteStride));
+        for (std::size_t j{0}; j++ < elements;
+             descriptor.IncrementSubscripts(at)) {
+          p(descriptor.Element<char>(at));
         }
       }
     } else {
@@ -202,20 +207,22 @@ void Finalize(const Descriptor &descriptor,
   const Descriptor &componentDesc{derived.component()};
   std::size_t myComponents{componentDesc.Elements()};
   std::size_t elements{descriptor.Elements()};
-  std::size_t byteStride{descriptor.ElementBytes()};
   for (auto k{recurse ? std::size_t{1}
                       /* skip first component, it's the parent */
                       : 0};
        k < myComponents; ++k) {
     const auto &comp{
         *componentDesc.ZeroBasedIndexedElement<typeInfo::Component>(k)};
+    SubscriptValue at[maxRank];
+    descriptor.GetLowerBounds(at);
     if (comp.genre() == typeInfo::Component::Genre::Allocatable &&
         comp.category() == TypeCategory::Derived) {
       // Component may be polymorphic or unlimited polymorphic. Need to use the
       // dynamic type to check whether finalization is needed.
-      for (std::size_t j{0}; j < elements; ++j) {
-        const Descriptor &compDesc{*descriptor.OffsetElement<Descriptor>(
-            j * byteStride + comp.offset())};
+      for (std::size_t j{0}; j++ < elements;
+           descriptor.IncrementSubscripts(at)) {
+        const Descriptor &compDesc{
+            *descriptor.ElementComponent<Descriptor>(at, comp.offset())};
         if (compDesc.IsAllocated()) {
           if (const DescriptorAddendum * addendum{compDesc.Addendum()}) {
             if (const typeInfo::DerivedType *
@@ -231,9 +238,10 @@ void Finalize(const Descriptor &descriptor,
         comp.genre() == typeInfo::Component::Genre::Automatic) {
       if (const typeInfo::DerivedType * compType{comp.derivedType()}) {
         if (!compType->noFinalizationNeeded()) {
-          for (std::size_t j{0}; j < elements; ++j) {
-            const Descriptor &compDesc{*descriptor.OffsetElement<Descriptor>(
-                j * byteStride + comp.offset())};
+          for (std::size_t j{0}; j++ < elements;
+               descriptor.IncrementSubscripts(at)) {
+            const Descriptor &compDesc{
+                *descriptor.ElementComponent<Descriptor>(at, comp.offset())};
             if (compDesc.IsAllocated()) {
               Finalize(compDesc, *compType, terminator);
             }
@@ -253,16 +261,23 @@ void Finalize(const Descriptor &descriptor,
       StaticDescriptor<maxRank, true, 0> staticDescriptor;
       Descriptor &compDesc{staticDescriptor.descriptor()};
       const typeInfo::DerivedType &compType{*comp.derivedType()};
-      for (std::size_t j{0}; j < elements; ++j) {
+      for (std::size_t j{0}; j++ < elements;
+           descriptor.IncrementSubscripts(at)) {
         compDesc.Establish(compType,
-            descriptor.OffsetElement<char>(j * byteStride + comp.offset()),
-            comp.rank(), extent);
+            descriptor.ElementComponent<char>(at, comp.offset()), comp.rank(),
+            extent);
         Finalize(compDesc, compType, terminator);
       }
     }
   }
   if (recurse) {
-    Finalize(descriptor, *parentType, terminator);
+    StaticDescriptor<maxRank, true, 8 /*?*/> statDesc;
+    Descriptor &tmpDesc{statDesc.descriptor()};
+    tmpDesc = descriptor;
+    tmpDesc.raw().attribute = CFI_attribute_pointer;
+    tmpDesc.Addendum()->set_derivedType(parentType);
+    tmpDesc.raw().elem_len = parentType->sizeInBytes();
+    Finalize(tmpDesc, *parentType, terminator);
   }
 }
 
@@ -289,8 +304,8 @@ void Destroy(const Descriptor &descriptor, bool finalize,
     if (comp.genre() == typeInfo::Component::Genre::Allocatable ||
         comp.genre() == typeInfo::Component::Genre::Automatic) {
       for (std::size_t j{0}; j < elements; ++j) {
-        Descriptor *d{reinterpret_cast<Descriptor *>(
-            descriptor.Element<char>(at) + comp.offset())};
+        Descriptor *d{
+            descriptor.ElementComponent<Descriptor>(at, comp.offset())};
         d->Deallocate();
         descriptor.IncrementSubscripts(at);
       }


        


More information about the flang-commits mailing list