[compiler-rt] Dev/aratiu/upstream i386 float128 fix (PR #200816)
Adrian Ratiu via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 1 06:28:33 PDT 2026
https://github.com/10ne1 created https://github.com/llvm/llvm-project/pull/200816
Hello everyone,
I independently hit the missing i386 builtins issue https://github.com/llvm/llvm-project/issues/121757 which got worse after upgrading to GCC 15 to build glibc in ChromiumOS (the rest of the system is built with clang + compiler-rt) and since the previous [PR fix](https://github.com/llvm/llvm-project/pull/122658) stalled for about 1.5 years, I'm posting a fix based on it, addressing pending feedback.
Two commits: one to add the generic TF builds for i386 and another to enable the long double <> float128 conversions.
>From 71c94e4d579e03e5b3a8d47228fbb91144c07489 Mon Sep 17 00:00:00 2001
From: Adrian Ratiu <adrian.ratiu at collabora.com>
Date: Mon, 1 Jun 2026 16:06:29 +0300
Subject: [PATCH 1/2] [compiler-rt][builtins] Build generic TF builtins for
i386
GCC >= 15.x forces glibc >= 2.26 to always enable float128 support
for i386, causing clang builds linking against glibc and compiler-rt
to fail with undefined symbols like:
ld.lld: error: undefined symbol: __unordtf2
>>> referenced by printf_fphex.c:123 (../stdio-common/printf_fphex.c:123)
>>> printf_fphex.o:(__printf_fphex_buffer) in archive /usr/i686-cros-linux-gnu/usr/lib/libc.a
>>> referenced by printf_fp.c:222
>>> printf_fp.o:(__printf_fp_buffer_1.constprop.0.isra.0) in archive /usr/i686-cros-linux-gnu/usr/lib/libc.a
The generic 128-bit float routines live in GENERIC_TF_SOURCES which
was not part of the i386 build. They also require __int128, which
clang does not enable by default on 32-bit x86.
So we add GENERIC_TF_SOURCES to i386_SOURCES and force-enable int128
for i386 as already done for riscv32 and 32-bit sparc (only when not
building with GCC), after which the symbols are emitted:
nm libclang_rt.builtins-i386.a | grep -E '__(unordtf2|addtf3|letf2)'
00000000 T __addtf3
00000000 T __letf2
00000000 T __unordtf2
Closes #121757
Based on https://github.com/llvm/llvm-project/pull/122658
Signed-off-by: Adrian Ratiu <adrian.ratiu at collabora.com>
---
compiler-rt/lib/builtins/CMakeLists.txt | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 1646b7077d7d1..11a3ddae064d9 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -379,6 +379,7 @@ if (NOT MSVC)
set(i386_SOURCES
${GENERIC_SOURCES}
${x86_ARCH_SOURCES}
+ ${GENERIC_TF_SOURCES}
i386/ashldi3.S
i386/ashrdi3.S
i386/divdi3.S
@@ -1086,9 +1087,9 @@ else ()
list(APPEND BUILTIN_CFLAGS_${arch} -fomit-frame-pointer -DCOMPILER_RT_ARMHF_TARGET)
endif()
- # For RISCV32 and 32-bit SPARC, we must force enable int128 for compiling long
- # double routines.
- if (COMPILER_RT_ENABLE_SOFTWARE_INT128 OR ("${arch}" MATCHES "riscv32|sparc$"
+ # For RISCV32, 32-bit SPARC and i386, we must force enable int128 for
+ # compiling long double routines.
+ if (COMPILER_RT_ENABLE_SOFTWARE_INT128 OR ("${arch}" MATCHES "riscv32|sparc$|i386"
AND NOT CMAKE_COMPILER_IS_GNUCC))
list(APPEND BUILTIN_CFLAGS_${arch} -fforce-enable-int128)
endif()
>From 8d84daf24a718194fbb5e5aad35e3d4ff91b6a24 Mon Sep 17 00:00:00 2001
From: Adrian Ratiu <adrian.ratiu at collabora.com>
Date: Mon, 1 Jun 2026 16:06:38 +0300
Subject: [PATCH 2/2] [compiler-rt][builtins] Enable i386 long double to
float128 conversions
__extendxftf2 (80-bit long double -> 128-bit __float128) and
__trunctfxf2 (the reverse) were already compiled for i386 via
x86_80_BIT_SOURCES, but their bodies were gated on defined(__x86_64__)
and so produced empty objects on i386.
Switch the guard from defined(__x86_64__) to HAS_80_BIT_LONG_DOUBLE so
the routines are emitted on i386, and correctly excluded on environments
without FP80 such as MSVC and Android.
Update the unit tests to match, passing -fforce-enable-int128 on the
RUN line unconditionally. This is safe because %clang_builtins always
invokes clang (never GCC) and the flag is a no-op where __int128 is
already native, so no lit substitution is needed.
Based on https://github.com/llvm/llvm-project/pull/122658
Signed-off-by: Adrian Ratiu <adrian.ratiu at collabora.com>
---
compiler-rt/lib/builtins/extendxftf2.c | 2 +-
compiler-rt/lib/builtins/trunctfxf2.c | 2 +-
compiler-rt/test/builtins/Unit/extendxftf2_test.c | 8 +++-----
compiler-rt/test/builtins/Unit/trunctfxf2_test.c | 8 +++-----
4 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/compiler-rt/lib/builtins/extendxftf2.c b/compiler-rt/lib/builtins/extendxftf2.c
index c1d97b5cfa151..dd9122902a4d0 100644
--- a/compiler-rt/lib/builtins/extendxftf2.c
+++ b/compiler-rt/lib/builtins/extendxftf2.c
@@ -12,7 +12,7 @@
#define QUAD_PRECISION
#include "fp_lib.h"
-#if defined(CRT_HAS_TF_MODE) && __LDBL_MANT_DIG__ == 64 && defined(__x86_64__)
+#if defined(CRT_HAS_TF_MODE) && __LDBL_MANT_DIG__ == 64 && HAS_80_BIT_LONG_DOUBLE
#define SRC_80
#define DST_QUAD
#include "fp_extend_impl.inc"
diff --git a/compiler-rt/lib/builtins/trunctfxf2.c b/compiler-rt/lib/builtins/trunctfxf2.c
index 49bd32d42aacb..d775f5b99976a 100644
--- a/compiler-rt/lib/builtins/trunctfxf2.c
+++ b/compiler-rt/lib/builtins/trunctfxf2.c
@@ -12,7 +12,7 @@
#define QUAD_PRECISION
#include "fp_lib.h"
-#if defined(CRT_HAS_TF_MODE) && __LDBL_MANT_DIG__ == 64 && defined(__x86_64__)
+#if defined(CRT_HAS_TF_MODE) && __LDBL_MANT_DIG__ == 64 && HAS_80_BIT_LONG_DOUBLE
#define SRC_QUAD
#define DST_80
diff --git a/compiler-rt/test/builtins/Unit/extendxftf2_test.c b/compiler-rt/test/builtins/Unit/extendxftf2_test.c
index 7c3b0abdc3924..65ddaa317fc90 100644
--- a/compiler-rt/test/builtins/Unit/extendxftf2_test.c
+++ b/compiler-rt/test/builtins/Unit/extendxftf2_test.c
@@ -1,11 +1,10 @@
-// RUN: %clang_builtins %s %librt -o %t && %run %t
+// RUN: %clang_builtins %s %librt -fforce-enable-int128 -o %t && %run %t
// REQUIRES: librt_has_extendxftf2
#include "int_lib.h"
#include <stdio.h>
-#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) && \
- (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
+#if defined(CRT_HAS_TF_MODE) && HAS_80_BIT_LONG_DOUBLE
#include "fp_test.h"
@@ -28,8 +27,7 @@ char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
#endif
int main() {
-#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) && \
- (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
+#if defined(CRT_HAS_TF_MODE) && HAS_80_BIT_LONG_DOUBLE
// qNaN
if (test__extendxftf2(makeQNaN80(), UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
diff --git a/compiler-rt/test/builtins/Unit/trunctfxf2_test.c b/compiler-rt/test/builtins/Unit/trunctfxf2_test.c
index 76885e255e4c4..25a46b9f645d9 100644
--- a/compiler-rt/test/builtins/Unit/trunctfxf2_test.c
+++ b/compiler-rt/test/builtins/Unit/trunctfxf2_test.c
@@ -1,11 +1,10 @@
-// RUN: %clang_builtins %s %librt -o %t && %run %t
+// RUN: %clang_builtins %s %librt -fforce-enable-int128 -o %t && %run %t
// REQUIRES: librt_has_trunctfxf2
#include "int_lib.h"
#include <stdio.h>
-#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) && \
- (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
+#if defined(CRT_HAS_TF_MODE) && HAS_80_BIT_LONG_DOUBLE
#include "fp_test.h"
@@ -28,8 +27,7 @@ char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
#endif
int main() {
-#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) && \
- (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
+#if defined(CRT_HAS_TF_MODE) && HAS_80_BIT_LONG_DOUBLE
// qNaN
if (test__trunctfxf2(makeQNaN128(), UINT64_C(0x7FFF),
UINT64_C(0xC000000000000000)))
More information about the llvm-commits
mailing list