Skip to content

Commit

Permalink
[flang][runtime] Support DT edit descriptor in result of READ(SIZE=)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
klausler committed Feb 17, 2023
1 parent 7067aee commit 4180b29
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 6 deletions.
2 changes: 1 addition & 1 deletion flang/runtime/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 10 additions & 0 deletions flang/runtime/descriptor-io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)>()};
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions flang/runtime/internal-unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions flang/runtime/internal-unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(); }
Expand Down
19 changes: 15 additions & 4 deletions flang/runtime/io-stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)};
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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>>()}) {
Expand Down Expand Up @@ -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()};
Expand Down
5 changes: 4 additions & 1 deletion flang/runtime/io-stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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};
Expand Down Expand Up @@ -406,6 +409,7 @@ class ExternalIoStatementBase : public IoStatementBase {
int EndIoStatement();
ExternalFileUnit *GetExternalFileUnit() const { return &unit_; }
void SetAsynchronous();
std::int64_t InquirePos();

private:
ExternalFileUnit &unit_;
Expand Down Expand Up @@ -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 *&);
Expand Down

0 comments on commit 4180b29

Please sign in to comment.