[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