[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