[flang-commits] [PATCH] D88685: [flang] Fix actions at end of output record

Peter Klausler via Phabricator via flang-commits flang-commits at lists.llvm.org
Thu Oct 1 11:01:49 PDT 2020


klausler created this revision.
klausler added a reviewer: schweitz.
klausler added a project: Flang.
Herald added a reviewer: jdoerfert.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
klausler requested review of this revision.

It turns out that unformatted fixed-size output records
do need to be padded out if short, in order to avoid a
spurious EOF crash reading a short record at the end of the file.
While here in AdvanceRecord(), move the unformatted
variable-length record header/footer writing code to here
from EndIoStatement().


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88685

Files:
  flang/runtime/io-stmt.cpp
  flang/runtime/io-stmt.h
  flang/runtime/unit.cpp


Index: flang/runtime/unit.cpp
===================================================================
--- flang/runtime/unit.cpp
+++ flang/runtime/unit.cpp
@@ -406,15 +406,32 @@
     FinishReadingRecord(handler);
     BeginReadingRecord(handler);
   } else { // Direction::Output
-    if (!isUnformatted) {
-      if (isFixedRecordLength && recordLength) {
-        if (furthestPositionInRecord < *recordLength) {
-          WriteFrame(frameOffsetInFile_, *recordLength, handler);
-          std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord,
-              ' ', *recordLength - furthestPositionInRecord);
-        }
+    if (isFixedRecordLength && recordLength) {
+      // Pad remainder of fixed length record
+      if (furthestPositionInRecord < *recordLength) {
+        WriteFrame(
+            frameOffsetInFile_, recordOffsetInFrame_ + *recordLength, handler);
+        std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord,
+            isUnformatted ? 0 : ' ', *recordLength - furthestPositionInRecord);
+      }
+    } else {
+      positionInRecord = furthestPositionInRecord;
+      if (isUnformatted) {
+        // Append the length of a sequential unformatted variable-length record
+        // as its footer, then overwrite the reserved first four bytes of the
+        // record with its length as its header.  These four bytes were skipped
+        // over in BeginUnformattedIO<Output>().
+        // TODO: Break very large records up into subrecords with negative
+        // headers &/or footers
+        std::uint32_t length;
+        length = furthestPositionInRecord - sizeof length;
+        ok &= Emit(reinterpret_cast<const char *>(&length), sizeof length,
+            sizeof length, handler);
+        positionInRecord = 0;
+        ok &= Emit(reinterpret_cast<const char *>(&length), sizeof length,
+            sizeof length, handler);
       } else {
-        positionInRecord = furthestPositionInRecord;
+        // Terminate formatted variable length record
         ok &= Emit("\n", 1, 1, handler); // TODO: Windows CR+LF
       }
     }
Index: flang/runtime/io-stmt.h
===================================================================
--- flang/runtime/io-stmt.h
+++ flang/runtime/io-stmt.h
@@ -322,7 +322,6 @@
   using ExternalIoStatementState<DIR>::ExternalIoStatementState;
   bool Receive(char *, std::size_t, std::size_t elementBytes = 0);
   bool Emit(const char *, std::size_t, std::size_t elementBytes = 0);
-  int EndIoStatement();
 };
 
 class OpenStatementState : public ExternalIoStatementBase {
Index: flang/runtime/io-stmt.cpp
===================================================================
--- flang/runtime/io-stmt.cpp
+++ flang/runtime/io-stmt.cpp
@@ -698,32 +698,6 @@
   return ExternalIoStatementState<DIR>::Emit(data, bytes, elementBytes);
 }
 
-template <Direction DIR>
-int UnformattedIoStatementState<DIR>::EndIoStatement() {
-  ExternalFileUnit &unit{this->unit()};
-  if constexpr (DIR == Direction::Output) {
-    if (unit.access == Access::Sequential && !unit.isFixedRecordLength) {
-      // Append the length of a sequential unformatted variable-length record
-      // as its footer, then overwrite the reserved first four bytes of the
-      // record with its length as its header.  These four bytes were skipped
-      // over in BeginUnformattedOutput().
-      // TODO: Break very large records up into subrecords with negative
-      // headers &/or footers
-      union {
-        std::uint32_t u;
-        char c[sizeof u];
-      } u;
-      u.u = unit.furthestPositionInRecord - sizeof u;
-      // TODO: Convert record length to little-endian on big-endian host?
-      if (!(this->Emit(u.c, sizeof u) &&
-              (this->HandleAbsolutePosition(0), this->Emit(u.c, sizeof u)))) {
-        return false;
-      }
-    }
-  }
-  return ExternalIoStatementState<DIR>::EndIoStatement();
-}
-
 template class InternalIoStatementState<Direction::Output>;
 template class InternalIoStatementState<Direction::Input>;
 template class InternalFormattedIoStatementState<Direction::Output>;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D88685.295627.patch
Type: text/x-patch
Size: 4098 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/flang-commits/attachments/20201001/9576c870/attachment-0001.bin>


More information about the flang-commits mailing list