[flang-commits] [flang] f19c46d - [flang][runtime] Iterate over array elements in user-defined derived type I/O

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Fri Mar 10 10:25:58 PST 2023


Author: Peter Klausler
Date: 2023-03-10T10:25:53-08:00
New Revision: f19c46d431f797a1b6017b8ea6c9244e87663aa2

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

LOG: [flang][runtime] Iterate over array elements in user-defined derived type I/O

It was only handling scalars; change to iterate over all array elements.

Differential Revision: https://reviews.llvm.org/D145752

Added: 
    

Modified: 
    flang/runtime/descriptor-io.cpp
    flang/runtime/descriptor-io.h

Removed: 
    


################################################################################
diff  --git a/flang/runtime/descriptor-io.cpp b/flang/runtime/descriptor-io.cpp
index 4a17a53b495a..c51a36b1a7bd 100644
--- a/flang/runtime/descriptor-io.cpp
+++ b/flang/runtime/descriptor-io.cpp
@@ -13,7 +13,8 @@ namespace Fortran::runtime::io::descr {
 
 // User-defined derived type formatted I/O (maybe)
 std::optional<bool> DefinedFormattedIo(IoStatementState &io,
-    const Descriptor &descriptor, const typeInfo::SpecialBinding &special) {
+    const Descriptor &descriptor, const typeInfo::DerivedType &derived,
+    const typeInfo::SpecialBinding &special) {
   std::optional<DataEdit> peek{io.GetNextDataEdit(0 /*to peek at it*/)};
   if (peek &&
       (peek->descriptor == DataEdit::DefinedDerivedType ||
@@ -33,8 +34,8 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io,
           ioType, io.mutableModes().inNamelist ? "NAMELIST" : "LISTDIRECTED");
       ioTypeLen = std::strlen(ioType);
     }
-    StaticDescriptor<1, true> statDesc;
-    Descriptor &vListDesc{statDesc.descriptor()};
+    StaticDescriptor<1, true> vListStatDesc;
+    Descriptor &vListDesc{vListStatDesc.descriptor()};
     vListDesc.Establish(TypeCategory::Integer, sizeof(int), nullptr, 1);
     vListDesc.set_base_addr(edit.vList);
     vListDesc.GetDimension(0).SetBounds(1, edit.vListEntries);
@@ -60,16 +61,36 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io,
       // I/O subroutine reads counts towards READ(SIZE=).
       startPos = io.InquirePos();
     }
+    std::size_t numElements{descriptor.Elements()};
+    SubscriptValue subscripts[maxRank];
+    descriptor.GetLowerBounds(subscripts);
     if (special.IsArgDescriptor(0)) {
+      // "dtv" argument is "class(t)", pass a descriptor
       auto *p{special.GetProc<void (*)(const Descriptor &, int &, char *,
           const Descriptor &, int &, char *, std::size_t, std::size_t)>()};
-      p(descriptor, unit, ioType, vListDesc, ioStat, ioMsg, ioTypeLen,
-          sizeof ioMsg);
+      StaticDescriptor<1, true, 10 /*?*/> elementStatDesc;
+      Descriptor &elementDesc{elementStatDesc.descriptor()};
+      elementDesc.Establish(
+          derived, nullptr, 0, nullptr, CFI_attribute_pointer);
+      for (; numElements-- > 0; descriptor.IncrementSubscripts(subscripts)) {
+        elementDesc.set_base_addr(descriptor.Element<char>(subscripts));
+        p(elementDesc, unit, ioType, vListDesc, ioStat, ioMsg, ioTypeLen,
+            sizeof ioMsg);
+        if (ioStat != IostatOk) {
+          break;
+        }
+      }
     } else {
+      // "dtv" argument is "type(t)", pass a raw pointer
       auto *p{special.GetProc<void (*)(const void *, int &, char *,
           const Descriptor &, int &, char *, std::size_t, std::size_t)>()};
-      p(descriptor.raw().base_addr, unit, ioType, vListDesc, ioStat, ioMsg,
-          ioTypeLen, sizeof ioMsg);
+      for (; numElements-- > 0; descriptor.IncrementSubscripts(subscripts)) {
+        p(descriptor.Element<char>(subscripts), unit, ioType, vListDesc, ioStat,
+            ioMsg, ioTypeLen, sizeof ioMsg);
+        if (ioStat != IostatOk) {
+          break;
+        }
+      }
     }
     handler.Forward(ioStat, ioMsg, sizeof ioMsg);
     external->PopChildIo(child);
@@ -93,6 +114,7 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io,
 
 // User-defined derived type unformatted I/O
 bool DefinedUnformattedIo(IoStatementState &io, const Descriptor &descriptor,
+    const typeInfo::DerivedType &derived,
     const typeInfo::SpecialBinding &special) {
   // Unformatted I/O must have an external unit (or child thereof).
   IoErrorHandler &handler{io.GetIoErrorHandler()};
@@ -102,14 +124,34 @@ bool DefinedUnformattedIo(IoStatementState &io, const Descriptor &descriptor,
   int unit{external->unitNumber()};
   int ioStat{IostatOk};
   char ioMsg[100];
+  std::size_t numElements{descriptor.Elements()};
+  SubscriptValue subscripts[maxRank];
+  descriptor.GetLowerBounds(subscripts);
   if (special.IsArgDescriptor(0)) {
+    // "dtv" argument is "class(t)", pass a descriptor
     auto *p{special.GetProc<void (*)(
         const Descriptor &, int &, int &, char *, std::size_t)>()};
-    p(descriptor, unit, ioStat, ioMsg, sizeof ioMsg);
+    StaticDescriptor<1, true, 10 /*?*/> elementStatDesc;
+    Descriptor &elementDesc{elementStatDesc.descriptor()};
+    elementDesc.Establish(derived, nullptr, 0, nullptr, CFI_attribute_pointer);
+    for (; numElements-- > 0; descriptor.IncrementSubscripts(subscripts)) {
+      elementDesc.set_base_addr(descriptor.Element<char>(subscripts));
+      p(elementDesc, unit, ioStat, ioMsg, sizeof ioMsg);
+      if (ioStat != IostatOk) {
+        break;
+      }
+    }
   } else {
+    // "dtv" argument is "type(t)", pass a raw pointer
     auto *p{special.GetProc<void (*)(
         const void *, int &, int &, char *, std::size_t)>()};
-    p(descriptor.raw().base_addr, unit, ioStat, ioMsg, sizeof ioMsg);
+    for (; numElements-- > 0; descriptor.IncrementSubscripts(subscripts)) {
+      p(descriptor.Element<char>(subscripts), unit, ioStat, ioMsg,
+          sizeof ioMsg);
+      if (ioStat != IostatOk) {
+        break;
+      }
+    }
   }
   handler.Forward(ioStat, ioMsg, sizeof ioMsg);
   external->PopChildIo(child);

diff  --git a/flang/runtime/descriptor-io.h b/flang/runtime/descriptor-io.h
index 8b2cf674f6b6..7bf55ded31d3 100644
--- a/flang/runtime/descriptor-io.h
+++ b/flang/runtime/descriptor-io.h
@@ -291,8 +291,8 @@ static bool DefaultComponentwiseIO(IoStatementState &io,
   return true;
 }
 
-std::optional<bool> DefinedFormattedIo(
-    IoStatementState &, const Descriptor &, const typeInfo::SpecialBinding &);
+std::optional<bool> DefinedFormattedIo(IoStatementState &, const Descriptor &,
+    const typeInfo::DerivedType &, const typeInfo::SpecialBinding &);
 
 template <Direction DIR>
 static bool FormattedDerivedTypeIO(
@@ -308,15 +308,15 @@ static bool FormattedDerivedTypeIO(
               ? typeInfo::SpecialBinding::Which::ReadFormatted
               : typeInfo::SpecialBinding::Which::WriteFormatted)}) {
     if (std::optional<bool> wasDefined{
-            DefinedFormattedIo(io, descriptor, *special)}) {
+            DefinedFormattedIo(io, descriptor, *type, *special)}) {
       return *wasDefined; // user-defined I/O was applied
     }
   }
   return DefaultComponentwiseIO<DIR>(io, descriptor, *type);
 }
 
-bool DefinedUnformattedIo(
-    IoStatementState &, const Descriptor &, const typeInfo::SpecialBinding &);
+bool DefinedUnformattedIo(IoStatementState &, const Descriptor &,
+    const typeInfo::DerivedType &, const typeInfo::SpecialBinding &);
 
 // Unformatted I/O
 template <Direction DIR>
@@ -332,7 +332,7 @@ static bool UnformattedDescriptorIO(
                 ? typeInfo::SpecialBinding::Which::ReadUnformatted
                 : typeInfo::SpecialBinding::Which::WriteUnformatted)}) {
       // User-defined derived type unformatted I/O
-      return DefinedUnformattedIo(io, descriptor, *special);
+      return DefinedUnformattedIo(io, descriptor, *type, *special);
     } else {
       // Default derived type unformatted I/O
       // TODO: If no component at any level has user defined READ or WRITE


        


More information about the flang-commits mailing list