[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