[flang-commits] [flang] bd43fa2 - [flang] Implement anonymous units in the runtime
peter klausler via flang-commits
flang-commits at lists.llvm.org
Tue Jul 14 16:13:01 PDT 2020
Author: peter klausler
Date: 2020-07-14T16:12:06-07:00
New Revision: bd43fa29e3f92161270cbd077b79282cdcbb6aa0
URL: https://github.com/llvm/llvm-project/commit/bd43fa29e3f92161270cbd077b79282cdcbb6aa0
DIFF: https://github.com/llvm/llvm-project/commit/bd43fa29e3f92161270cbd077b79282cdcbb6aa0.diff
LOG: [flang] Implement anonymous units in the runtime
I/O from/to an unopened unit number needs to open &/or create
a "fort.$UNIT" file.
Fixes FCVS test fm401.f.
Reviewed By: tskeith
Differential Revision: https://reviews.llvm.org/D83809
Added:
Modified:
flang/runtime/io-api.cpp
flang/runtime/unit-map.h
flang/runtime/unit.cpp
flang/runtime/unit.h
Removed:
################################################################################
diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index 4710a590ccab..2163b3bca0d8 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -111,8 +111,8 @@ Cookie BeginExternalListIO(
if (unitNumber == DefaultUnit) {
unitNumber = DIR == Direction::Input ? 5 : 6;
}
- ExternalFileUnit &unit{
- ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
+ ExternalFileUnit &unit{ExternalFileUnit::LookUpOrCreateAnonymous(
+ unitNumber, DIR, false /*formatted*/, terminator)};
if (unit.access == Access::Direct) {
terminator.Crash("List-directed I/O attempted on direct access file");
return nullptr;
@@ -150,8 +150,8 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength,
if (unitNumber == DefaultUnit) {
unitNumber = DIR == Direction::Input ? 5 : 6;
}
- ExternalFileUnit &unit{
- ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
+ ExternalFileUnit &unit{ExternalFileUnit::LookUpOrCreateAnonymous(
+ unitNumber, DIR, false /*formatted*/, terminator)};
if (unit.isUnformatted) {
terminator.Crash("Formatted I/O attempted on unformatted file");
return nullptr;
@@ -185,8 +185,8 @@ template <Direction DIR>
Cookie BeginUnformattedIO(
ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
Terminator terminator{sourceFile, sourceLine};
- ExternalFileUnit &unit{
- ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
+ ExternalFileUnit &unit{ExternalFileUnit::LookUpOrCreateAnonymous(
+ unitNumber, DIR, true /*unformatted*/, terminator)};
if (!unit.isUnformatted) {
terminator.Crash("Unformatted output attempted on formatted file");
}
@@ -223,7 +223,7 @@ Cookie IONAME(BeginOpenUnit)( // OPEN(without NEWUNIT=)
bool wasExtant{false};
Terminator terminator{sourceFile, sourceLine};
ExternalFileUnit &unit{
- ExternalFileUnit::LookUpOrCreate(unitNumber, terminator, &wasExtant)};
+ ExternalFileUnit::LookUpOrCreate(unitNumber, terminator, wasExtant)};
return &unit.BeginIoStatement<OpenStatementState>(
unit, wasExtant, sourceFile, sourceLine);
}
@@ -231,10 +231,11 @@ Cookie IONAME(BeginOpenUnit)( // OPEN(without NEWUNIT=)
Cookie IONAME(BeginOpenNewUnit)( // OPEN(NEWUNIT=j)
const char *sourceFile, int sourceLine) {
Terminator terminator{sourceFile, sourceLine};
+ bool ignored{false};
ExternalFileUnit &unit{ExternalFileUnit::LookUpOrCreate(
- ExternalFileUnit::NewUnit(terminator), terminator)};
+ ExternalFileUnit::NewUnit(terminator), terminator, ignored)};
return &unit.BeginIoStatement<OpenStatementState>(
- unit, false /*wasExtant*/, sourceFile, sourceLine);
+ unit, false /*was an existing file*/, sourceFile, sourceLine);
}
Cookie IONAME(BeginClose)(
diff --git a/flang/runtime/unit-map.h b/flang/runtime/unit-map.h
index 9efb2698d223..be244f5ae463 100644
--- a/flang/runtime/unit-map.h
+++ b/flang/runtime/unit-map.h
@@ -27,16 +27,11 @@ class UnitMap {
}
ExternalFileUnit &LookUpOrCreate(
- int n, const Terminator &terminator, bool *wasExtant) {
+ int n, const Terminator &terminator, bool &wasExtant) {
CriticalSection critical{lock_};
auto *p{Find(n)};
- if (wasExtant) {
- *wasExtant = p != nullptr;
- }
- if (p) {
- return *p;
- }
- return Create(n, terminator);
+ wasExtant = p != nullptr;
+ return p ? *p : Create(n, terminator);
}
ExternalFileUnit &NewUnit(const Terminator &terminator) {
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 2193ee0f6aca..cf20d7cd81c6 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -10,6 +10,7 @@
#include "io-error.h"
#include "lock.h"
#include "unit-map.h"
+#include <cstdio>
namespace Fortran::runtime::io {
@@ -46,10 +47,38 @@ ExternalFileUnit &ExternalFileUnit::LookUpOrCrash(
}
ExternalFileUnit &ExternalFileUnit::LookUpOrCreate(
- int unit, const Terminator &terminator, bool *wasExtant) {
+ int unit, const Terminator &terminator, bool &wasExtant) {
return GetUnitMap().LookUpOrCreate(unit, terminator, wasExtant);
}
+ExternalFileUnit &ExternalFileUnit::LookUpOrCreateAnonymous(
+ int unit, Direction dir, bool isUnformatted, const Terminator &terminator) {
+ bool exists{false};
+ ExternalFileUnit &result{
+ GetUnitMap().LookUpOrCreate(unit, terminator, exists)};
+ if (!exists) {
+ // I/O to an unconnected unit reads/creates a local file, e.g. fort.7
+ std::size_t pathMaxLen{32};
+ auto path{SizedNew<char>{terminator}(pathMaxLen)};
+ std::snprintf(path.get(), pathMaxLen, "fort.%d", unit);
+ IoErrorHandler handler{terminator};
+ result.OpenUnit(
+ dir == Direction::Input ? OpenStatus::Old : OpenStatus::Replace,
+ Position::Rewind, std::move(path), std::strlen(path.get()), handler);
+ result.isUnformatted = isUnformatted;
+ }
+ return result;
+}
+
+ExternalFileUnit &ExternalFileUnit::CreateNew(
+ int unit, const Terminator &terminator) {
+ bool wasExtant{false};
+ ExternalFileUnit &result{
+ GetUnitMap().LookUpOrCreate(unit, terminator, wasExtant)};
+ RUNTIME_CHECK(terminator, !wasExtant);
+ return result;
+}
+
ExternalFileUnit *ExternalFileUnit::LookUpForClose(int unit) {
return GetUnitMap().LookUpForClose(unit);
}
@@ -155,14 +184,14 @@ UnitMap &ExternalFileUnit::GetUnitMap() {
Terminator terminator{__FILE__, __LINE__};
IoErrorHandler handler{terminator};
unitMap = New<UnitMap>{terminator}().release();
- ExternalFileUnit &out{ExternalFileUnit::LookUpOrCreate(6, terminator)};
+ ExternalFileUnit &out{ExternalFileUnit::CreateNew(6, terminator)};
out.Predefine(1);
out.set_mayRead(false);
out.set_mayWrite(true);
out.set_mayPosition(false);
out.SetDirection(Direction::Output, handler);
defaultOutput = &out;
- ExternalFileUnit &in{ExternalFileUnit::LookUpOrCreate(5, terminator)};
+ ExternalFileUnit &in{ExternalFileUnit::CreateNew(5, terminator)};
in.Predefine(0);
in.set_mayRead(true);
in.set_mayWrite(false);
diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index c54625413b87..f0edeedef081 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -39,7 +39,10 @@ class ExternalFileUnit : public ConnectionState,
static ExternalFileUnit *LookUp(int unit);
static ExternalFileUnit &LookUpOrCrash(int unit, const Terminator &);
static ExternalFileUnit &LookUpOrCreate(
- int unit, const Terminator &, bool *wasExtant = nullptr);
+ int unit, const Terminator &, bool &wasExtant);
+ static ExternalFileUnit &LookUpOrCreateAnonymous(
+ int unit, Direction, bool isUnformatted, const Terminator &);
+ static ExternalFileUnit &CreateNew(int unit, const Terminator &);
static ExternalFileUnit *LookUpForClose(int unit);
static int NewUnit(const Terminator &);
static void CloseAll(IoErrorHandler &);
More information about the flang-commits
mailing list