[flang-commits] [flang] [flang] Avoid recursion in runtime derived type initialization (PR #102394)

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Mon Aug 19 13:45:39 PDT 2024


================
@@ -29,97 +30,92 @@ static RT_API_ATTRS void GetComponentExtents(SubscriptValue (&extents)[maxRank],
   }
 }
 
-RT_API_ATTRS 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()};
-  int stat{StatOk};
-  // Initialize data components in each element; the per-element iterations
-  // constitute the inner loops, not the outer ones
-  std::size_t myComponents{componentDesc.Elements()};
-  for (std::size_t k{0}; k < myComponents; ++k) {
+RT_API_ATTRS auto engine::Initialization::Resume(Engine &engine) -> ResultType {
+  while (component_.Iterating(components_)) {
     const auto &comp{
-        *componentDesc.ZeroBasedIndexedElement<typeInfo::Component>(k)};
-    SubscriptValue at[maxRank];
-    instance.GetLowerBounds(at);
+        *componentDesc_->ZeroBasedIndexedElement<typeInfo::Component>(
+            component_.at)};
     if (comp.genre() == typeInfo::Component::Genre::Allocatable ||
         comp.genre() == typeInfo::Component::Genre::Automatic) {
-      for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
-        Descriptor &allocDesc{
-            *instance.ElementComponent<Descriptor>(at, comp.offset())};
-        comp.EstablishDescriptor(allocDesc, instance, terminator);
+      while (element_.Iterating(elements_, &instance_)) {
+        Descriptor &allocDesc{*instance_.ElementComponent<Descriptor>(
+            element_.subscripts, comp.offset())};
+        comp.EstablishDescriptor(allocDesc, instance_, engine.terminator());
         allocDesc.raw().attribute = CFI_attribute_allocatable;
         if (comp.genre() == typeInfo::Component::Genre::Automatic) {
-          stat = ReturnError(terminator, allocDesc.Allocate(), errMsg, hasStat);
-          if (stat == StatOk) {
-            if (const DescriptorAddendum * addendum{allocDesc.Addendum()}) {
-              if (const auto *derived{addendum->derivedType()}) {
-                if (!derived->noInitializationNeeded()) {
-                  stat = Initialize(
-                      allocDesc, *derived, terminator, hasStat, errMsg);
-                }
+          if (auto stat{ReturnError(engine.terminator(), allocDesc.Allocate(),
+                  engine.errMsg(), engine.hasStat())};
+              stat != StatOk) {
+            return engine.Fail(stat);
+          }
+          if (const DescriptorAddendum * addendum{allocDesc.Addendum()}) {
+            if (const auto *derived{addendum->derivedType()}) {
+              if (!derived->noInitializationNeeded()) {
+                component_.ResumeAtSameIteration();
+                return engine.Begin(Job::Initialization, allocDesc, derived);
               }
             }
           }
-          if (stat != StatOk) {
-            break;
-          }
         }
       }
     } else if (const void *init{comp.initialization()}) {
       // 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; instance.IncrementSubscripts(at)) {
-        char *ptr{instance.ElementComponent<char>(at, comp.offset())};
+      std::size_t bytes{comp.SizeInBytes(instance_)};
+      while (element_.Iterating(elements_, &instance_)) {
+        char *ptr{instance_.ElementComponent<char>(
+            element_.subscripts, 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; instance.IncrementSubscripts(at)) {
-        Descriptor &ptrDesc{
-            *instance.ElementComponent<Descriptor>(at, comp.offset())};
-        comp.EstablishDescriptor(ptrDesc, instance, terminator);
+      while (element_.Iterating(elements_, &instance_)) {
+        Descriptor &ptrDesc{*instance_.ElementComponent<Descriptor>(
+            element_.subscripts, comp.offset())};
+        comp.EstablishDescriptor(ptrDesc, instance_, engine.terminator());
         ptrDesc.raw().attribute = CFI_attribute_pointer;
       }
     } else if (comp.genre() == typeInfo::Component::Genre::Data &&
         comp.derivedType() && !comp.derivedType()->noInitializationNeeded()) {
       // Default initialization of non-pointer non-allocatable/automatic
-      // data component.  Handles parent component's elements.  Recursive.
-      SubscriptValue extents[maxRank];
-      GetComponentExtents(extents, comp, instance);
-      StaticDescriptor<maxRank, true, 0> staticDescriptor;
-      Descriptor &compDesc{staticDescriptor.descriptor()};
-      const typeInfo::DerivedType &compType{*comp.derivedType()};
-      for (std::size_t j{0}; j++ < elements; instance.IncrementSubscripts(at)) {
+      // data component.  Handles parent component's elements.
+      if (!element_.active) {
----------------
vzakhari wrote:

nit: maybe use `element_.at == 0` as in two other instances.

https://github.com/llvm/llvm-project/pull/102394


More information about the flang-commits mailing list