[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