[flang-commits] [flang] 5d5b968 - [flang] Add fixes and missing stmts to I/O runtime API handlers (ext. I/O part 8)

peter klausler via flang-commits flang-commits at lists.llvm.org
Sat Jul 4 12:54:19 PDT 2020


Author: peter klausler
Date: 2020-07-04T12:53:31-07:00
New Revision: 5d5b9682527debef472bd8547e4e10df22ac0ef4

URL: https://github.com/llvm/llvm-project/commit/5d5b9682527debef472bd8547e4e10df22ac0ef4
DIFF: https://github.com/llvm/llvm-project/commit/5d5b9682527debef472bd8547e4e10df22ac0ef4.diff

LOG: [flang] Add fixes and missing stmts to I/O runtime API handlers (ext. I/O part 8)

Complete the rework of the initial implementation of external I/O
to fix problems found in testing (tests to follow); add handlers
for hitherto unimplemented PAUSE, FLUSH, ENDFILE, BACKSPACE, and
REWIND statements.

Reviewed By: tskeith, sscalpone

Differential Revision: https://reviews.llvm.org/D83162

Added: 
    

Modified: 
    flang/runtime/io-api.cpp
    flang/runtime/stop.cpp
    flang/runtime/stop.h

Removed: 
    


################################################################################
diff  --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index bbb7eb2863c6..77b32ca6bc1c 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -121,10 +121,12 @@ Cookie BeginExternalListIO(
     terminator.Crash("List-directed I/O attempted on unformatted file");
     return nullptr;
   }
+  IoErrorHandler handler{terminator};
+  unit.SetDirection(DIR, handler);
   IoStatementState &io{unit.BeginIoStatement<ExternalListIoStatementState<DIR>>(
       unit, sourceFile, sourceLine)};
   if constexpr (DIR == Direction::Input) {
-    io.AdvanceRecord();
+    unit.BeginReadingRecord(handler);
   }
   return &io;
 }
@@ -154,11 +156,13 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength,
     terminator.Crash("Formatted I/O attempted on unformatted file");
     return nullptr;
   }
+  IoErrorHandler handler{terminator};
+  unit.SetDirection(DIR, handler);
   IoStatementState &io{
       unit.BeginIoStatement<ExternalFormattedIoStatementState<DIR>>(
           unit, format, formatLength, sourceFile, sourceLine)};
   if constexpr (DIR == Direction::Input) {
-    io.AdvanceRecord();
+    unit.BeginReadingRecord(handler);
   }
   return &io;
 }
@@ -181,17 +185,19 @@ template <Direction DIR>
 Cookie BeginUnformattedIO(
     ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
   Terminator terminator{sourceFile, sourceLine};
-  ExternalFileUnit &file{
+  ExternalFileUnit &unit{
       ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
-  if (!file.isUnformatted) {
+  if (!unit.isUnformatted) {
     terminator.Crash("Unformatted output attempted on formatted file");
   }
-  IoStatementState &io{file.BeginIoStatement<UnformattedIoStatementState<DIR>>(
-      file, sourceFile, sourceLine)};
+  IoStatementState &io{unit.BeginIoStatement<UnformattedIoStatementState<DIR>>(
+      unit, sourceFile, sourceLine)};
+  IoErrorHandler handler{terminator};
+  unit.SetDirection(DIR, handler);
   if constexpr (DIR == Direction::Input) {
-    io.AdvanceRecord();
+    unit.BeginReadingRecord(handler);
   } else {
-    if (file.access == Access::Sequential && !file.recordLength.has_value()) {
+    if (unit.access == Access::Sequential && !unit.isFixedRecordLength) {
       // Create space for (sub)record header to be completed by
       // UnformattedIoStatementState<Direction::Output>::EndIoStatement()
       io.Emit("\0\0\0\0", 4); // placeholder for record length header
@@ -225,8 +231,10 @@ Cookie IONAME(BeginOpenUnit)( // OPEN(without NEWUNIT=)
 Cookie IONAME(BeginOpenNewUnit)( // OPEN(NEWUNIT=j)
     const char *sourceFile, int sourceLine) {
   Terminator terminator{sourceFile, sourceLine};
-  return IONAME(BeginOpenUnit)(
-      ExternalFileUnit::NewUnit(terminator), sourceFile, sourceLine);
+  ExternalFileUnit &unit{ExternalFileUnit::LookUpOrCreate(
+      ExternalFileUnit::NewUnit(terminator), terminator)};
+  return &unit.BeginIoStatement<OpenStatementState>(
+      unit, false /*wasExtant*/, sourceFile, sourceLine);
 }
 
 Cookie IONAME(BeginClose)(
@@ -243,6 +251,42 @@ Cookie IONAME(BeginClose)(
   }
 }
 
+Cookie IONAME(BeginFlush)(
+    ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
+  Terminator terminator{sourceFile, sourceLine};
+  ExternalFileUnit &unit{
+      ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
+  return &unit.BeginIoStatement<ExternalMiscIoStatementState>(
+      unit, ExternalMiscIoStatementState::Flush, sourceFile, sourceLine);
+}
+
+Cookie IONAME(BeginBackspace)(
+    ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
+  Terminator terminator{sourceFile, sourceLine};
+  ExternalFileUnit &unit{
+      ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
+  return &unit.BeginIoStatement<ExternalMiscIoStatementState>(
+      unit, ExternalMiscIoStatementState::Backspace, sourceFile, sourceLine);
+}
+
+Cookie IONAME(BeginEndfile)(
+    ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
+  Terminator terminator{sourceFile, sourceLine};
+  ExternalFileUnit &unit{
+      ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
+  return &unit.BeginIoStatement<ExternalMiscIoStatementState>(
+      unit, ExternalMiscIoStatementState::Endfile, sourceFile, sourceLine);
+}
+
+Cookie IONAME(BeginRewind)(
+    ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
+  Terminator terminator{sourceFile, sourceLine};
+  ExternalFileUnit &unit{
+      ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
+  return &unit.BeginIoStatement<ExternalMiscIoStatementState>(
+      unit, ExternalMiscIoStatementState::Rewind, sourceFile, sourceLine);
+}
+
 // Control list items
 
 void IONAME(EnableHandlers)(Cookie cookie, bool hasIoStat, bool hasErr,
@@ -388,7 +432,7 @@ bool IONAME(SetRec)(Cookie cookie, std::int64_t rec) {
         "REC= may not appear unless ACCESS='DIRECT'");
     return false;
   }
-  if (!connection.recordLength) {
+  if (!connection.isFixedRecordLength || !connection.recordLength) {
     io.GetIoErrorHandler().SignalError("RECL= was not specified");
     return false;
   }
@@ -640,10 +684,11 @@ bool IONAME(SetRecl)(Cookie cookie, std::size_t n) {
   if (n <= 0) {
     io.GetIoErrorHandler().SignalError("RECL= must be greater than zero");
   }
-  if (open->wasExtant() && open->unit().recordLength.has_value() &&
-      *open->unit().recordLength != static_cast<std::int64_t>(n)) {
+  if (open->wasExtant() && open->unit().isFixedRecordLength &&
+      open->unit().recordLength.value_or(n) != static_cast<std::int64_t>(n)) {
     open->SignalError("RECL= may not be changed for an open unit");
   }
+  open->unit().isFixedRecordLength = true;
   open->unit().recordLength = n;
   return true;
 }
@@ -754,7 +799,17 @@ bool IONAME(OutputUnformattedBlock)(
   if (auto *unf{io.get_if<UnformattedIoStatementState<Direction::Output>>()}) {
     return unf->Emit(x, length);
   }
-  io.GetIoErrorHandler().Crash("OutputUnformatted() called for an I/O "
+  io.GetIoErrorHandler().Crash("OutputUnformattedBlock() called for an I/O "
+                               "statement that is not unformatted output");
+  return false;
+}
+
+bool IONAME(InputUnformattedBlock)(Cookie cookie, char *x, std::size_t length) {
+  IoStatementState &io{*cookie};
+  if (auto *unf{io.get_if<UnformattedIoStatementState<Direction::Input>>()}) {
+    return unf->Receive(x, length);
+  }
+  io.GetIoErrorHandler().Crash("InputUnformattedBlock() called for an I/O "
                                "statement that is not unformatted output");
   return false;
 }

diff  --git a/flang/runtime/stop.cpp b/flang/runtime/stop.cpp
index cd91b77cff1c..49592b75a2ad 100644
--- a/flang/runtime/stop.cpp
+++ b/flang/runtime/stop.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "stop.h"
+#include "file.h"
 #include "io-error.h"
 #include "terminator.h"
 #include "unit.h"
@@ -71,6 +72,19 @@ static void CloseAllExternalUnits(const char *why) {
   std::exit(EXIT_FAILURE);
 }
 
+void RTNAME(PauseStatement)() {
+  if (Fortran::runtime::io::IsATerminal(0)) {
+    Fortran::runtime::io::IoErrorHandler handler{"PAUSE statement"};
+    Fortran::runtime::io::ExternalFileUnit::FlushAll(handler);
+    std::fputs("Fortran PAUSE: hit RETURN to continue:", stderr);
+    std::fflush(nullptr);
+    if (std::fgetc(stdin) == EOF) {
+      CloseAllExternalUnits("PAUSE statement");
+      std::exit(EXIT_SUCCESS);
+    }
+  }
+}
+
 [[noreturn]] void RTNAME(FailImageStatement)() {
   Fortran::runtime::NotifyOtherImagesOfFailImageStatement();
   CloseAllExternalUnits("FAIL IMAGE statement");

diff  --git a/flang/runtime/stop.h b/flang/runtime/stop.h
index 249e71e0b1f0..3d5f22e5761a 100644
--- a/flang/runtime/stop.h
+++ b/flang/runtime/stop.h
@@ -20,6 +20,7 @@ NORETURN void RTNAME(StopStatement)(int code DEFAULT_VALUE(EXIT_SUCCESS),
     bool isErrorStop DEFAULT_VALUE(false), bool quiet DEFAULT_VALUE(false));
 NORETURN void RTNAME(StopStatementText)(const char *,
     bool isErrorStop DEFAULT_VALUE(false), bool quiet DEFAULT_VALUE(false));
+void RTNAME(PauseStatement)(NO_ARGUMENTS);
 NORETURN void RTNAME(FailImageStatement)(NO_ARGUMENTS);
 NORETURN void RTNAME(ProgramEndStatement)(NO_ARGUMENTS);
 


        


More information about the flang-commits mailing list