Skip to content

Commit

Permalink
[Flang] Shift the data from lower to higher order bits in the big end…
Browse files Browse the repository at this point in the history
…ian environment (llvm#73670)

Shift the data from lower to higher order bits when memcpy the value in
the namelist in the big endian environment

---------

Co-authored-by: Mark Danial <mark.danial@ibm.com>
Co-authored-by: Kelvin Li <kli@ca.ibm.com>
  • Loading branch information
3 people authored Dec 28, 2023
1 parent 6dc5ba4 commit fdccfa3
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 11 deletions.
32 changes: 22 additions & 10 deletions flang/include/flang/Common/uint128.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,18 @@ template <bool IS_SIGNED = false> class Int128 {
constexpr Int128(unsigned n) : low_{n} {}
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)} {}
constexpr Int128(long n)
: 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)} {}
constexpr Int128(int n) {
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);
}
constexpr Int128(long long n) {
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;
Expand Down Expand Up @@ -246,7 +249,10 @@ 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) {
low_ = lo;
high_ = hi;
}
constexpr int LeadingZeroes() const {
if (high_ == 0) {
return 64 + LeadingZeroBitCount(low_);
Expand All @@ -255,7 +261,13 @@ template <bool IS_SIGNED = false> class Int128 {
}
}
static constexpr std::uint64_t topBit{std::uint64_t{1} << 63};
#if FLANG_LITTLE_ENDIAN
std::uint64_t low_{0}, high_{0};
#elif FLANG_BIG_ENDIAN
std::uint64_t high_{0}, low_{0};
#else
#error host endianness is not known
#endif
};

using UnsignedInt128 = Int128<false>;
Expand Down
11 changes: 10 additions & 1 deletion flang/runtime/edit-input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,16 @@ bool EditIntegerInput(
value = -value;
}
if (any || !io.GetConnectionState().IsAtEOF()) {
std::memcpy(n, &value, kind); // a blank field means zero
// 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};
// For kind==8 (i.e. shft==0), the value is stored in low_ in big endian.
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
}
}
return any;
}
Expand Down

0 comments on commit fdccfa3

Please sign in to comment.