[flang-commits] [flang] 27d666b - [flang] Noncontiguous formats

V Donaldson via flang-commits flang-commits at lists.llvm.org
Wed Aug 24 13:51:41 PDT 2022


Author: V Donaldson
Date: 2022-08-24T13:51:16-07:00
New Revision: 27d666b9adc12a13f67ccde96d5b4d181f56ffc5

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

LOG: [flang] Noncontiguous formats

Add the remaining pieces to support IO for noncontigous formats.
This is done by passing an array descriptor to IO calls.  Scalar
formats continue to pass string and length arguments.  IO calls
with formats are modified to place the new format descriptor
argument directly after the original string and length arguments.

Added: 
    

Modified: 
    flang/include/flang/Runtime/io-api.h
    flang/lib/Lower/IO.cpp
    flang/runtime/format-implementation.h
    flang/runtime/io-api.cpp
    flang/runtime/io-stmt.cpp
    flang/runtime/io-stmt.h
    flang/test/Lower/read-write-buffer.f90
    flang/unittests/Runtime/ExternalIOTest.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Runtime/io-api.h b/flang/include/flang/Runtime/io-api.h
index 972fbace66aec..20ff9fc2ce42b 100644
--- a/flang/include/flang/Runtime/io-api.h
+++ b/flang/include/flang/Runtime/io-api.h
@@ -86,13 +86,15 @@ Cookie IONAME(BeginInternalArrayListInput)(const Descriptor &,
     void **scratchArea = nullptr, std::size_t scratchBytes = 0,
     const char *sourceFile = nullptr, int sourceLine = 0);
 Cookie IONAME(BeginInternalArrayFormattedOutput)(const Descriptor &,
-    const char *format, std::size_t formatLength, void **scratchArea = nullptr,
+    const char *format, std::size_t formatLength,
+    const Descriptor *formatDescriptor = nullptr, void **scratchArea = nullptr,
     std::size_t scratchBytes = 0, const char *sourceFile = nullptr,
-    int sourceLine = 0, const Descriptor *formatDescriptor = nullptr);
+    int sourceLine = 0);
 Cookie IONAME(BeginInternalArrayFormattedInput)(const Descriptor &,
-    const char *format, std::size_t formatLength, void **scratchArea = nullptr,
+    const char *format, std::size_t formatLength,
+    const Descriptor *formatDescriptor = nullptr, void **scratchArea = nullptr,
     std::size_t scratchBytes = 0, const char *sourceFile = nullptr,
-    int sourceLine = 0, const Descriptor *formatDescriptor = nullptr);
+    int sourceLine = 0);
 
 // Internal I/O to/from a default-kind character scalar can avoid a
 // descriptor.
@@ -106,14 +108,14 @@ Cookie IONAME(BeginInternalListInput)(const char *internal,
     int sourceLine = 0);
 Cookie IONAME(BeginInternalFormattedOutput)(char *internal,
     std::size_t internalLength, const char *format, std::size_t formatLength,
-    void **scratchArea = nullptr, std::size_t scratchBytes = 0,
-    const char *sourceFile = nullptr, int sourceLine = 0,
-    const Descriptor *formatDescriptor = nullptr);
+    const Descriptor *formatDescriptor = nullptr, void **scratchArea = nullptr,
+    std::size_t scratchBytes = 0, const char *sourceFile = nullptr,
+    int sourceLine = 0);
 Cookie IONAME(BeginInternalFormattedInput)(const char *internal,
     std::size_t internalLength, const char *format, std::size_t formatLength,
-    void **scratchArea = nullptr, std::size_t scratchBytes = 0,
-    const char *sourceFile = nullptr, int sourceLine = 0,
-    const Descriptor *formatDescriptor = nullptr);
+    const Descriptor *formatDescriptor = nullptr, void **scratchArea = nullptr,
+    std::size_t scratchBytes = 0, const char *sourceFile = nullptr,
+    int sourceLine = 0);
 
 // External unit numbers must fit in default integers. When the integer
 // provided as UNIT is of a wider type than the default integer, it could
@@ -137,11 +139,11 @@ Cookie IONAME(BeginExternalListOutput)(ExternalUnit = DefaultUnit,
 Cookie IONAME(BeginExternalListInput)(ExternalUnit = DefaultUnit,
     const char *sourceFile = nullptr, int sourceLine = 0);
 Cookie IONAME(BeginExternalFormattedOutput)(const char *format, std::size_t,
-    ExternalUnit = DefaultUnit, const char *sourceFile = nullptr,
-    int sourceLine = 0, const Descriptor *formatDescriptor = nullptr);
+    const Descriptor *formatDescriptor = nullptr, ExternalUnit = DefaultUnit,
+    const char *sourceFile = nullptr, int sourceLine = 0);
 Cookie IONAME(BeginExternalFormattedInput)(const char *format, std::size_t,
-    ExternalUnit = DefaultUnit, const char *sourceFile = nullptr,
-    int sourceLine = 0, const Descriptor *formatDescriptor = nullptr);
+    const Descriptor *formatDescriptor = nullptr, ExternalUnit = DefaultUnit,
+    const char *sourceFile = nullptr, int sourceLine = 0);
 Cookie IONAME(BeginUnformattedOutput)(ExternalUnit = DefaultUnit,
     const char *sourceFile = nullptr, int sourceLine = 0);
 Cookie IONAME(BeginUnformattedInput)(ExternalUnit = DefaultUnit,

diff  --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index b7fc7c4d1033e..9a73e1c30c8e3 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -1487,9 +1487,15 @@ genFormat(Fortran::lower::AbstractConverter &converter, mlir::Location loc,
   assert(pExpr && "missing format expression");
   auto e = Fortran::semantics::GetExpr(*pExpr);
   if (Fortran::semantics::ExprHasTypeCategory(
-          *e, Fortran::common::TypeCategory::Character))
+          *e, Fortran::common::TypeCategory::Character)) {
     // character expression
+    if (e->Rank())
+      // Array: return address(descriptor) and no length (and no kind value).
+      return {fir::getBase(converter.genExprBox(loc, *e, stmtCtx)),
+              mlir::Value{}, mlir::Value{}};
+    // Scalar: return address(format) and format length (and no kind value).
     return lowerStringLit(converter, loc, stmtCtx, *pExpr, strTy, lenTy);
+  }
 
   if (Fortran::semantics::ExprHasTypeCategory(
           *e, Fortran::common::TypeCategory::Integer) &&
@@ -1855,11 +1861,26 @@ void genBeginDataTransferCallArgs(
   auto maybeGetFormatArgs = [&]() {
     if (!isFormatted || isListOrNml)
       return;
-    auto pair =
+    std::tuple triple =
         getFormat(converter, loc, stmt, ioFuncTy.getInput(ioArgs.size()),
                   ioFuncTy.getInput(ioArgs.size() + 1), stmtCtx);
-    ioArgs.push_back(std::get<0>(pair)); // format character string
-    ioArgs.push_back(std::get<1>(pair)); // format length
+    mlir::Value address = std::get<0>(triple);
+    mlir::Value length = std::get<1>(triple);
+    if (length) {
+      // Scalar format: string arg + length arg; no format descriptor arg
+      ioArgs.push_back(address); // format string
+      ioArgs.push_back(length);  // format length
+      ioArgs.push_back(
+          builder.createNullConstant(loc, ioFuncTy.getInput(ioArgs.size())));
+      return;
+    }
+    // Array format: no string arg, no length arg; format descriptor arg
+    ioArgs.push_back(
+        builder.createNullConstant(loc, ioFuncTy.getInput(ioArgs.size())));
+    ioArgs.push_back(
+        builder.createNullConstant(loc, ioFuncTy.getInput(ioArgs.size())));
+    ioArgs.push_back( // format descriptor
+        builder.createConvert(loc, ioFuncTy.getInput(ioArgs.size()), address));
   };
   if constexpr (hasIOCtrl) { // READ or WRITE
     if (isInternal) {
@@ -1894,15 +1915,11 @@ void genBeginDataTransferCallArgs(
         loc, builder.getIntegerAttr(ioFuncTy.getInput(ioArgs.size()),
                                     Fortran::runtime::io::DefaultUnit)));
   }
-  // File name and line number.
+  // File name and line number are always the last two arguments.
   ioArgs.push_back(
       locToFilename(converter, loc, ioFuncTy.getInput(ioArgs.size())));
   ioArgs.push_back(
       locToLineNo(converter, loc, ioFuncTy.getInput(ioArgs.size())));
-  // Placeholder for format passed as a descriptor.
-  if (isFormatted && !isListOrNml)
-    ioArgs.push_back(
-        builder.createNullConstant(loc, ioFuncTy.getInput(ioArgs.size())));
 }
 
 template <bool isInput, bool hasIOCtrl = true, typename A>

diff  --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h
index 251ce241c9a3b..275cbab2258b0 100644
--- a/flang/runtime/format-implementation.h
+++ b/flang/runtime/format-implementation.h
@@ -33,21 +33,22 @@ FormatControl<CONTEXT>::FormatControl(const Terminator &terminator,
   RUNTIME_CHECK(terminator, maxHeight == maxHeight_);
   if (!format && formatDescriptor) {
     // The format is a character array passed via a descriptor.
-    formatLength = formatDescriptor->SizeInBytes() / sizeof(CharType);
+    std::size_t elements{formatDescriptor->Elements()};
+    std::size_t elementBytes{formatDescriptor->ElementBytes()};
+    formatLength = elements * elementBytes / sizeof(CharType);
     formatLength_ = static_cast<int>(formatLength);
     if (formatDescriptor->IsContiguous()) {
       // Treat the contiguous array as a single character value.
-      format = const_cast<const CharType *>(
+      format_ = const_cast<const CharType *>(
           reinterpret_cast<CharType *>(formatDescriptor->raw().base_addr));
     } else {
       // Concatenate its elements into a temporary array.
       char *p{reinterpret_cast<char *>(
           AllocateMemoryOrCrash(terminator, formatLength * sizeof(CharType)))};
-      format = p;
+      format_ = p;
       SubscriptValue at[maxRank];
       formatDescriptor->GetLowerBounds(at);
-      auto elementBytes{formatDescriptor->ElementBytes()};
-      for (std::size_t j{0}; j < formatLength; ++j) {
+      for (std::size_t j{0}; j < elements; ++j) {
         std::memcpy(p, formatDescriptor->Element<char>(at), elementBytes);
         p += elementBytes;
         formatDescriptor->IncrementSubscripts(at);

diff  --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index 152ac9fb6f60f..197cfcc2f7f3d 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -69,32 +69,32 @@ Cookie IONAME(BeginInternalArrayListInput)(const Descriptor &descriptor,
 
 template <Direction DIR>
 Cookie BeginInternalArrayFormattedIO(const Descriptor &descriptor,
-    const char *format, std::size_t formatLength, void ** /*scratchArea*/,
-    std::size_t /*scratchBytes*/, const char *sourceFile, int sourceLine,
-    const Descriptor *formatDescriptor) {
+    const char *format, std::size_t formatLength,
+    const Descriptor *formatDescriptor, void ** /*scratchArea*/,
+    std::size_t /*scratchBytes*/, const char *sourceFile, int sourceLine) {
   Terminator oom{sourceFile, sourceLine};
   return &New<InternalFormattedIoStatementState<DIR>>{oom}(descriptor, format,
-      formatLength, sourceFile, sourceLine, formatDescriptor)
+      formatLength, formatDescriptor, sourceFile, sourceLine)
               .release()
               ->ioStatementState();
 }
 
 Cookie IONAME(BeginInternalArrayFormattedOutput)(const Descriptor &descriptor,
-    const char *format, std::size_t formatLength, void **scratchArea,
-    std::size_t scratchBytes, const char *sourceFile, int sourceLine,
-    const Descriptor *formatDescriptor) {
+    const char *format, std::size_t formatLength,
+    const Descriptor *formatDescriptor, void **scratchArea,
+    std::size_t scratchBytes, const char *sourceFile, int sourceLine) {
   return BeginInternalArrayFormattedIO<Direction::Output>(descriptor, format,
-      formatLength, scratchArea, scratchBytes, sourceFile, sourceLine,
-      formatDescriptor);
+      formatLength, formatDescriptor, scratchArea, scratchBytes, sourceFile,
+      sourceLine);
 }
 
 Cookie IONAME(BeginInternalArrayFormattedInput)(const Descriptor &descriptor,
-    const char *format, std::size_t formatLength, void **scratchArea,
-    std::size_t scratchBytes, const char *sourceFile, int sourceLine,
-    const Descriptor *formatDescriptor) {
+    const char *format, std::size_t formatLength,
+    const Descriptor *formatDescriptor, void **scratchArea,
+    std::size_t scratchBytes, const char *sourceFile, int sourceLine) {
   return BeginInternalArrayFormattedIO<Direction::Input>(descriptor, format,
-      formatLength, scratchArea, scratchBytes, sourceFile, sourceLine,
-      formatDescriptor);
+      formatLength, formatDescriptor, scratchArea, scratchBytes, sourceFile,
+      sourceLine);
 }
 
 template <Direction DIR>
@@ -127,33 +127,32 @@ template <Direction DIR>
 Cookie BeginInternalFormattedIO(
     std::conditional_t<DIR == Direction::Input, const char, char> *internal,
     std::size_t internalLength, const char *format, std::size_t formatLength,
-    void ** /*scratchArea*/, std::size_t /*scratchBytes*/,
-    const char *sourceFile, int sourceLine,
-    const Descriptor *formatDescriptor) {
+    const Descriptor *formatDescriptor, void ** /*scratchArea*/,
+    std::size_t /*scratchBytes*/, const char *sourceFile, int sourceLine) {
   Terminator oom{sourceFile, sourceLine};
   return &New<InternalFormattedIoStatementState<DIR>>{oom}(internal,
-      internalLength, format, formatLength, sourceFile, sourceLine,
-      formatDescriptor)
+      internalLength, format, formatLength, formatDescriptor, sourceFile,
+      sourceLine)
               .release()
               ->ioStatementState();
 }
 
 Cookie IONAME(BeginInternalFormattedOutput)(char *internal,
     std::size_t internalLength, const char *format, std::size_t formatLength,
-    void **scratchArea, std::size_t scratchBytes, const char *sourceFile,
-    int sourceLine, const Descriptor *formatDescriptor) {
+    const Descriptor *formatDescriptor, void **scratchArea,
+    std::size_t scratchBytes, const char *sourceFile, int sourceLine) {
   return BeginInternalFormattedIO<Direction::Output>(internal, internalLength,
-      format, formatLength, scratchArea, scratchBytes, sourceFile, sourceLine,
-      formatDescriptor);
+      format, formatLength, formatDescriptor, scratchArea, scratchBytes,
+      sourceFile, sourceLine);
 }
 
 Cookie IONAME(BeginInternalFormattedInput)(const char *internal,
     std::size_t internalLength, const char *format, std::size_t formatLength,
-    void **scratchArea, std::size_t scratchBytes, const char *sourceFile,
-    int sourceLine, const Descriptor *formatDescriptor) {
+    const Descriptor *formatDescriptor, void **scratchArea,
+    std::size_t scratchBytes, const char *sourceFile, int sourceLine) {
   return BeginInternalFormattedIO<Direction::Input>(internal, internalLength,
-      format, formatLength, scratchArea, scratchBytes, sourceFile, sourceLine,
-      formatDescriptor);
+      format, formatLength, formatDescriptor, scratchArea, scratchBytes,
+      sourceFile, sourceLine);
 }
 
 static Cookie NoopUnit(const Terminator &terminator, int unitNumber,
@@ -244,8 +243,8 @@ Cookie IONAME(BeginExternalListInput)(
 
 template <Direction DIR>
 Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength,
-    ExternalUnit unitNumber, const char *sourceFile, int sourceLine,
-    const Descriptor *formatDescriptor) {
+    const Descriptor *formatDescriptor, ExternalUnit unitNumber,
+    const char *sourceFile, int sourceLine) {
   Terminator terminator{sourceFile, sourceLine};
   if (unitNumber == DefaultUnit) {
     unitNumber = DIR == Direction::Input ? 5 : 6;
@@ -269,8 +268,8 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength,
     }
     if (iostat == IostatOk) {
       return &child->BeginIoStatement<ChildFormattedIoStatementState<DIR>>(
-          *child, format, formatLength, sourceFile, sourceLine,
-          formatDescriptor);
+          *child, format, formatLength, formatDescriptor, sourceFile,
+          sourceLine);
     } else {
       return &child->BeginIoStatement<ErroneousIoStatementState>(
           iostat, nullptr /* no unit */, sourceFile, sourceLine);
@@ -281,8 +280,8 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength,
     }
     if (iostat == IostatOk) {
       return &unit->BeginIoStatement<ExternalFormattedIoStatementState<DIR>>(
-          terminator, *unit, format, formatLength, sourceFile, sourceLine,
-          formatDescriptor);
+          terminator, *unit, format, formatLength, formatDescriptor, sourceFile,
+          sourceLine);
     } else {
       return &unit->BeginIoStatement<ErroneousIoStatementState>(
           terminator, iostat, unit, sourceFile, sourceLine);
@@ -291,17 +290,17 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength,
 }
 
 Cookie IONAME(BeginExternalFormattedOutput)(const char *format,
-    std::size_t formatLength, ExternalUnit unitNumber, const char *sourceFile,
-    int sourceLine, const Descriptor *formatDescriptor) {
+    std::size_t formatLength, const Descriptor *formatDescriptor,
+    ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
   return BeginExternalFormattedIO<Direction::Output>(format, formatLength,
-      unitNumber, sourceFile, sourceLine, formatDescriptor);
+      formatDescriptor, unitNumber, sourceFile, sourceLine);
 }
 
 Cookie IONAME(BeginExternalFormattedInput)(const char *format,
-    std::size_t formatLength, ExternalUnit unitNumber, const char *sourceFile,
-    int sourceLine, const Descriptor *formatDescriptor) {
+    std::size_t formatLength, const Descriptor *formatDescriptor,
+    ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
   return BeginExternalFormattedIO<Direction::Input>(format, formatLength,
-      unitNumber, sourceFile, sourceLine, formatDescriptor);
+      formatDescriptor, unitNumber, sourceFile, sourceLine);
 }
 
 template <Direction DIR>

diff  --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index fa73371e3f7f5..3ab5c879fbb66 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -140,8 +140,8 @@ void InternalIoStatementState<DIR>::HandleRelativePosition(std::int64_t n) {
 template <Direction DIR, typename CHAR>
 InternalFormattedIoStatementState<DIR, CHAR>::InternalFormattedIoStatementState(
     Buffer buffer, std::size_t length, const CharType *format,
-    std::size_t formatLength, const char *sourceFile, int sourceLine,
-    const Descriptor *formatDescriptor)
+    std::size_t formatLength, const Descriptor *formatDescriptor,
+    const char *sourceFile, int sourceLine)
     : InternalIoStatementState<DIR>{buffer, length, sourceFile, sourceLine},
       ioStatementState_{*this}, format_{*this, format, formatLength,
                                     formatDescriptor} {}
@@ -149,7 +149,7 @@ InternalFormattedIoStatementState<DIR, CHAR>::InternalFormattedIoStatementState(
 template <Direction DIR, typename CHAR>
 InternalFormattedIoStatementState<DIR, CHAR>::InternalFormattedIoStatementState(
     const Descriptor &d, const CharType *format, std::size_t formatLength,
-    const char *sourceFile, int sourceLine, const Descriptor *formatDescriptor)
+    const Descriptor *formatDescriptor, const char *sourceFile, int sourceLine)
     : InternalIoStatementState<DIR>{d, sourceFile, sourceLine},
       ioStatementState_{*this}, format_{*this, format, formatLength,
                                     formatDescriptor} {}
@@ -398,7 +398,7 @@ void ExternalIoStatementState<DIR>::FinishReadingRecord() {
 template <Direction DIR, typename CHAR>
 ExternalFormattedIoStatementState<DIR, CHAR>::ExternalFormattedIoStatementState(
     ExternalFileUnit &unit, const CHAR *format, std::size_t formatLength,
-    const char *sourceFile, int sourceLine, const Descriptor *formatDescriptor)
+    const Descriptor *formatDescriptor, const char *sourceFile, int sourceLine)
     : ExternalIoStatementState<DIR>{unit, sourceFile, sourceLine},
       format_{*this, format, formatLength, formatDescriptor} {}
 
@@ -853,7 +853,7 @@ void ChildIoStatementState<DIR>::HandleRelativePosition(std::int64_t n) {
 template <Direction DIR, typename CHAR>
 ChildFormattedIoStatementState<DIR, CHAR>::ChildFormattedIoStatementState(
     ChildIo &child, const CHAR *format, std::size_t formatLength,
-    const char *sourceFile, int sourceLine, const Descriptor *formatDescriptor)
+    const Descriptor *formatDescriptor, const char *sourceFile, int sourceLine)
     : ChildIoStatementState<DIR>{child, sourceFile, sourceLine},
       mutableModes_{child.parent().mutableModes()}, format_{*this, format,
                                                         formatLength,

diff  --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 388bcaa1aad81..9e040e0e4ae13 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -358,11 +358,11 @@ class InternalFormattedIoStatementState
   using typename InternalIoStatementState<DIR>::Buffer;
   InternalFormattedIoStatementState(Buffer internal, std::size_t internalLength,
       const CharType *format, std::size_t formatLength,
-      const char *sourceFile = nullptr, int sourceLine = 0,
-      const Descriptor *formatDescriptor = nullptr);
+      const Descriptor *formatDescriptor = nullptr,
+      const char *sourceFile = nullptr, int sourceLine = 0);
   InternalFormattedIoStatementState(const Descriptor &, const CharType *format,
-      std::size_t formatLength, const char *sourceFile = nullptr,
-      int sourceLine = 0, const Descriptor *formatDescriptor = nullptr);
+      std::size_t formatLength, const Descriptor *formatDescriptor = nullptr,
+      const char *sourceFile = nullptr, int sourceLine = 0);
   IoStatementState &ioStatementState() { return ioStatementState_; }
   void CompleteOperation();
   int EndIoStatement();
@@ -444,8 +444,8 @@ class ExternalFormattedIoStatementState
 public:
   using CharType = CHAR;
   ExternalFormattedIoStatementState(ExternalFileUnit &, const CharType *format,
-      std::size_t formatLength, const char *sourceFile = nullptr,
-      int sourceLine = 0, const Descriptor *formatDescriptor = nullptr);
+      std::size_t formatLength, const Descriptor *formatDescriptor = nullptr,
+      const char *sourceFile = nullptr, int sourceLine = 0);
   void CompleteOperation();
   int EndIoStatement();
   std::optional<DataEdit> GetNextDataEdit(
@@ -500,8 +500,8 @@ class ChildFormattedIoStatementState : public ChildIoStatementState<DIR>,
 public:
   using CharType = CHAR;
   ChildFormattedIoStatementState(ChildIo &, const CharType *format,
-      std::size_t formatLength, const char *sourceFile = nullptr,
-      int sourceLine = 0, const Descriptor *formatDescriptor = nullptr);
+      std::size_t formatLength, const Descriptor *formatDescriptor = nullptr,
+      const char *sourceFile = nullptr, int sourceLine = 0);
   MutableModes &mutableModes() { return mutableModes_; }
   void CompleteOperation();
   int EndIoStatement();

diff  --git a/flang/test/Lower/read-write-buffer.f90 b/flang/test/Lower/read-write-buffer.f90
index 2972049ba74ca..889209242cb4a 100644
--- a/flang/test/Lower/read-write-buffer.f90
+++ b/flang/test/Lower/read-write-buffer.f90
@@ -10,11 +10,12 @@ subroutine test_array_format
   character(10) :: array(2)
   array(1) ="(15HThis i"
   array(2) ="s a test.)"
-  ! CHECK-DAG: %[[fmtLen:.*]] = arith.muli %[[c10]], %[[c2]] : index
-  ! CHECK-DAG: %[[scalarFmt:.*]] = fir.convert %[[mem]] : (!fir.ref<!fir.array<2x!fir.char<1,10>>>) -> !fir.ref<!fir.char<1,?>>
-  ! CHECK-DAG: %[[fmtArg:.*]] = fir.convert %[[scalarFmt]] : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
-  ! CHECK-DAG: %[[fmtLenArg:.*]] = fir.convert %[[fmtLen]] : (index) -> i64 
-  ! CHECK: fir.call @_FortranAioBeginExternalFormattedOutput(%[[fmtArg]], %[[fmtLenArg]], {{.*}}) 
+  ! CHECK: %[[shape:.*]] = fir.shape %c2{{.*}} (index) -> !fir.shape<1>
+  ! CHECK: %[[fmtBox:.*]] = fir.embox %[[mem]](%[[shape]]) : (!fir.ref<!fir.array<2x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.box<!fir.array<2x!fir.char<1,10>>>
+  ! CHECK: %[[fmtArg:.*]] = fir.zero_bits !fir.ref<i8>
+  ! CHECK: %[[fmtLenArg:.*]] = fir.zero_bits i64
+  ! CHECK: %[[fmtDesc:.*]] = fir.convert %[[fmtBox]] : (!fir.box<!fir.array<2x!fir.char<1,10>>>) -> !fir.box<none>
+  ! CHECK: fir.call @_FortranAioBeginExternalFormattedOutput(%[[fmtArg]], %[[fmtLenArg]], %[[fmtDesc]], {{.*}}) 
   write(*, array) 
 end subroutine
 

diff  --git a/flang/unittests/Runtime/ExternalIOTest.cpp b/flang/unittests/Runtime/ExternalIOTest.cpp
index a129204908315..389abf1d0404a 100644
--- a/flang/unittests/Runtime/ExternalIOTest.cpp
+++ b/flang/unittests/Runtime/ExternalIOTest.cpp
@@ -357,7 +357,7 @@ TEST(ExternalIOTests, TestDirectFormatted) {
   for (int j{1}; j <= records; ++j) {
     // WRITE(UNIT=unit,FMT=fmt,REC=j) j
     io = IONAME(BeginExternalFormattedOutput)(
-        fmt, sizeof fmt - 1, unit, __FILE__, __LINE__);
+        fmt, sizeof fmt - 1, nullptr, unit, __FILE__, __LINE__);
     ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')';
     ASSERT_TRUE(IONAME(OutputInteger64)(io, j)) << "OutputInteger64()";
     ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
@@ -367,7 +367,7 @@ TEST(ExternalIOTests, TestDirectFormatted) {
   for (int j{records}; j >= 1; --j) {
     // READ(UNIT=unit,FMT=fmt,REC=j) n
     io = IONAME(BeginExternalFormattedInput)(
-        fmt, sizeof fmt - 1, unit, __FILE__, __LINE__);
+        fmt, sizeof fmt - 1, nullptr, unit, __FILE__, __LINE__);
     ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')';
     std::int64_t buffer;
     ASSERT_TRUE(IONAME(InputInteger)(io, buffer)) << "InputInteger()";
@@ -412,7 +412,7 @@ TEST(ExternalIOTests, TestSequentialVariableFormatted) {
     std::snprintf(fmt, sizeof fmt, "(%dI4)", j);
     // DO J=1,RECORDS; WRITE(UNIT=unit,FMT=fmt) BUFFER(0:j); END DO
     io = IONAME(BeginExternalFormattedOutput)(
-        fmt, std::strlen(fmt), unit, __FILE__, __LINE__);
+        fmt, std::strlen(fmt), nullptr, unit, __FILE__, __LINE__);
     for (int k{0}; k < j; ++k) {
       ASSERT_TRUE(IONAME(OutputInteger64)(io, buffer[k]))
           << "OutputInteger64()";
@@ -430,7 +430,7 @@ TEST(ExternalIOTests, TestSequentialVariableFormatted) {
     std::snprintf(fmt, sizeof fmt, "(%dI4)", j);
     // DO J=1,RECORDS; READ(UNIT=unit,FMT=fmt) n; check n; END DO
     io = IONAME(BeginExternalFormattedInput)(
-        fmt, std::strlen(fmt), unit, __FILE__, __LINE__);
+        fmt, std::strlen(fmt), nullptr, unit, __FILE__, __LINE__);
 
     std::int64_t check[records];
     for (int k{0}; k < j; ++k) {
@@ -456,7 +456,7 @@ TEST(ExternalIOTests, TestSequentialVariableFormatted) {
     std::snprintf(fmt, sizeof fmt, "(%dI4)", j);
     // READ(UNIT=unit,FMT=fmt,SIZE=chars) n; check
     io = IONAME(BeginExternalFormattedInput)(
-        fmt, std::strlen(fmt), unit, __FILE__, __LINE__);
+        fmt, std::strlen(fmt), nullptr, unit, __FILE__, __LINE__);
 
     std::int64_t check[records];
     for (int k{0}; k < j; ++k) {
@@ -510,7 +510,7 @@ TEST(ExternalIOTests, TestNonAvancingInput) {
   for (const auto &record : records) {
     // WRITE(UNIT=unit,FMT=fmt) record
     io = IONAME(BeginExternalFormattedOutput)(
-        fmt.data(), fmt.length(), unit, __FILE__, __LINE__);
+        fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__);
     ASSERT_TRUE(IONAME(OutputAscii)(io, record.data(), record.length()))
         << "OutputAscii()";
     ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
@@ -541,7 +541,7 @@ TEST(ExternalIOTests, TestNonAvancingInput) {
   for (auto &inputItem : inputItems) {
     // READ(UNIT=unit, FMT=fmt, ADVANCE='NO', IOSTAT=iostat) inputItem
     io = IONAME(BeginExternalFormattedInput)(
-        fmt.data(), fmt.length(), unit, __FILE__, __LINE__);
+        fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__);
     IONAME(EnableHandlers)(io, true, false, false, false, false);
     ASSERT_TRUE(IONAME(SetAdvance)(io, "NO", 2)) << "SetAdvance(NO)" << j;
     bool result{
@@ -581,7 +581,7 @@ TEST(ExternalIOTests, TestWriteAfterNonAvancingInput) {
   for (const auto &record : records) {
     // WRITE(UNIT=unit,FMT=fmt) record
     io = IONAME(BeginExternalFormattedOutput)(
-        fmt.data(), fmt.length(), unit, __FILE__, __LINE__);
+        fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__);
     ASSERT_TRUE(IONAME(OutputAscii)(io, record.data(), record.length()))
         << "OutputAscii()";
     ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
@@ -608,7 +608,7 @@ TEST(ExternalIOTests, TestWriteAfterNonAvancingInput) {
   for (auto &inputItem : inputItems) {
     // READ(UNIT=unit, FMT=fmt, ADVANCE='NO', IOSTAT=iostat) inputItem
     io = IONAME(BeginExternalFormattedInput)(
-        fmt.data(), fmt.length(), unit, __FILE__, __LINE__);
+        fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__);
     IONAME(EnableHandlers)(io, true, false, false, false, false);
     ASSERT_TRUE(IONAME(SetAdvance)(io, "NO", 2)) << "SetAdvance(NO)" << j;
     ASSERT_TRUE(
@@ -625,7 +625,7 @@ TEST(ExternalIOTests, TestWriteAfterNonAvancingInput) {
   static constexpr std::string_view outputItem{"XYZ"};
   // WRITE(UNIT=unit,FMT=fmt) record
   io = IONAME(BeginExternalFormattedOutput)(
-      fmt.data(), fmt.length(), unit, __FILE__, __LINE__);
+      fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__);
   ASSERT_TRUE(IONAME(OutputAscii)(io, outputItem.data(), outputItem.length()))
       << "OutputAscii()";
   ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
@@ -643,7 +643,7 @@ TEST(ExternalIOTests, TestWriteAfterNonAvancingInput) {
   std::string expectedRecord{"ABCDEFGHXYZ         "};
   // READ(UNIT=unit, FMT=fmt, IOSTAT=iostat) result
   io = IONAME(BeginExternalFormattedInput)(
-      fmt.data(), fmt.length(), unit, __FILE__, __LINE__);
+      fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__);
   IONAME(EnableHandlers)(io, true, false, false, false, false);
   ASSERT_TRUE(
       IONAME(InputAscii)(io, resultRecord.data(), resultRecord.length()))
@@ -674,7 +674,7 @@ TEST(ExternalIOTests, TestWriteAfterEndfile) {
   // WRITE(unit,"(I8)") 1234
   static constexpr std::string_view format{"(I8)"};
   io = IONAME(BeginExternalFormattedOutput)(
-      format.data(), format.length(), unit, __FILE__, __LINE__);
+      format.data(), format.length(), nullptr, unit, __FILE__, __LINE__);
   ASSERT_TRUE(IONAME(OutputInteger64)(io, 1234)) << "OutputInteger64()";
   ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
       << "EndIoStatement for WRITE before ENDFILE";
@@ -684,7 +684,7 @@ TEST(ExternalIOTests, TestWriteAfterEndfile) {
       << "EndIoStatement for ENDFILE";
   // WRITE(unit,"(I8)",iostat=iostat) 5678
   io = IONAME(BeginExternalFormattedOutput)(
-      format.data(), format.length(), unit, __FILE__, __LINE__);
+      format.data(), format.length(), nullptr, unit, __FILE__, __LINE__);
   IONAME(EnableHandlers)(io, true /*IOSTAT=*/);
   ASSERT_FALSE(IONAME(OutputInteger64)(io, 5678)) << "OutputInteger64()";
   ASSERT_EQ(IONAME(EndIoStatement)(io), IostatWriteAfterEndfile)
@@ -695,7 +695,7 @@ TEST(ExternalIOTests, TestWriteAfterEndfile) {
       << "EndIoStatement for BACKSPACE";
   // WRITE(unit,"(I8)") 3456
   io = IONAME(BeginExternalFormattedOutput)(
-      format.data(), format.length(), unit, __FILE__, __LINE__);
+      format.data(), format.length(), nullptr, unit, __FILE__, __LINE__);
   ASSERT_TRUE(IONAME(OutputInteger64)(io, 3456)) << "OutputInteger64()";
   ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
       << "EndIoStatement for WRITE after BACKSPACE";
@@ -706,7 +706,7 @@ TEST(ExternalIOTests, TestWriteAfterEndfile) {
   // READ(unit,"(I8)",END=) j, k
   std::int64_t j{-1}, k{-1}, eof{-1};
   io = IONAME(BeginExternalFormattedInput)(
-      format.data(), format.length(), unit, __FILE__, __LINE__);
+      format.data(), format.length(), nullptr, unit, __FILE__, __LINE__);
   IONAME(EnableHandlers)(io, false, false, true /*END=*/);
   ASSERT_TRUE(IONAME(InputInteger)(io, j)) << "InputInteger(j)";
   ASSERT_EQ(j, 1234) << "READ(j)";


        


More information about the flang-commits mailing list