diff --git a/flang-rt/include/flang-rt/runtime/connection.h b/flang-rt/include/flang-rt/runtime/connection.h index 03d9658e7067b..601669942cdd6 100644 --- a/flang-rt/include/flang-rt/runtime/connection.h +++ b/flang-rt/include/flang-rt/runtime/connection.h @@ -45,19 +45,36 @@ struct ConnectionAttributes { }; struct ConnectionState : public ConnectionAttributes { - RT_API_ATTRS bool - IsAtEOF() const; // true when read has hit EOF or endfile record - RT_API_ATTRS bool - IsAfterEndfile() const; // true after ENDFILE until repositioned + RT_API_ATTRS bool IsAtEOF() const { + // true when read has hit EOF or endfile record + return endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber; + } + RT_API_ATTRS bool IsAfterEndfile() const { + // true after ENDFILE until repositioned + return endfileRecordNumber && currentRecordNumber > *endfileRecordNumber; + } // All positions and measurements are always in units of bytes, // not characters. Multi-byte character encodings are possible in // both internal I/O (when the character kind of the variable is 2 or 4) // and external formatted I/O (when the encoding is UTF-8). - RT_API_ATTRS std::size_t RemainingSpaceInRecord() const; - RT_API_ATTRS bool NeedAdvance(std::size_t) const; - RT_API_ATTRS void HandleAbsolutePosition(std::int64_t); - RT_API_ATTRS void HandleRelativePosition(std::int64_t); + RT_API_ATTRS std::size_t RemainingSpaceInRecord() const { + auto recl{recordLength.value_or(openRecl.value_or( + executionEnvironment.listDirectedOutputLineLengthLimit))}; + return positionInRecord >= recl ? 0 : recl - positionInRecord; + } + RT_API_ATTRS bool NeedAdvance(std::size_t width) const { + return positionInRecord > 0 && width > RemainingSpaceInRecord(); + } + RT_API_ATTRS void HandleAbsolutePosition(std::int64_t n) { + positionInRecord = (n < 0 ? 0 : n) + leftTabLimit.value_or(0); + } + RT_API_ATTRS void HandleRelativePosition(std::int64_t n) { + auto least{leftTabLimit.value_or(0)}; + auto newPos{positionInRecord + n}; + positionInRecord = newPos < least ? least : newPos; + ; + } RT_API_ATTRS void BeginRecord() { positionInRecord = 0; diff --git a/flang-rt/include/flang-rt/runtime/io-stmt.h b/flang-rt/include/flang-rt/runtime/io-stmt.h index 33cc91271ab12..c9c193335c940 100644 --- a/flang-rt/include/flang-rt/runtime/io-stmt.h +++ b/flang-rt/include/flang-rt/runtime/io-stmt.h @@ -130,20 +130,94 @@ class IoStatementState { } // Vacant after the end of the current record - RT_API_ATTRS Fortran::common::optional GetCurrentChar( + RT_API_ATTRS Fortran::common::optional GetCurrentCharSlow( std::size_t &byteCount); + // For faster formatted input editing, this structure can be built by + // GetUpcomingFastAsciiField() and used to save significant time in + // GetCurrentChar, NextInField() and other input utilities when the input + // is buffered, does not require UTF-8 conversion, and comprises only + // single byte characters. + class FastAsciiField { + public: + RT_API_ATTRS FastAsciiField(ConnectionState &connection) + : connection_{connection} {} + RT_API_ATTRS FastAsciiField( + ConnectionState &connection, const char *start, std::size_t bytes) + : connection_{connection}, at_{start}, limit_{start + bytes} { + CheckForAsterisk(); + } + RT_API_ATTRS ConnectionState &connection() { return connection_; } + RT_API_ATTRS std::size_t got() const { return got_; } + + RT_API_ATTRS bool MustUseSlowPath() const { return at_ == nullptr; } + + RT_API_ATTRS Fortran::common::optional Next() const { + if (at_ && at_ < limit_) { + return *at_; + } else { + return std::nullopt; + } + } + RT_API_ATTRS void NextRecord(IoStatementState &io) { + if (at_) { + if (std::size_t bytes{io.GetNextInputBytes(at_)}) { + limit_ = at_ + bytes; + CheckForAsterisk(); + } else { + at_ = limit_ = nullptr; + } + } + } + RT_API_ATTRS void Advance(int gotten, std::size_t bytes) { + if (at_ && at_ < limit_) { + ++at_; + got_ += gotten; + } + connection_.HandleRelativePosition(bytes); + } + RT_API_ATTRS bool MightHaveAsterisk() const { return !at_ || hasAsterisk_; } + + private: + RT_API_ATTRS void CheckForAsterisk() { + hasAsterisk_ = + at_ && at_ < limit_ && std::memchr(at_, '*', limit_ - at_) != nullptr; + } + + ConnectionState &connection_; + const char *at_{nullptr}; + const char *limit_{nullptr}; + std::size_t got_{0}; // for READ(..., SIZE=) + bool hasAsterisk_{false}; + }; + + RT_API_ATTRS FastAsciiField GetUpcomingFastAsciiField(); + + RT_API_ATTRS Fortran::common::optional GetCurrentChar( + std::size_t &byteCount, FastAsciiField *field = nullptr) { + if (field) { + if (auto ch{field->Next()}) { + byteCount = ch ? 1 : 0; + return ch; + } else if (!field->MustUseSlowPath()) { + return std::nullopt; + } + } + return GetCurrentCharSlow(byteCount); + } + // The result of CueUpInput() and the "remaining" arguments to SkipSpaces() // and NextInField() are always in units of bytes, not characters; the // distinction matters for internal input from CHARACTER(KIND=2 and 4). // For fixed-width fields, return the number of remaining bytes. // Skip over leading blanks. - RT_API_ATTRS Fortran::common::optional CueUpInput(const DataEdit &edit) { + RT_API_ATTRS Fortran::common::optional CueUpInput( + const DataEdit &edit, FastAsciiField *fastField = nullptr) { Fortran::common::optional remaining; if (edit.IsListDirected()) { std::size_t byteCount{0}; - GetNextNonBlank(byteCount); + GetNextNonBlank(byteCount, fastField); } else { if (edit.width.value_or(0) > 0) { remaining = *edit.width; @@ -152,16 +226,17 @@ class IoStatementState { *remaining *= bytesPerChar; } } - SkipSpaces(remaining); + SkipSpaces(remaining, fastField); } return remaining; } RT_API_ATTRS Fortran::common::optional SkipSpaces( - Fortran::common::optional &remaining) { + Fortran::common::optional &remaining, + FastAsciiField *fastField = nullptr) { while (!remaining || *remaining > 0) { std::size_t byteCount{0}; - if (auto ch{GetCurrentChar(byteCount)}) { + if (auto ch{GetCurrentChar(byteCount, fastField)}) { if (*ch != ' ' && *ch != '\t') { return ch; } @@ -172,7 +247,11 @@ class IoStatementState { GotChar(byteCount); *remaining -= byteCount; } - HandleRelativePosition(byteCount); + if (fastField) { + fastField->Advance(0, byteCount); + } else { + HandleRelativePosition(byteCount); + } } else { break; } @@ -183,25 +262,35 @@ class IoStatementState { // Acquires the next input character, respecting any applicable field width // or separator character. RT_API_ATTRS Fortran::common::optional NextInField( - Fortran::common::optional &remaining, const DataEdit &); + Fortran::common::optional &remaining, const DataEdit &, + FastAsciiField *field = nullptr); // Detect and signal any end-of-record condition after input. // Returns true if at EOR and remaining input should be padded with blanks. - RT_API_ATTRS bool CheckForEndOfRecord(std::size_t afterReading); + RT_API_ATTRS bool CheckForEndOfRecord( + std::size_t afterReading, const ConnectionState &); // Skips spaces, advances records, and ignores NAMELIST comments RT_API_ATTRS Fortran::common::optional GetNextNonBlank( - std::size_t &byteCount) { - auto ch{GetCurrentChar(byteCount)}; + std::size_t &byteCount, FastAsciiField *fastField = nullptr) { + auto ch{GetCurrentChar(byteCount, fastField)}; bool inNamelist{mutableModes().inNamelist}; while (!ch || *ch == ' ' || *ch == '\t' || *ch == '\n' || (inNamelist && *ch == '!')) { if (ch && (*ch == ' ' || *ch == '\t' || *ch == '\n')) { - HandleRelativePosition(byteCount); - } else if (!AdvanceRecord()) { + if (fastField) { + fastField->Advance(0, byteCount); + } else { + HandleRelativePosition(byteCount); + } + } else if (AdvanceRecord()) { + if (fastField) { + fastField->NextRecord(*this); + } + } else { return Fortran::common::nullopt; } - ch = GetCurrentChar(byteCount); + ch = GetCurrentChar(byteCount, fastField); } return ch; } diff --git a/flang-rt/lib/runtime/connection.cpp b/flang-rt/lib/runtime/connection.cpp index 2f01dbbb95920..2e02717f5425b 100644 --- a/flang-rt/lib/runtime/connection.cpp +++ b/flang-rt/lib/runtime/connection.cpp @@ -9,37 +9,10 @@ #include "flang-rt/runtime/connection.h" #include "flang-rt/runtime/environment.h" #include "flang-rt/runtime/io-stmt.h" -#include namespace Fortran::runtime::io { RT_OFFLOAD_API_GROUP_BEGIN -RT_API_ATTRS std::size_t ConnectionState::RemainingSpaceInRecord() const { - auto recl{recordLength.value_or(openRecl.value_or( - executionEnvironment.listDirectedOutputLineLengthLimit))}; - return positionInRecord >= recl ? 0 : recl - positionInRecord; -} - -RT_API_ATTRS bool ConnectionState::NeedAdvance(std::size_t width) const { - return positionInRecord > 0 && width > RemainingSpaceInRecord(); -} - -RT_API_ATTRS bool ConnectionState::IsAtEOF() const { - return endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber; -} - -RT_API_ATTRS bool ConnectionState::IsAfterEndfile() const { - return endfileRecordNumber && currentRecordNumber > *endfileRecordNumber; -} - -RT_API_ATTRS void ConnectionState::HandleAbsolutePosition(std::int64_t n) { - positionInRecord = std::max(n, std::int64_t{0}) + leftTabLimit.value_or(0); -} - -RT_API_ATTRS void ConnectionState::HandleRelativePosition(std::int64_t n) { - positionInRecord = std::max(leftTabLimit.value_or(0), positionInRecord + n); -} - SavedPosition::SavedPosition(IoStatementState &io) : io_{io} { ConnectionState &conn{io_.GetConnectionState()}; saved_ = conn; diff --git a/flang-rt/lib/runtime/edit-input.cpp b/flang-rt/lib/runtime/edit-input.cpp index 99a266648f95c..0a7b09f836c7d 100644 --- a/flang-rt/lib/runtime/edit-input.cpp +++ b/flang-rt/lib/runtime/edit-input.cpp @@ -169,17 +169,18 @@ static inline RT_API_ATTRS char32_t GetRadixPointChar(const DataEdit &edit) { // Prepares input from a field, and returns the sign, if any, else '\0'. static RT_API_ATTRS char ScanNumericPrefix(IoStatementState &io, const DataEdit &edit, Fortran::common::optional &next, - Fortran::common::optional &remaining) { - remaining = io.CueUpInput(edit); - next = io.NextInField(remaining, edit); + Fortran::common::optional &remaining, + IoStatementState::FastAsciiField *fastField = nullptr) { + remaining = io.CueUpInput(edit, fastField); + next = io.NextInField(remaining, edit, fastField); char sign{'\0'}; if (next) { if (*next == '-' || *next == '+') { sign = *next; if (!edit.IsListDirected()) { - io.SkipSpaces(remaining); + io.SkipSpaces(remaining, fastField); } - next = io.NextInField(remaining, edit); + next = io.NextInField(remaining, edit, fastField); } } return sign; @@ -213,17 +214,18 @@ RT_API_ATTRS bool EditIntegerInput(IoStatementState &io, const DataEdit &edit, } Fortran::common::optional remaining; Fortran::common::optional next; - char sign{ScanNumericPrefix(io, edit, next, remaining)}; + auto fastField{io.GetUpcomingFastAsciiField()}; + char sign{ScanNumericPrefix(io, edit, next, remaining, &fastField)}; if (sign == '-' && !isSigned) { io.GetIoErrorHandler().SignalError("Negative sign in UNSIGNED input field"); return false; } - common::UnsignedInt128 value{0}; + common::uint128_t value{0}; bool any{!!sign}; bool overflow{false}; const char32_t comma{GetSeparatorChar(edit)}; - static constexpr auto maxu128{~common::UnsignedInt128{0}}; - for (; next; next = io.NextInField(remaining, edit)) { + static constexpr auto maxu128{~common::uint128_t{0}}; + for (; next; next = io.NextInField(remaining, edit, &fastField)) { char32_t ch{*next}; if (ch == ' ' || ch == '\t') { if (edit.modes.editingFlags & blankZero) { @@ -243,7 +245,7 @@ RT_API_ATTRS bool EditIntegerInput(IoStatementState &io, const DataEdit &edit, // input, like a few other Fortran compilers do. // TODO: also process exponents? Some compilers do, but they obviously // can't just be ignored. - while ((next = io.NextInField(remaining, edit))) { + while ((next = io.NextInField(remaining, edit, &fastField))) { if (*next < '0' || *next > '9') { break; } @@ -271,7 +273,7 @@ RT_API_ATTRS bool EditIntegerInput(IoStatementState &io, const DataEdit &edit, return false; } if (isSigned) { - auto maxForKind{common::UnsignedInt128{1} << ((8 * kind) - 1)}; + auto maxForKind{common::uint128_t{1} << ((8 * kind) - 1)}; overflow |= value >= maxForKind && (value > maxForKind || sign != '-'); } else { auto maxForKind{maxu128 >> (((16 - kind) * 8) + (isSigned ? 1 : 0))}; @@ -287,7 +289,16 @@ RT_API_ATTRS bool EditIntegerInput(IoStatementState &io, const DataEdit &edit, } if (any || !io.GetIoErrorHandler().InError()) { // The value is stored in the lower order bits on big endian platform. - // When memcpy, shift the value to the higher order bit. + // For memcpy, shift the value to the highest order bits. +#if USING_NATIVE_INT128_T + auto shft{static_cast(sizeof value - kind)}; + if (!isHostLittleEndian && shft >= 0) { + auto l{value << shft}; + std::memcpy(n, &l, kind); + } else { + std::memcpy(n, &value, kind); // a blank field means zero + } +#else auto shft{static_cast(sizeof(value.low())) - kind}; // For kind==8 (i.e. shft==0), the value is stored in low_ in big endian. if (!isHostLittleEndian && shft >= 0) { @@ -296,6 +307,8 @@ RT_API_ATTRS bool EditIntegerInput(IoStatementState &io, const DataEdit &edit, } else { std::memcpy(n, &value, kind); // a blank field means zero } +#endif + io.GotChar(fastField.got()); return true; } else { return false; @@ -1070,7 +1083,7 @@ RT_API_ATTRS bool EditCharacterInput(IoStatementState &io, const DataEdit &edit, readyBytes = io.GetNextInputBytes(input); if (readyBytes == 0 || (readyBytes < remainingChars && edit.modes.nonAdvancing)) { - if (io.CheckForEndOfRecord(readyBytes)) { + if (io.CheckForEndOfRecord(readyBytes, connection)) { if (readyBytes == 0) { // PAD='YES' and no more data Fortran::runtime::fill_n(x, lengthChars, ' '); diff --git a/flang-rt/lib/runtime/io-api.cpp b/flang-rt/lib/runtime/io-api.cpp index 2b7ec9134689b..6af0121437cd5 100644 --- a/flang-rt/lib/runtime/io-api.cpp +++ b/flang-rt/lib/runtime/io-api.cpp @@ -1057,14 +1057,15 @@ bool IODEF(InputDescriptor)(Cookie cookie, const Descriptor &descriptor) { } bool IODEF(InputInteger)(Cookie cookie, std::int64_t &n, int kind) { - if (!cookie->CheckFormattedStmtType("InputInteger")) { - return false; + IoStatementState &io{*cookie}; + if (io.BeginReadingRecord()) { + if (auto edit{io.GetNextDataEdit()}) { + return edit->descriptor == DataEdit::ListDirectedNullValue || + EditIntegerInput(io, *edit, reinterpret_cast(&n), kind, + /*isSigned=*/true); + } } - StaticDescriptor<0> staticDescriptor; - Descriptor &descriptor{staticDescriptor.descriptor()}; - descriptor.Establish( - TypeCategory::Integer, kind, reinterpret_cast(&n), 0); - return descr::DescriptorIO(*cookie, descriptor); + return false; } bool IODEF(InputReal32)(Cookie cookie, float &x) { diff --git a/flang-rt/lib/runtime/io-stmt.cpp b/flang-rt/lib/runtime/io-stmt.cpp index 19b13c128b196..8056c8db8525b 100644 --- a/flang-rt/lib/runtime/io-stmt.cpp +++ b/flang-rt/lib/runtime/io-stmt.cpp @@ -596,7 +596,7 @@ ExternalFileUnit *IoStatementState::GetExternalFileUnit() const { [](auto &x) { return x.get().GetExternalFileUnit(); }, u_); } -Fortran::common::optional IoStatementState::GetCurrentChar( +Fortran::common::optional IoStatementState::GetCurrentCharSlow( std::size_t &byteCount) { const char *p{nullptr}; std::size_t bytes{GetNextInputBytes(p)}; @@ -628,12 +628,24 @@ Fortran::common::optional IoStatementState::GetCurrentChar( } } +IoStatementState::FastAsciiField IoStatementState::GetUpcomingFastAsciiField() { + ConnectionState &connection{GetConnectionState()}; + if (!connection.isUTF8 && connection.internalIoCharKind <= 1) { + const char *p{nullptr}; + if (std::size_t bytes{GetNextInputBytes(p)}) { + return FastAsciiField(connection, p, bytes); + } + } + return FastAsciiField(connection); +} + Fortran::common::optional IoStatementState::NextInField( - Fortran::common::optional &remaining, const DataEdit &edit) { + Fortran::common::optional &remaining, const DataEdit &edit, + FastAsciiField *field) { std::size_t byteCount{0}; if (!remaining) { // Stream, list-directed, NAMELIST, &c. - if (auto next{GetCurrentChar(byteCount)}) { - if (edit.width.value_or(0) == 0) { + if (auto next{GetCurrentChar(byteCount, field)}) { + if ((*next < '0' || *next == ';') && edit.width.value_or(0) == 0) { // list-directed, NAMELIST, I0 &c., or width-free I/G: // check for separator character switch (*next) { @@ -667,21 +679,30 @@ Fortran::common::optional IoStatementState::NextInField( break; } } - HandleRelativePosition(byteCount); - GotChar(byteCount); + if (field) { + field->Advance(1, byteCount); + } else { + HandleRelativePosition(byteCount); + GotChar(byteCount); + } return next; } } else if (*remaining > 0) { - if (auto next{GetCurrentChar(byteCount)}) { + if (auto next{GetCurrentChar(byteCount, field)}) { if (byteCount > static_cast(*remaining)) { return Fortran::common::nullopt; } *remaining -= byteCount; - HandleRelativePosition(byteCount); - GotChar(byteCount); + if (field) { + field->Advance(1, byteCount); + } else { + HandleRelativePosition(byteCount); + GotChar(byteCount); + } return next; } - if (CheckForEndOfRecord(0)) { // do padding + if (CheckForEndOfRecord(0, + field ? field->connection() : GetConnectionState())) { // do padding --*remaining; return Fortran::common::optional{' '}; } @@ -689,8 +710,8 @@ Fortran::common::optional IoStatementState::NextInField( return Fortran::common::nullopt; } -bool IoStatementState::CheckForEndOfRecord(std::size_t afterReading) { - const ConnectionState &connection{GetConnectionState()}; +bool IoStatementState::CheckForEndOfRecord( + std::size_t afterReading, const ConnectionState &connection) { if (!connection.IsAtEOF()) { if (auto length{connection.EffectiveRecordLength()}) { if (connection.positionInRecord + @@ -799,7 +820,6 @@ Fortran::common::optional ListDirectedStatementState::GetNextDataEdit( IoStatementState &io, int maxRepeat) { // N.B. list-directed transfers cannot be nonadvancing (C1221) - ConnectionState &connection{io.GetConnectionState()}; DataEdit edit; edit.descriptor = DataEdit::ListDirected; edit.repeat = 1; // may be overridden below @@ -840,14 +860,15 @@ ListDirectedStatementState::GetNextDataEdit( imaginaryPart_ = true; edit.descriptor = DataEdit::ListDirectedImaginaryPart; } - auto ch{io.GetNextNonBlank(byteCount)}; + auto fastField{io.GetUpcomingFastAsciiField()}; + auto ch{io.GetNextNonBlank(byteCount, &fastField)}; if (ch && *ch == comma && eatComma_) { // Consume comma & whitespace after previous item. // This includes the comma between real and imaginary components // in list-directed/NAMELIST complex input. // (When DECIMAL='COMMA', the comma is actually a semicolon.) - io.HandleRelativePosition(byteCount); - ch = io.GetNextNonBlank(byteCount); + fastField.Advance(0, byteCount); + ch = io.GetNextNonBlank(byteCount, &fastField); } eatComma_ = true; if (!ch) { @@ -865,8 +886,9 @@ ListDirectedStatementState::GetNextDataEdit( if (imaginaryPart_) { // can't repeat components return edit; } - if (*ch >= '0' && *ch <= '9') { // look for "r*" repetition count - auto start{connection.positionInRecord}; + if (*ch >= '0' && *ch <= '9' && fastField.MightHaveAsterisk()) { + // look for "r*" repetition count + auto start{fastField.connection().positionInRecord}; int r{0}; do { static auto constexpr clamp{(std::numeric_limits::max() - '9') / 10}; @@ -875,12 +897,12 @@ ListDirectedStatementState::GetNextDataEdit( break; } r = 10 * r + (*ch - '0'); - io.HandleRelativePosition(byteCount); - ch = io.GetCurrentChar(byteCount); + fastField.Advance(0, byteCount); + ch = io.GetCurrentChar(byteCount, &fastField); } while (ch && *ch >= '0' && *ch <= '9'); if (r > 0 && ch && *ch == '*') { // subtle: r must be nonzero - io.HandleRelativePosition(byteCount); - ch = io.GetCurrentChar(byteCount); + fastField.Advance(0, byteCount); + ch = io.GetCurrentChar(byteCount, &fastField); if (ch && *ch == '/') { // r*/ hitSlash_ = true; edit.descriptor = DataEdit::ListDirectedNullValue; @@ -895,12 +917,12 @@ ListDirectedStatementState::GetNextDataEdit( repeatPosition_.emplace(io); } } else { // not a repetition count, just an integer value; rewind - connection.positionInRecord = start; + fastField.connection().positionInRecord = start; } } if (!imaginaryPart_ && ch && *ch == '(') { realPart_ = true; - io.HandleRelativePosition(byteCount); + fastField.connection().HandleRelativePosition(byteCount); edit.descriptor = DataEdit::ListDirectedRealPart; } return edit; diff --git a/flang-rt/lib/runtime/unit.cpp b/flang-rt/lib/runtime/unit.cpp index 199287d7237fd..5f52fa2781db5 100644 --- a/flang-rt/lib/runtime/unit.cpp +++ b/flang-rt/lib/runtime/unit.cpp @@ -135,6 +135,13 @@ bool ExternalFileUnit::Receive(char *data, std::size_t bytes, std::size_t ExternalFileUnit::GetNextInputBytes( const char *&p, IoErrorHandler &handler) { RUNTIME_CHECK(handler, direction_ == Direction::Input); + if (access == Access::Sequential && + positionInRecord < recordLength.value_or(positionInRecord)) { + // Fast path for variable-length formatted input: the whole record + // must be in frame as a result of newline detection for record length. + p = Frame() + recordOffsetInFrame_ + positionInRecord; + return *recordLength - positionInRecord; + } std::size_t length{1}; if (auto recl{EffectiveRecordLength()}) { if (positionInRecord < *recl) { @@ -443,7 +450,6 @@ void ExternalFileUnit::Rewind(IoErrorHandler &handler) { DoImpliedEndfile(handler); SetPosition(0); currentRecordNumber = 1; - leftTabLimit.reset(); anyWriteSinceLastPositioning_ = false; } } @@ -455,6 +461,8 @@ void ExternalFileUnit::SetPosition(std::int64_t pos) { directAccessRecWasSet_ = true; } BeginRecord(); + beganReadingRecord_ = false; // for positioning after nonadvancing input + leftTabLimit.reset(); } void ExternalFileUnit::Sought(std::int64_t zeroBasedPos) { diff --git a/flang/include/flang/Common/uint128.h b/flang/include/flang/Common/uint128.h index faecb88737a0b..c4bc4689a1eaa 100644 --- a/flang/include/flang/Common/uint128.h +++ b/flang/include/flang/Common/uint128.h @@ -278,9 +278,11 @@ using SignedInt128 = Int128; #if !AVOID_NATIVE_UINT128_T && (defined __GNUC__ || defined __clang__) && \ defined __SIZEOF_INT128__ +#define USING_NATIVE_INT128_T 1 using uint128_t = __uint128_t; using int128_t = __int128_t; #else +#undef USING_NATIVE_INT128_T using uint128_t = UnsignedInt128; using int128_t = SignedInt128; #endif