[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