[libc-commits] [libc] [libc] Some more MSVC compatibility in src/__support. (PR #158108)
via libc-commits
libc-commits at lists.llvm.org
Thu Sep 11 10:32:51 PDT 2025
https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/158108
>From e2a7269e1f3d0d17adf2995d413a14ff19d133c4 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 11 Sep 2025 16:25:57 +0000
Subject: [PATCH 1/3] [libc] Some more MSVC compatibility in src/__support.
---
libc/src/__support/CPP/bit.h | 2 +-
.../CPP/type_traits/is_destructible.h | 2 +-
libc/src/__support/FPUtil/FEnvImpl.h | 8 +++++--
libc/src/__support/FPUtil/FPBits.h | 10 ++++-----
libc/src/__support/endian_internal.h | 22 +++++++++++++++++++
libc/src/__support/macros/config.h | 1 +
libc/src/__support/math_extras.h | 10 +++++++++
7 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h
index 5a997ef555702..8dbb30047faec 100644
--- a/libc/src/__support/CPP/bit.h
+++ b/libc/src/__support/CPP/bit.h
@@ -39,7 +39,7 @@ bit_cast(const From &from) {
#if __has_builtin(__builtin_bit_cast)
return __builtin_bit_cast(To, from);
#else
- To to;
+ To to{};
char *dst = reinterpret_cast<char *>(&to);
const char *src = reinterpret_cast<const char *>(&from);
#if __has_builtin(__builtin_memcpy_inline)
diff --git a/libc/src/__support/CPP/type_traits/is_destructible.h b/libc/src/__support/CPP/type_traits/is_destructible.h
index 830f22efafa52..7ada2235b4e73 100644
--- a/libc/src/__support/CPP/type_traits/is_destructible.h
+++ b/libc/src/__support/CPP/type_traits/is_destructible.h
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace cpp {
// is_destructible
-#if __has_builtin(__is_destructible)
+#if __has_builtin(__is_destructible) || defined(LIBC_COMPILER_IS_MSVC)
template <typename T>
struct is_destructible : bool_constant<__is_destructible(T)> {};
#else
diff --git a/libc/src/__support/FPUtil/FEnvImpl.h b/libc/src/__support/FPUtil/FEnvImpl.h
index 7bd56434e58fe..ef3f60a5b3d7f 100644
--- a/libc/src/__support/FPUtil/FEnvImpl.h
+++ b/libc/src/__support/FPUtil/FEnvImpl.h
@@ -18,6 +18,7 @@
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h"
#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/macros/properties/compiler.h"
#if defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_FP)
#if defined(__APPLE__)
@@ -29,9 +30,12 @@
// The extra !defined(APPLE) condition is to cause x86_64 MacOS builds to use
// the dummy implementations below. Once a proper x86_64 darwin fenv is set up,
// the apple condition here should be removed.
-#elif defined(LIBC_TARGET_ARCH_IS_X86) && !defined(__APPLE__)
+// TODO: fully support fenv for MSVC.
+#elif defined(LIBC_TARGET_ARCH_IS_X86) && !defined(__APPLE__) && \
+ !defined(LIBC_COMPILER_IS_MSVC)
#include "x86_64/FEnvImpl.h"
-#elif defined(LIBC_TARGET_ARCH_IS_ARM) && defined(__ARM_FP)
+#elif defined(LIBC_TARGET_ARCH_IS_ARM) && defined(__ARM_FP) && \
+ !defined(LIBC_COMPILER_IS_MSVC)
#include "arm/FEnvImpl.h"
#elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV) && defined(__riscv_flen)
#include "riscv/FEnvImpl.h"
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 2f695c1583755..ce4925bae125a 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -789,16 +789,16 @@ struct FPRep : public FPRepImpl<fp_type, FPRep<fp_type>> {
// Returns the FPType corresponding to C++ type T on the host.
template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
using UnqualT = cpp::remove_cv_t<T>;
- if constexpr (cpp::is_same_v<UnqualT, float> && __FLT_MANT_DIG__ == 24)
+ if constexpr (cpp::is_same_v<UnqualT, float> && FLT_MANT_DIG == 24)
return FPType::IEEE754_Binary32;
- else if constexpr (cpp::is_same_v<UnqualT, double> && __DBL_MANT_DIG__ == 53)
+ 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)
+ if constexpr (LDBL_MANT_DIG == 53)
return FPType::IEEE754_Binary64;
- else if constexpr (__LDBL_MANT_DIG__ == 64)
+ else if constexpr (LDBL_MANT_DIG == 64)
return FPType::X86_Binary80;
- else if constexpr (__LDBL_MANT_DIG__ == 113)
+ else if constexpr (LDBL_MANT_DIG == 113)
return FPType::IEEE754_Binary128;
}
#if defined(LIBC_TYPES_HAS_FLOAT16)
diff --git a/libc/src/__support/endian_internal.h b/libc/src/__support/endian_internal.h
index c78090ad85e05..c309ccf4d146f 100644
--- a/libc/src/__support/endian_internal.h
+++ b/libc/src/__support/endian_internal.h
@@ -16,10 +16,32 @@
namespace LIBC_NAMESPACE_DECL {
// We rely on compiler preprocessor defines to allow for cross compilation.
+#ifdef LIBC_COMPILER_IS_MSVC
+#define __BYTE_ORDER__ 0
+#define __ORDER_LITTLE_ENDIAN__ 0
+#define __ORDER_BIG_ENDIAN__ 1
+
+LIBC_INLINE static uint16_t __builtin_bswap16(uint16_t v) {
+ return (v << 8) | (v >> 8);
+}
+
+LIBC_INLINE static uint16_t __builtin_bswap32(uint32_t v) {
+ return __builtin_bswap16(static_cast<uint16>(v >> 16)) ||
+ (static_cast<uint32_t>(__builtin_bswap16(static_cast<uint16_t>(v)))
+ << 16);
+}
+
+LIBC_INLINE static uint16_t __builtin_bswap64(uint64_t v) {
+ return __builtin_bswap32(static_cast<uint32>(v >> 32)) ||
+ (static_cast<uint64_t>(__builtin_bswap32(static_cast<uint32_t>(v)))
+ << 32);
+}
+#else
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
!defined(__ORDER_BIG_ENDIAN__)
#error "Missing preprocessor definitions for endianness detection."
#endif
+#endif // LIBC_COMPILER_IS_MSVC
namespace internal {
diff --git a/libc/src/__support/macros/config.h b/libc/src/__support/macros/config.h
index 685188893e7b7..501a816d49631 100644
--- a/libc/src/__support/macros/config.h
+++ b/libc/src/__support/macros/config.h
@@ -44,6 +44,7 @@
#endif
#define __builtin_expect(value, expectation) (value)
+#define __builtin_unreachable() __assume(0)
#endif // LIBC_COMPILER_IS_MSVC
diff --git a/libc/src/__support/math_extras.h b/libc/src/__support/math_extras.h
index 954bcb1b6ef89..d4dc6dcb4acf6 100644
--- a/libc/src/__support/math_extras.h
+++ b/libc/src/__support/math_extras.h
@@ -55,13 +55,23 @@ mask_leading_zeros() {
// Returns whether 'a + b' overflows, the result is stored in 'res'.
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr bool add_overflow(T a, T b, T &res) {
+#if __has_builtin(__builtin_add_overflow)
return __builtin_add_overflow(a, b, &res);
+#else
+ res = a + b;
+ return (res < a) || (res < b);
+#endif // __builtin_add_overflow
}
// Returns whether 'a - b' overflows, the result is stored in 'res'.
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr bool sub_overflow(T a, T b, T &res) {
+#if __has_builtin(__builtin_sub_overflow)
return __builtin_sub_overflow(a, b, &res);
+#else
+ res = a - b;
+ return (res > a);
+#endif // __builtin_sub_overflow
}
#define RETURN_IF(TYPE, BUILTIN) \
>From 1ce1e5c9b5e3a1e0413d157b2e1313b6698d8d6d Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 11 Sep 2025 17:28:18 +0000
Subject: [PATCH 2/3] Add byte_swap utility function.
---
libc/src/__support/endian_internal.h | 60 +++++++++++++++++-----------
1 file changed, 37 insertions(+), 23 deletions(-)
diff --git a/libc/src/__support/endian_internal.h b/libc/src/__support/endian_internal.h
index c309ccf4d146f..cc7bf989866c7 100644
--- a/libc/src/__support/endian_internal.h
+++ b/libc/src/__support/endian_internal.h
@@ -20,23 +20,7 @@ namespace LIBC_NAMESPACE_DECL {
#define __BYTE_ORDER__ 0
#define __ORDER_LITTLE_ENDIAN__ 0
#define __ORDER_BIG_ENDIAN__ 1
-
-LIBC_INLINE static uint16_t __builtin_bswap16(uint16_t v) {
- return (v << 8) | (v >> 8);
-}
-
-LIBC_INLINE static uint16_t __builtin_bswap32(uint32_t v) {
- return __builtin_bswap16(static_cast<uint16>(v >> 16)) ||
- (static_cast<uint32_t>(__builtin_bswap16(static_cast<uint16_t>(v)))
- << 16);
-}
-
-LIBC_INLINE static uint16_t __builtin_bswap64(uint64_t v) {
- return __builtin_bswap32(static_cast<uint32>(v >> 32)) ||
- (static_cast<uint64_t>(__builtin_bswap32(static_cast<uint32_t>(v)))
- << 32);
-}
-#else
+#else // !LIBC_COMPILER_IS_MSVC
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
!defined(__ORDER_BIG_ENDIAN__)
#error "Missing preprocessor definitions for endianness detection."
@@ -45,6 +29,36 @@ LIBC_INLINE static uint16_t __builtin_bswap64(uint64_t v) {
namespace internal {
+template <typename T> LIBC_INLINE T byte_swap(T value);
+
+template <> LIBC_INLINE uint16_t byte_swap<uint16_t>(uint16_t value) {
+#if __has_builtin(__builtin_bswap16)
+ return __builtin_bswap16(value);
+#else
+ return (v << 8) | (v >> 8);
+#endif // __builtin_bswap16
+};
+
+template <> LIBC_INLINE uint32_t byte_swap<uint32_t>(uint32_t value) {
+#if __has_builtin(__builtin_bswap32)
+ return __builtin_bswap32(value);
+#else
+ return byte_swap<uint16_t>(static_cast<uint16>(v >> 16)) ||
+ (static_cast<uint32_t>(byte_swap<uint16_t>(static_cast<uint16_t>(v)))
+ << 16);
+#endif // __builtin_bswap64
+};
+
+template <> LIBC_INLINE uint64_t byte_swap<uint64_t>(uint64_t value) {
+#if __has_builtin(__builtin_bswap64)
+ return __builtin_bswap64(value);
+#else
+ return byte_swap<uint32_t>(static_cast<uint32>(v >> 32)) ||
+ (static_cast<uint64_t>(byte_swap<uint32_t>(static_cast<uint32_t>(v)))
+ << 32);
+#endif // __builtin_bswap64
+};
+
// Converts uint8_t, uint16_t, uint32_t, uint64_t to its big or little endian
// counterpart.
// We use explicit template specialization:
@@ -75,7 +89,7 @@ template <>
template <>
LIBC_INLINE uint16_t
Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint16_t>(uint16_t v) {
- return __builtin_bswap16(v);
+ return byte_swap<uint16_t>(v);
}
template <>
template <>
@@ -87,7 +101,7 @@ template <>
template <>
LIBC_INLINE uint32_t
Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint32_t>(uint32_t v) {
- return __builtin_bswap32(v);
+ return byte_swap<uint32_t>(v);
}
template <>
template <>
@@ -99,7 +113,7 @@ template <>
template <>
LIBC_INLINE uint64_t
Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint64_t>(uint64_t v) {
- return __builtin_bswap64(v);
+ return byte_swap<uint64_t>(v);
}
template <>
template <>
@@ -131,7 +145,7 @@ template <>
template <>
LIBC_INLINE uint16_t
Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint16_t>(uint16_t v) {
- return __builtin_bswap16(v);
+ return byte_swap<uint16_t>(v);
}
template <>
template <>
@@ -143,7 +157,7 @@ template <>
template <>
LIBC_INLINE uint32_t
Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint32_t>(uint32_t v) {
- return __builtin_bswap32(v);
+ return byte_swap<uint32_t>(v);
}
template <>
template <>
@@ -155,7 +169,7 @@ template <>
template <>
LIBC_INLINE uint64_t
Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint64_t>(uint64_t v) {
- return __builtin_bswap64(v);
+ return byte_swap<uint64_t>(v);
}
} // namespace internal
>From b4c289fcc489401adc83f194e3254a94c6b223e4 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 11 Sep 2025 17:32:33 +0000
Subject: [PATCH 3/3] Remove extra ;
---
libc/src/__support/endian_internal.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/src/__support/endian_internal.h b/libc/src/__support/endian_internal.h
index cc7bf989866c7..4ac8709625d3a 100644
--- a/libc/src/__support/endian_internal.h
+++ b/libc/src/__support/endian_internal.h
@@ -37,7 +37,7 @@ template <> LIBC_INLINE uint16_t byte_swap<uint16_t>(uint16_t value) {
#else
return (v << 8) | (v >> 8);
#endif // __builtin_bswap16
-};
+}
template <> LIBC_INLINE uint32_t byte_swap<uint32_t>(uint32_t value) {
#if __has_builtin(__builtin_bswap32)
@@ -47,7 +47,7 @@ template <> LIBC_INLINE uint32_t byte_swap<uint32_t>(uint32_t value) {
(static_cast<uint32_t>(byte_swap<uint16_t>(static_cast<uint16_t>(v)))
<< 16);
#endif // __builtin_bswap64
-};
+}
template <> LIBC_INLINE uint64_t byte_swap<uint64_t>(uint64_t value) {
#if __has_builtin(__builtin_bswap64)
@@ -57,7 +57,7 @@ template <> LIBC_INLINE uint64_t byte_swap<uint64_t>(uint64_t value) {
(static_cast<uint64_t>(byte_swap<uint32_t>(static_cast<uint32_t>(v)))
<< 32);
#endif // __builtin_bswap64
-};
+}
// Converts uint8_t, uint16_t, uint32_t, uint64_t to its big or little endian
// counterpart.
More information about the libc-commits
mailing list