[flang-commits] [PATCH] D89435: [flang][msvc] Avoid a reinterpret_cast

Peter Klausler via Phabricator via flang-commits flang-commits at lists.llvm.org
Wed Oct 14 16:37:08 PDT 2020


klausler created this revision.
klausler added a reviewer: Meinersbur.
klausler added a project: Flang.
Herald added subscribers: llvm-commits, jdoerfert.
Herald added a project: LLVM.
klausler requested review of this revision.

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.

Proposed as an alternative to https://reviews.llvm.org/D88798.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D89435

Files:
  flang/include/flang/Evaluate/integer.h
  flang/lib/Evaluate/real.cpp


Index: flang/lib/Evaluate/real.cpp
===================================================================
--- flang/lib/Evaluate/real.cpp
+++ flang/lib/Evaluate/real.cpp
@@ -496,14 +496,15 @@
     }
   } 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++;
Index: flang/include/flang/Evaluate/integer.h
===================================================================
--- flang/include/flang/Evaluate/integer.h
+++ flang/include/flang/Evaluate/integer.h
@@ -462,21 +462,30 @@
     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 ~)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D89435.298261.patch
Type: text/x-patch
Size: 2542 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/flang-commits/attachments/20201014/5e5d99f9/attachment.bin>


More information about the flang-commits mailing list