[flang-commits] [flang] 4180b29 - [flang][runtime] Support DT edit descriptor in result of READ(SIZE=)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Fri Feb 17 09:15:31 PST 2023
Author: Peter Klausler
Date: 2023-02-17T09:15:18-08:00
New Revision: 4180b29d206f2049b54111d0465e15d47900b66b
URL: https://github.com/llvm/llvm-project/commit/4180b29d206f2049b54111d0465e15d47900b66b
DIFF: https://github.com/llvm/llvm-project/commit/4180b29d206f2049b54111d0465e15d47900b66b.diff
LOG: [flang][runtime] Support DT edit descriptor in result of READ(SIZE=)
When a formatted I/O READ statement processes a DT edit descriptor to call a
user-defined I/O subroutine to read a derived type data item, all of the
characters that that subroutine reads via child I/O count as charecters
read by an edit descriptor and should accumulate in the result returned
by a SIZE= item in the original READ statement's control list.
Differential Revision: https://reviews.llvm.org/D144234
Added:
Modified:
flang/runtime/connection.h
flang/runtime/descriptor-io.cpp
flang/runtime/internal-unit.cpp
flang/runtime/internal-unit.h
flang/runtime/io-stmt.cpp
flang/runtime/io-stmt.h
Removed:
################################################################################
diff --git a/flang/runtime/connection.h b/flang/runtime/connection.h
index acda51124e0d4..70c20e17fd01a 100644
--- a/flang/runtime/connection.h
+++ b/flang/runtime/connection.h
@@ -74,7 +74,7 @@ struct ConnectionState : public ConnectionAttributes {
std::int64_t currentRecordNumber{1}; // 1 is first
- // positionInRecord is the 0-based bytes offset in the current recurd
+ // positionInRecord is the 0-based bytes offset in the current record
// to/from which the next data transfer will occur. It can be past
// furthestPositionInRecord if moved by an X or T or TR control edit
// descriptor.
diff --git a/flang/runtime/descriptor-io.cpp b/flang/runtime/descriptor-io.cpp
index d34ac68c8a533..c6b57bf5f088d 100644
--- a/flang/runtime/descriptor-io.cpp
+++ b/flang/runtime/descriptor-io.cpp
@@ -50,6 +50,13 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io,
int unit{external->unitNumber()};
int ioStat{IostatOk};
char ioMsg[100];
+ std::optional<std::int64_t> startPos;
+ if (edit.descriptor == DataEdit::DefinedDerivedType &&
+ special.which() == typeInfo::SpecialBinding::Which::ReadFormatted) {
+ // DT is an edit descriptor so everything that the child
+ // I/O subroutine reads counts towards READ(SIZE=).
+ startPos = io.InquirePos();
+ }
if (special.IsArgDescriptor(0)) {
auto *p{special.GetProc<void (*)(const Descriptor &, int &, char *,
const Descriptor &, int &, char *, std::size_t, std::size_t)>()};
@@ -69,6 +76,9 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io,
RUNTIME_CHECK(handler, external == closing);
external->DestroyClosed();
}
+ if (startPos) {
+ io.GotChar(io.InquirePos() - *startPos);
+ }
return handler.GetIoStat() == IostatOk;
} else {
// There's a user-defined I/O subroutine, but there's a FORMAT present and
diff --git a/flang/runtime/internal-unit.cpp b/flang/runtime/internal-unit.cpp
index a38db49a83ed6..aa7130f3a6a53 100644
--- a/flang/runtime/internal-unit.cpp
+++ b/flang/runtime/internal-unit.cpp
@@ -157,6 +157,12 @@ void InternalDescriptorUnit<DIR>::BackspaceRecord(IoErrorHandler &handler) {
BeginRecord();
}
+template <Direction DIR>
+std::int64_t InternalDescriptorUnit<DIR>::InquirePos() {
+ return (currentRecordNumber - 1) * recordLength.value_or(0) +
+ positionInRecord + 1;
+}
+
template class InternalDescriptorUnit<Direction::Output>;
template class InternalDescriptorUnit<Direction::Input>;
} // namespace Fortran::runtime::io
diff --git a/flang/runtime/internal-unit.h b/flang/runtime/internal-unit.h
index 06e54dee10f6b..f0c50aac98878 100644
--- a/flang/runtime/internal-unit.h
+++ b/flang/runtime/internal-unit.h
@@ -34,6 +34,7 @@ template <Direction DIR> class InternalDescriptorUnit : public ConnectionState {
std::size_t GetNextInputBytes(const char *&, IoErrorHandler &);
bool AdvanceRecord(IoErrorHandler &);
void BackspaceRecord(IoErrorHandler &);
+ std::int64_t InquirePos();
private:
Descriptor &descriptor() { return staticDescriptor_.descriptor(); }
diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp
index 8e75ca5f68824..9467822d8e410 100644
--- a/flang/runtime/io-stmt.cpp
+++ b/flang/runtime/io-stmt.cpp
@@ -70,6 +70,8 @@ bool IoStatementBase::Inquire(InquiryKeywordHash, std::int64_t &) {
return false;
}
+std::int64_t IoStatementBase::InquirePos() { return 0; }
+
void IoStatementBase::BadInquiryKeywordHashCrash(InquiryKeywordHash inquiry) {
char buffer[16];
const char *decode{InquiryKeywordHashDecode(buffer, sizeof buffer, inquiry)};
@@ -137,6 +139,11 @@ void InternalIoStatementState<DIR>::HandleRelativePosition(std::int64_t n) {
return unit_.HandleRelativePosition(n);
}
+template <Direction DIR>
+std::int64_t InternalIoStatementState<DIR>::InquirePos() {
+ return unit_.InquirePos();
+}
+
template <Direction DIR, typename CHAR>
InternalFormattedIoStatementState<DIR, CHAR>::InternalFormattedIoStatementState(
Buffer buffer, std::size_t length, const CharType *format,
@@ -206,6 +213,10 @@ void ExternalIoStatementBase::SetAsynchronous() {
asynchronousID_ = unit().GetAsynchronousId(*this);
}
+std::int64_t ExternalIoStatementBase::InquirePos() {
+ return unit_.InquirePos();
+}
+
void OpenStatementState::set_path(const char *path, std::size_t length) {
pathLength_ = TrimTrailingSpaces(path, length);
path_ = SaveDefaultCharacter(path, pathLength_, *this);
@@ -635,6 +646,10 @@ bool IoStatementState::Inquire(InquiryKeywordHash inquiry, std::int64_t &n) {
[&](auto &x) { return x.get().Inquire(inquiry, n); }, u_);
}
+std::int64_t IoStatementState::InquirePos() {
+ return common::visit([&](auto &x) { return x.get().InquirePos(); }, u_);
+}
+
void IoStatementState::GotChar(int n) {
if (auto *formattedIn{
get_if<FormattedIoStatementState<Direction::Input>>()}) {
@@ -823,10 +838,6 @@ ExternalFileUnit *ChildIoStatementState<DIR>::GetExternalFileUnit() const {
return child_.parent().GetExternalFileUnit();
}
-template <Direction DIR> void ChildIoStatementState<DIR>::CompleteOperation() {
- IoStatementBase::CompleteOperation();
-}
-
template <Direction DIR> int ChildIoStatementState<DIR>::EndIoStatement() {
CompleteOperation();
auto result{IoStatementBase::EndIoStatement()};
diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index a4aa908378215..c1fdc29f8c255 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -102,6 +102,7 @@ class IoStatementState {
bool Inquire(InquiryKeywordHash, bool &);
bool Inquire(InquiryKeywordHash, std::int64_t, bool &); // PENDING=
bool Inquire(InquiryKeywordHash, std::int64_t &);
+ std::int64_t InquirePos();
void GotChar(signed int = 1); // for READ(SIZE=); can be <0
MutableModes &mutableModes();
@@ -262,6 +263,7 @@ class IoStatementBase : public IoErrorHandler {
bool Inquire(InquiryKeywordHash, bool &);
bool Inquire(InquiryKeywordHash, std::int64_t, bool &);
bool Inquire(InquiryKeywordHash, std::int64_t &);
+ std::int64_t InquirePos();
void BadInquiryKeywordHashCrash(InquiryKeywordHash);
@@ -343,6 +345,7 @@ class InternalIoStatementState : public IoStatementBase,
MutableModes &mutableModes() { return unit_.modes; }
void HandleRelativePosition(std::int64_t);
void HandleAbsolutePosition(std::int64_t);
+ std::int64_t InquirePos();
protected:
bool free_{true};
@@ -406,6 +409,7 @@ class ExternalIoStatementBase : public IoStatementBase {
int EndIoStatement();
ExternalFileUnit *GetExternalFileUnit() const { return &unit_; }
void SetAsynchronous();
+ std::int64_t InquirePos();
private:
ExternalFileUnit &unit_;
@@ -483,7 +487,6 @@ class ChildIoStatementState : public IoStatementBase,
MutableModes &mutableModes();
ConnectionState &GetConnectionState();
ExternalFileUnit *GetExternalFileUnit() const;
- void CompleteOperation();
int EndIoStatement();
bool Emit(const char *, std::size_t bytes, std::size_t elementBytes = 0);
std::size_t GetNextInputBytes(const char *&);
More information about the flang-commits
mailing list