Skip to content

Commit fdccfa3

Browse files
madanial0kkwli
andauthored
[Flang] Shift the data from lower to higher order bits in the big endian environment (#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 <[email protected]> Co-authored-by: Kelvin Li <[email protected]>
1 parent 6dc5ba4 commit fdccfa3

File tree

2 files changed

+32
-11
lines changed

2 files changed

+32
-11
lines changed

flang/include/flang/Common/uint128.h

+22-10
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,18 @@ template <bool IS_SIGNED = false> class Int128 {
3333
constexpr Int128(unsigned n) : low_{n} {}
3434
constexpr Int128(unsigned long n) : low_{n} {}
3535
constexpr Int128(unsigned long long n) : low_{n} {}
36-
constexpr Int128(int n)
37-
: low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
38-
n < 0)} {}
39-
constexpr Int128(long n)
40-
: low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
41-
n < 0)} {}
42-
constexpr Int128(long long n)
43-
: low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
44-
n < 0)} {}
36+
constexpr Int128(int n) {
37+
low_ = static_cast<std::uint64_t>(n);
38+
high_ = -static_cast<std::uint64_t>(n < 0);
39+
}
40+
constexpr Int128(long n) {
41+
low_ = static_cast<std::uint64_t>(n);
42+
high_ = -static_cast<std::uint64_t>(n < 0);
43+
}
44+
constexpr Int128(long long n) {
45+
low_ = static_cast<std::uint64_t>(n);
46+
high_ = -static_cast<std::uint64_t>(n < 0);
47+
}
4548
constexpr Int128(const Int128 &) = default;
4649
constexpr Int128(Int128 &&) = default;
4750
constexpr Int128 &operator=(const Int128 &) = default;
@@ -246,7 +249,10 @@ template <bool IS_SIGNED = false> class Int128 {
246249
}
247250

248251
private:
249-
constexpr Int128(std::uint64_t hi, std::uint64_t lo) : low_{lo}, high_{hi} {}
252+
constexpr Int128(std::uint64_t hi, std::uint64_t lo) {
253+
low_ = lo;
254+
high_ = hi;
255+
}
250256
constexpr int LeadingZeroes() const {
251257
if (high_ == 0) {
252258
return 64 + LeadingZeroBitCount(low_);
@@ -255,7 +261,13 @@ template <bool IS_SIGNED = false> class Int128 {
255261
}
256262
}
257263
static constexpr std::uint64_t topBit{std::uint64_t{1} << 63};
264+
#if FLANG_LITTLE_ENDIAN
258265
std::uint64_t low_{0}, high_{0};
266+
#elif FLANG_BIG_ENDIAN
267+
std::uint64_t high_{0}, low_{0};
268+
#else
269+
#error host endianness is not known
270+
#endif
259271
};
260272

261273
using UnsignedInt128 = Int128<false>;

flang/runtime/edit-input.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,16 @@ bool EditIntegerInput(
244244
value = -value;
245245
}
246246
if (any || !io.GetConnectionState().IsAtEOF()) {
247-
std::memcpy(n, &value, kind); // a blank field means zero
247+
// The value is stored in the lower order bits on big endian platform.
248+
// When memcpy, shift the value to the higher order bit.
249+
auto shft{static_cast<int>(sizeof(value.low())) - kind};
250+
// For kind==8 (i.e. shft==0), the value is stored in low_ in big endian.
251+
if (!isHostLittleEndian && shft >= 0) {
252+
auto l{value.low() << (8 * shft)};
253+
std::memcpy(n, &l, kind);
254+
} else {
255+
std::memcpy(n, &value, kind); // a blank field means zero
256+
}
248257
}
249258
return any;
250259
}

0 commit comments

Comments
 (0)