Skip to content

Commit ba3942f

Browse files
vdonaldsonklauslerpsteinfeld
authored
cherry pick several runtime and intrinsic fixes (#1006)
* [flang] Fix regression from recent runtime input fix A recent runtime I/O change[1] was meant to improve the handling of input from external files missing a terminal newline on their last records; the change was "triggered" by the wrong circumstances and causing reads that should have pulled more data into the buffer to be treated as EOFs. So fix that, and also don't retain input data in the buffer once an input record has been finished unless it's known that list-directed or NAMELIST input of a repeated input item may need to backspace a non-positionable external unit to return to the beginning of the repeated item. [1] 6578893 Differential Revision: https://reviews.llvm.org/D108164 * [flang] Add missing call to BeginReadingRecord() NAMELIST input needs to start with a call to BeginReadingRecord(). Internal unit input doesn't care (so unit tests were passing), but external unit input does need the call and will assert without it. Differential Revision: https://reviews.llvm.org/D108051 * [flang] Fix the vector version of EOSHIFT with a BOUNDARY argument When the vector version of EOSHIFT was called, the BOUNDARY argument was being ignored. I fixed that and added a test that would not pass without this fix. Differential Revision: https://reviews.llvm.org/D108249 Co-authored-by: peter klausler <[email protected]> Co-authored-by: Peter Steinfeld <[email protected]>
1 parent fd8dc16 commit ba3942f

File tree

7 files changed

+58
-12
lines changed

7 files changed

+58
-12
lines changed

flang/runtime/connection.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ struct ConnectionState : public ConnectionAttributes {
5757
// or an end-of-file READ condition on a sequential access file
5858
std::optional<std::int64_t> endfileRecordNumber;
5959

60+
// Set when processing repeated items during list-directed & NAMELIST input
61+
// in order to keep a span of records in frame on a non-positionable file,
62+
// so that backspacing to the beginning of the repeated item doesn't require
63+
// repositioning the external storage medium when that's impossible.
64+
std::optional<std::int64_t> resumptionRecordNumber;
65+
6066
// Mutable modes set at OPEN() that can be overridden in READ/WRITE & FORMAT
6167
MutableModes modes; // BLANK=, DECIMAL=, SIGN=, ROUND=, PAD=, DELIM=, kP
6268
};

flang/runtime/io-stmt.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,11 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
653653
comma = ';';
654654
}
655655
if (remaining_ > 0 && !realPart_) { // "r*c" repetition in progress
656-
while (connection.currentRecordNumber > repeatRecordNumber_) {
656+
RUNTIME_CHECK(
657+
io.GetIoErrorHandler(), connection.resumptionRecordNumber.has_value());
658+
while (connection.currentRecordNumber >
659+
connection.resumptionRecordNumber.value_or(
660+
connection.currentRecordNumber)) {
657661
io.BackspaceRecord();
658662
}
659663
connection.HandleAbsolutePosition(repeatPositionInRecord_);
@@ -666,6 +670,9 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
666670
}
667671
}
668672
remaining_ -= edit.repeat;
673+
if (remaining_ <= 0) {
674+
connection.resumptionRecordNumber.reset();
675+
}
669676
return edit;
670677
}
671678
// Skip separators, handle a "r*c" repeat count; see 13.10.2 in Fortran 2018
@@ -726,7 +733,11 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit(
726733
}
727734
edit.repeat = std::min<int>(r, maxRepeat);
728735
remaining_ = r - edit.repeat;
729-
repeatRecordNumber_ = connection.currentRecordNumber;
736+
if (remaining_ > 0) {
737+
connection.resumptionRecordNumber = connection.currentRecordNumber;
738+
} else {
739+
connection.resumptionRecordNumber.reset();
740+
}
730741
repeatPositionInRecord_ = connection.positionInRecord;
731742
} else { // not a repetition count, just an integer value; rewind
732743
connection.positionInRecord = start;

flang/runtime/io-stmt.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@ class ListDirectedStatementState<Direction::Input>
229229

230230
private:
231231
int remaining_{0}; // for "r*" repetition
232-
std::int64_t repeatRecordNumber_;
233232
std::int64_t repeatPositionInRecord_;
234233
bool eatComma_{false}; // consume comma after previously read item
235234
bool hitSlash_{false}; // once '/' is seen, nullify further items

flang/runtime/namelist.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ bool IONAME(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
263263
auto *listInput{io.get_if<ListDirectedStatementState<Direction::Input>>()};
264264
RUNTIME_CHECK(handler, listInput != nullptr);
265265
// Check the group header
266+
io.BeginReadingRecord();
266267
std::optional<char32_t> next{io.GetNextNonBlank()};
267268
if (!next || *next != '&') {
268269
handler.SignalError(

flang/runtime/transformational.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,8 @@ void RTNAME(EoshiftVector)(Descriptor &result, const Descriptor &source,
284284
SubscriptValue sourceAt{lb + j - 1 + shift};
285285
if (sourceAt >= lb && sourceAt < lb + extent) {
286286
CopyElement(result, &j, source, &sourceAt, terminator);
287+
} else if (boundary) {
288+
CopyElement(result, &j, *boundary, 0, terminator);
287289
}
288290
}
289291
}

flang/runtime/unit.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -350,13 +350,10 @@ bool ExternalFileUnit::SetSequentialVariableFormattedRecordLength() {
350350
if (*recordLength > 0 && record[*recordLength - 1] == '\r') {
351351
--*recordLength;
352352
}
353-
} else {
354-
recordLength = bytes; // final record w/o \n
353+
return true;
355354
}
356-
return true;
357-
} else {
358-
return false;
359355
}
356+
return false;
360357
}
361358

362359
void ExternalFileUnit::SetLeftTabLimit() {
@@ -421,7 +418,10 @@ void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
421418
Frame()[recordOffsetInFrame_ + *recordLength] == '\n') {
422419
++recordOffsetInFrame_;
423420
}
424-
recordOffsetInFrame_ += *recordLength;
421+
if (!resumptionRecordNumber || mayPosition()) {
422+
frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
423+
recordOffsetInFrame_ = 0;
424+
}
425425
recordLength.reset();
426426
}
427427
}
@@ -612,10 +612,17 @@ void ExternalFileUnit::BeginSequentialVariableFormattedInputRecord(
612612
}
613613
std::size_t length{0};
614614
do {
615-
std::size_t need{recordOffsetInFrame_ + length + 1};
616-
length = ReadFrame(frameOffsetInFile_, need, handler);
615+
std::size_t need{length + 1};
616+
length =
617+
ReadFrame(frameOffsetInFile_, recordOffsetInFrame_ + need, handler) -
618+
recordOffsetInFrame_;
617619
if (length < need) {
618-
handler.SignalEnd();
620+
if (length > 0) {
621+
// final record w/o \n
622+
recordLength = length;
623+
} else {
624+
handler.SignalEnd();
625+
}
619626
break;
620627
}
621628
} while (!SetSequentialVariableFormattedRecordLength());

flang/unittests/RuntimeGTest/Transformational.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,26 @@ TEST(Transformational, Shifts) {
110110
*result.ZeroBasedIndexedElement<std::int32_t>(j), eoshiftExpect1[j]);
111111
}
112112
result.Destroy();
113+
114+
// VECTOR EOSHIFT
115+
StaticDescriptor<0> boundaryDescriptor;
116+
Descriptor vectorBoundary{boundaryDescriptor.descriptor()};
117+
std::int32_t boundaryValue{343};
118+
vectorBoundary.Establish(TypeCategory::Integer, 4,
119+
const_cast<void *>(reinterpret_cast<const void *>(&boundaryValue)), 0);
120+
RTNAME(EoshiftVector)
121+
(vectorResult, *vector, 2, &vectorBoundary, __FILE__, __LINE__);
122+
EXPECT_EQ(vectorResult.type(), array->type());
123+
EXPECT_EQ(vectorResult.rank(), 1);
124+
EXPECT_EQ(vectorResult.GetDimension(0).LowerBound(), 1);
125+
EXPECT_EQ(vectorResult.GetDimension(0).Extent(), 6);
126+
EXPECT_EQ(vectorResult.type(), (TypeCode{TypeCategory::Integer, 4}));
127+
static std::int32_t eoshiftVectorExpect[6]{3, 4, 5, 6, 343, 343};
128+
for (int j{0}; j < 6; ++j) {
129+
EXPECT_EQ(*vectorResult.ZeroBasedIndexedElement<std::int32_t>(j),
130+
eoshiftVectorExpect[j]);
131+
}
132+
vectorResult.Destroy();
113133
}
114134

115135
TEST(Transformational, Pack) {

0 commit comments

Comments
 (0)