[flang-commits] [flang] [Flang] Shift the data from lower to higher order bits in the big endian environment (PR #73670)

via flang-commits flang-commits at lists.llvm.org
Thu Dec 14 09:13:06 PST 2023


https://github.com/madanial0 updated https://github.com/llvm/llvm-project/pull/73670

>From 7cffd6fa49ce7a0e7c9ef0af6ad1e8d42598e099 Mon Sep 17 00:00:00 2001
From: Mark Danial <madanial at dixon.rtp.raleigh.ibm.com>
Date: Mon, 27 Nov 2023 21:11:52 -0500
Subject: [PATCH 1/2] [Flang] Shift the data from lower to higher order bits in
 the big endian environment

---
 flang/runtime/edit-input.cpp | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp
index 822099b5141b1b..71b2d3a4818427 100644
--- a/flang/runtime/edit-input.cpp
+++ b/flang/runtime/edit-input.cpp
@@ -244,7 +244,15 @@ bool EditIntegerInput(
     value = -value;
   }
   if (any || !io.GetConnectionState().IsAtEOF()) {
-    std::memcpy(n, &value, kind); // a blank field means zero
+    // For integer kind <= 4, the value is stored in the lower order bits on
+    // the big endian platform. When memcpy the value, shift the value, shift
+    // the value to the higher order bit.
+    if (!isHostLittleEndian && kind <= 4) {
+      auto l{value.low() << (8 * (sizeof(value.low()) - kind))};
+      std::memcpy(n, &l, kind);
+    } else {
+      std::memcpy(n, &value, kind); // a blank field means zero
+    }
   }
   return any;
 }

>From 19367432e424f117c7c8a3267419307ea6e130aa Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Tue, 12 Dec 2023 15:56:33 -0500
Subject: [PATCH 2/2] swap two halves in Int128 in big endian

---
 flang/include/flang/Common/uint128.h | 30 ++++++++++++++++++++--------
 flang/runtime/edit-input.cpp         | 10 +++++-----
 2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/flang/include/flang/Common/uint128.h b/flang/include/flang/Common/uint128.h
index bfd2eef01f6f08..c66dc4f303a734 100644
--- a/flang/include/flang/Common/uint128.h
+++ b/flang/include/flang/Common/uint128.h
@@ -23,6 +23,16 @@
 #include <cstdint>
 #include <type_traits>
 
+#if FLANG_LITTLE_ENDIAN
+#define SWAP(a, i, b, j) \
+  a{i}, b { j }
+#elif FLANG_BIG_ENDIAN
+#define SWAP(a, i, b, j) \
+  b{j}, a { i }
+#else
+#error host endianness is not known
+#endif
+
 namespace Fortran::common {
 
 template <bool IS_SIGNED = false> class Int128 {
@@ -34,14 +44,14 @@ template <bool IS_SIGNED = false> class Int128 {
   constexpr Int128(unsigned long n) : low_{n} {}
   constexpr Int128(unsigned long long n) : low_{n} {}
   constexpr Int128(int n)
-      : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
-                                                 n < 0)} {}
+      : SWAP(low_, static_cast<std::uint64_t>(n), high_,
+            -static_cast<std::uint64_t>(n < 0)) {}
   constexpr Int128(long n)
-      : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
-                                                 n < 0)} {}
+      : SWAP(low_, static_cast<std::uint64_t>(n), high_,
+            -static_cast<std::uint64_t>(n < 0)) {}
   constexpr Int128(long long n)
-      : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
-                                                 n < 0)} {}
+      : SWAP(low_, static_cast<std::uint64_t>(n), high_,
+            -static_cast<std::uint64_t>(n < 0)) {}
   constexpr Int128(const Int128 &) = default;
   constexpr Int128(Int128 &&) = default;
   constexpr Int128 &operator=(const Int128 &) = default;
@@ -246,7 +256,8 @@ template <bool IS_SIGNED = false> class Int128 {
   }
 
 private:
-  constexpr Int128(std::uint64_t hi, std::uint64_t lo) : low_{lo}, high_{hi} {}
+  constexpr Int128(std::uint64_t hi, std::uint64_t lo)
+      : SWAP(low_, lo, high_, hi) {}
   constexpr int LeadingZeroes() const {
     if (high_ == 0) {
       return 64 + LeadingZeroBitCount(low_);
@@ -255,7 +266,7 @@ template <bool IS_SIGNED = false> class Int128 {
     }
   }
   static constexpr std::uint64_t topBit{std::uint64_t{1} << 63};
-  std::uint64_t low_{0}, high_{0};
+  std::uint64_t SWAP(low_, 0, high_, 0);
 };
 
 using UnsignedInt128 = Int128<false>;
@@ -288,4 +299,7 @@ template <int BITS>
 using HostSignedIntType = typename HostSignedIntTypeHelper<BITS>::type;
 
 } // namespace Fortran::common
+
+#undef SWAP
+
 #endif
diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp
index 71b2d3a4818427..1267e5281c5ab4 100644
--- a/flang/runtime/edit-input.cpp
+++ b/flang/runtime/edit-input.cpp
@@ -244,11 +244,11 @@ bool EditIntegerInput(
     value = -value;
   }
   if (any || !io.GetConnectionState().IsAtEOF()) {
-    // For integer kind <= 4, the value is stored in the lower order bits on
-    // the big endian platform. When memcpy the value, shift the value, shift
-    // the value to the higher order bit.
-    if (!isHostLittleEndian && kind <= 4) {
-      auto l{value.low() << (8 * (sizeof(value.low()) - kind))};
+    // The value is stored in the lower order bits on big endian platform.
+    // When memcpy, shift the value to the higher order bit.
+    auto shft{static_cast<int>(sizeof(value.low())) - kind};
+    if (!isHostLittleEndian && shft >= 0) {
+      auto l{value.low() << (8 * shft)};
       std::memcpy(n, &l, kind);
     } else {
       std::memcpy(n, &value, kind); // a blank field means zero



More information about the flang-commits mailing list