[flang-commits] [flang] [flang] Fix REAL(10) Read() endianness for big-endian hosts (PR #234842)
via flang-commits
flang-commits at lists.llvm.org
Thu Oct 22 21:59:14 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Kelvin Li (kkwli)
<details>
<summary>Changes</summary>
On big-endian hosts (e.g. AIX), reinterpret_casting a uint128_t onto X87IntegerContainer misaligns the 80-bit x87 value, making every decimal-to-binary conversion return zero. Build Word via the Integer<> integer constructor instead, which uses SetLEPart() internally and is endian-portable. Also remove test expectations that reflected the bug.
https://github.com/llvm/llvm-project/pull/216958 exposes this bug and cause the following failures on AIX:
```
Failed Tests (3):
flang-Unit :: Evaluate/./FlangEvaluateTests/RealValueKind/RealValueKind/AsFortran/REAL_10
flang-Unit :: Evaluate/./FlangEvaluateTests/RealValueKind/RealValueKind/FromIntegerPowersOfTwo/REAL_10
flang-Unit :: Evaluate/./FlangEvaluateTests/RealValueKind/RealValueKind/Read/REAL_10
```
https://lab.llvm.org/buildbot/#/builders/231/builds/2026
Assisted-by: IBM Bob
---
Full diff: https://github.com/llvm/llvm-project/pull/234842.diff
3 Files Affected:
- (modified) flang/lib/Evaluate/real.cpp (+13-2)
- (modified) flang/test/Semantics/kinds04_q10.f90 (+1-4)
- (modified) flang/test/Semantics/kinds04_q16.f90 (+1-4)
``````````diff
diff --git a/flang/lib/Evaluate/real.cpp b/flang/lib/Evaluate/real.cpp
index b5413c9cb9129..f927cef7358d5 100644
--- a/flang/lib/Evaluate/real.cpp
+++ b/flang/lib/Evaluate/real.cpp
@@ -673,8 +673,19 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Read(
const char *&p, Rounding rounding) {
auto converted{
decimal::ConvertToBinary<P>(p, MapRoundingMode(rounding.mode))};
- const auto *value{reinterpret_cast<Real<W, P> *>(&converted.binary)};
- return {*value, MapFlags(converted.flags)};
+ // Building Word from lo/hi uint64_t halves via the Integer<> integer
+ // constructor is endian-portable
+ auto raw{converted.binary.raw()};
+ const std::uint64_t lo{static_cast<std::uint64_t>(raw)};
+ Word word{lo};
+ if constexpr (sizeof(typename decltype(converted.binary)::RawType) >
+ sizeof(std::uint64_t)) {
+ const std::uint64_t hi{static_cast<std::uint64_t>(raw >> 64)};
+ if (hi) {
+ word = word.IOR(Word{hi}.SHIFTL(64));
+ }
+ }
+ return {Real<W, P>{word}, MapFlags(converted.flags)};
}
template <typename W, int P> std::string Real<W, P>::DumpHexadecimal() const {
diff --git a/flang/test/Semantics/kinds04_q10.f90 b/flang/test/Semantics/kinds04_q10.f90
index 3bec7a386585b..118ce60071fcf 100644
--- a/flang/test/Semantics/kinds04_q10.f90
+++ b/flang/test/Semantics/kinds04_q10.f90
@@ -1,5 +1,5 @@
! RUN: not %flang_fc1 %s 2>%t.stderr
-! RUN: FileCheck %s --input-file=%t.stderr --check-prefixes=PORTABILITY,ERROR,WARNING%if system-aix %{,AIX_WARNING%}
+! RUN: FileCheck %s --input-file=%t.stderr --check-prefixes=PORTABILITY,ERROR,WARNING
! C716 If both kind-param and exponent-letter appear, exponent-letter
! shall be E. (As an extension we also allow an exponent-letter which matches
! the kind-param)
@@ -13,12 +13,10 @@ subroutine s(var)
!PORTABILITY: Explicit kind parameter together with non-'E' exponent letter is not standard
real :: realvar4 = 4.0D6_8
!WARNING: Explicit kind parameter on real constant disagrees with exponent letter 'q'
- !AIX_WARNING: underflow on REAL(10) to REAL(4) conversion
real :: realvar5 = 4.0Q6_10
!PORTABILITY: Explicit kind parameter together with non-'E' exponent letter is not standard
real :: realvar6 = 4.0Q6_16
real :: realvar7 = 4.0E6_8
- !AIX_WARNING: underflow on REAL(10) to REAL(4) conversion
real :: realvar8 = 4.0E6_10
real :: realvar9 = 4.0E6_16
!ERROR: Unsupported REAL(KIND=32)
@@ -32,7 +30,6 @@ subroutine s(var)
!PORTABILITY: Explicit kind parameter together with non-'E' exponent letter is not standard
double precision :: doublevar5 = 4.0Q6_16
double precision :: doublevar6 = 4.0E6_8
- !AIX_WARNING: underflow on REAL(10) to REAL(8) conversion
double precision :: doublevar7 = 4.0E6_10
double precision :: doublevar8 = 4.0E6_16
!ERROR: Unsupported REAL(KIND=32)
diff --git a/flang/test/Semantics/kinds04_q16.f90 b/flang/test/Semantics/kinds04_q16.f90
index d440fa4d1402d..d18191a8366b3 100644
--- a/flang/test/Semantics/kinds04_q16.f90
+++ b/flang/test/Semantics/kinds04_q16.f90
@@ -1,5 +1,5 @@
! RUN: not %flang_fc1 %s 2>%t.stderr
-! RUN: FileCheck %s --input-file=%t.stderr --check-prefixes=%if system-aix %{"PORTABILITY","WARNING","ERROR","AIX_WARNING"%} %else %{"PORTABILITY","WARNING","ERROR"%}
+! RUN: FileCheck %s --input-file=%t.stderr --check-prefixes=PORTABILITY,WARNING,ERROR
! C716 If both kind-param and exponent-letter appear, exponent-letter
! shall be E. (As an extension we also allow an exponent-letter which matches
! the kind-param)
@@ -16,12 +16,10 @@ subroutine s(var)
!PORTABILITY: Explicit kind parameter together with non-'E' exponent letter is not standard
real :: realvar4 = 4.0D6_8
!WARNING: Explicit kind parameter on real constant disagrees with exponent letter 'q'
- !AIX_WARNING: underflow on REAL(10) to REAL(4) conversion
real :: realvar5 = 4.0Q6_10
!PORTABILITY: Explicit kind parameter together with non-'E' exponent letter is not standard
real :: realvar6 = 4.0Q6_16
real :: realvar7 = 4.0E6_8
- !AIX_WARNING: underflow on REAL(10) to REAL(4) conversion
real :: realvar8 = 4.0E6_10
real :: realvar9 = 4.0E6_16
!ERROR: Unsupported REAL(KIND=32)
@@ -35,7 +33,6 @@ subroutine s(var)
!PORTABILITY: Explicit kind parameter together with non-'E' exponent letter is not standard
double precision :: doublevar5 = 4.0Q6_16
double precision :: doublevar6 = 4.0E6_8
- !AIX_WARNING: underflow on REAL(10) to REAL(8) conversion
double precision :: doublevar7 = 4.0E6_10
double precision :: doublevar8 = 4.0E6_16
!ERROR: Unsupported REAL(KIND=32)
``````````
</details>
https://github.com/llvm/llvm-project/pull/234842
More information about the flang-commits
mailing list