[libc-commits] [libc] [libc] Fix FreeBSD build for 53-bit-rounded fp80s (PR #216332)

Lewis Crawford via libc-commits libc-commits at lists.llvm.org
Fri Aug 14 07:36:18 PDT 2026


https://github.com/LewisCrawford created https://github.com/llvm/llvm-project/pull/216332

Fix build issues on FreeBSD, which reports `LDBL_MANT_DIG == 53` for `long double` on some targets despite using fp80 as the underlying type. This is because it stores the value as an fp80, but configures the FPU to round the mantissa to 53-bits. However, this causes some parts of libc to misidentify the fp80 as an fp64 since both use a 53-bit mantissa. This led to build issues on FreeBSD when trying to bitcast the 12-byte `FPBits<long double>` to an 8-byte fp64 value.

This is fixed by checking both the mantissa size and the exponent range when determining the correct format for `long double`. Also, move the check for this to a single place in `types.h`, rather than re-checking the `LDBL_MANT_DIG` and `LDBL_MAX_EXP` values in `FPBits.h`.

>From e87b3f766c74ebd40b468ea464594ab38789452e Mon Sep 17 00:00:00 2001
From: Lewis Crawford <lcrawford at nvidia.com>
Date: Thu, 13 Aug 2026 17:06:06 +0000
Subject: [PATCH] [libc] Fix FreeBSD build for 53-bit-rounded fp80s

Fix build issues on FreeBSD, which reports `LDBL_MANT_DIG == 53` for
`long double` on some targets despite using fp80 as the underlying type.
This is because it stores the value as an fp80, but configures the FPU to
round the mantissa to 53-bits. However, this causes some parts of libc to
misidentify the fp80 as an fp64 since both use a 53-bit mantissa.
This led to build issues on FreeBSD when trying to bitcast the 12-byte
`FPBits<long double>` to an 8-byte fp64 value.

This is fixed by checking both the mantissa size and the exponent range
when determining the correct format for `long double`. Also, move the
check for this to a single place in `types.h`, rather than re-checking
the `LDBL_MANT_DIG` and `LDBL_MAX_EXP` values in `FPBits.h`.
---
 libc/src/__support/FPUtil/FPBits.h           | 15 ++++++++-------
 libc/src/__support/macros/properties/types.h | 11 +++++++++--
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 58222f1a7ae15..0a7aee7ae232e 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -794,14 +794,15 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
   else if constexpr (cpp::is_same_v<UnqualT, double> && DBL_MANT_DIG == 53)
     return FPType::IEEE754_Binary64;
   else if constexpr (cpp::is_same_v<UnqualT, long double>) {
-    if constexpr (LDBL_MANT_DIG == 53)
-      return FPType::IEEE754_Binary64;
-    else if constexpr (LDBL_MANT_DIG == 64)
-      return FPType::X86_Binary80;
+#if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
+    return FPType::IEEE754_Binary64;
+#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
+    return FPType::X86_Binary80;
+#else
     // TODO: properly treat double-double type.
-    // else if constexpr (LDBL_MANT_DIG == 113)
-    else
-      return FPType::IEEE754_Binary128;
+    // #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
+    return FPType::IEEE754_Binary128;
+#endif
   }
 #if defined(LIBC_TYPES_HAS_FLOAT16)
   else if constexpr (cpp::is_same_v<UnqualT, float16>)
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index 083b05164ae64..a5925cdd704b7 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -21,9 +21,16 @@
 #include "src/__support/macros/properties/os.h"
 
 // 'long double' properties.
-#if (LDBL_MANT_DIG == 53)
+//
+// Note: we cannot distinguish between f64 and f80 by just checking for a 53-bit
+// mantissa. On FreeBSD, `long double` is an fp80, but the FPU rounds the
+// mantissa to 53 bits. On GCC this is TARGET_96_ROUND_53_LONG_DOUBLE, which
+// reports LDBL_MANT_DIG == 53. As such, we must also check the exponent's range
+// to distinguish between f64 and 53-bit rounded f80 for `long double`.
+#if (LDBL_MANT_DIG == 53) && (LDBL_MAX_EXP == 1024)
 #define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64
-#elif (LDBL_MANT_DIG == 64)
+#elif (LDBL_MANT_DIG == 64) ||                                                 \
+    ((LDBL_MANT_DIG == 53) && (LDBL_MAX_EXP == 16384))
 #define LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
 #elif (LDBL_MANT_DIG == 113)
 #define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128



More information about the libc-commits mailing list