Skip to content

Commit

Permalink
[flang][msvc] Avoid a reinterpret_cast
Browse files Browse the repository at this point in the history
The call to the binary->decimal formatter in real.cpp was cheating
by using a reinterpret_cast<> to extract its binary value.
Use a more principled and portable approach by extending the
API of evaluate::Integer<> to include ToUInt<>()/ToSInt<>()
member function templates that do the "right" thing.  Retain
ToUInt64()/ToSInt64() for compatibility.

Differential revision: https://reviews.llvm.org/D89435
  • Loading branch information
klausler committed Oct 15, 2020
1 parent cf6fd40 commit 2aad6a0
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 13 deletions.
29 changes: 19 additions & 10 deletions flang/include/flang/Evaluate/integer.h
Expand Up @@ -462,21 +462,30 @@ class Integer {
return CompareUnsigned(y);
}

constexpr std::uint64_t ToUInt64() const {
std::uint64_t n{LEPart(0)};
int filled{partBits};
for (int j{1}; filled < 64 && j < parts; ++j, filled += partBits) {
n |= std::uint64_t{LEPart(j)} << filled;
template <typename UINT = std::uint64_t> constexpr UINT ToUInt() const {
UINT n{LEPart(0)};
std::size_t filled{partBits};
constexpr std::size_t maxBits{CHAR_BIT * sizeof n};
for (int j{1}; filled < maxBits && j < parts; ++j, filled += partBits) {
n |= UINT{LEPart(j)} << filled;
}
return n;
}

constexpr std::int64_t ToInt64() const {
std::int64_t signExtended = ToUInt64();
if constexpr (bits < 64) {
signExtended |= -(signExtended >> (bits - 1)) << bits;
template <typename SINT = std::int64_t, typename UINT = std::uint64_t>
constexpr SINT ToSInt() const {
SINT n = ToUInt<UINT>();
constexpr std::size_t maxBits{CHAR_BIT * sizeof n};
if constexpr (bits < maxBits) {
n |= -(n >> (bits - 1)) << bits;
}
return signExtended;
return n;
}

constexpr std::uint64_t ToUInt64() const { return ToUInt<std::uint64_t>(); }

constexpr std::int64_t ToInt64() const {
return ToSInt<std::int64_t, std::uint64_t>();
}

// Ones'-complement (i.e., C's ~)
Expand Down
7 changes: 4 additions & 3 deletions flang/lib/Evaluate/real.cpp
Expand Up @@ -496,14 +496,15 @@ llvm::raw_ostream &Real<W, P>::AsFortran(
}
} else {
using B = decimal::BinaryFloatingPointNumber<P>;
const auto *value{reinterpret_cast<const B *>(this)};
char buffer[24000]; // accommodate real*16
B value{word_.template ToUInt<typename B::RawType>()};
char buffer[common::MaxDecimalConversionDigits(P) +
EXTRA_DECIMAL_CONVERSION_SPACE];
decimal::DecimalConversionFlags flags{}; // default: exact representation
if (minimal) {
flags = decimal::Minimize;
}
auto result{decimal::ConvertToDecimal<P>(buffer, sizeof buffer, flags,
static_cast<int>(sizeof buffer), decimal::RoundNearest, *value)};
static_cast<int>(sizeof buffer), decimal::RoundNearest, value)};
const char *p{result.str};
if (DEREF(p) == '-' || *p == '+') {
o << *p++;
Expand Down

0 comments on commit 2aad6a0

Please sign in to comment.