diff --git a/libc/utils/FPUtil/FloatProperties.h b/libc/utils/FPUtil/FloatProperties.h --- a/libc/utils/FPUtil/FloatProperties.h +++ b/libc/utils/FPUtil/FloatProperties.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_UTILS_FPUTIL_FLOAT_PROPERTIES_H #define LLVM_LIBC_UTILS_FPUTIL_FLOAT_PROPERTIES_H +#include "PlatformDefs.h" #include namespace __llvm_libc { @@ -24,6 +25,7 @@ static constexpr uint32_t bitWidth = sizeof(BitsType) << 3; static constexpr uint32_t mantissaWidth = 23; + static constexpr uint32_t exponentWidth = 8; static constexpr BitsType mantissaMask = 0x007fffffU; static constexpr BitsType signMask = 0x80000000U; static constexpr BitsType exponentMask = ~(signMask | mantissaMask); @@ -43,6 +45,7 @@ static constexpr uint32_t bitWidth = sizeof(BitsType) << 3; static constexpr uint32_t mantissaWidth = 52; + static constexpr uint32_t exponentWidth = 11; static constexpr BitsType mantissaMask = 0x000fffffffffffffU; static constexpr BitsType signMask = 0x8000000000000000ULL; static constexpr BitsType exponentMask = ~(signMask | mantissaMask); @@ -54,6 +57,83 @@ static constexpr BitsType quietNaNMask = 0x0008000000000000ULL; }; +// Properties for long double on Windows platform, same as double precision. +#if defined(LONG_DOUBLE_IS_DOUBLE) +template <> struct FloatProperties { + typedef uint64_t BitsType; + static_assert(sizeof(BitsType) == sizeof(double), + "Unexpected size of 'double' type."); + + static constexpr uint32_t bitWidth = FloatProperties::bitWidth; + + static constexpr uint32_t mantissaWidth = + FloatProperties::mantissaWidth; + static constexpr uint32_t exponentWidth = + FloatProperties::exponentWidth; + static constexpr BitsType mantissaMask = + FloatProperties::mantissaMask; + static constexpr BitsType signMask = FloatProperties::signMask; + static constexpr BitsType exponentMask = + FloatProperties::exponentMask; + static constexpr uint32_t exponentOffset = + FloatProperties::exponentOffset; + + // If a number x is a NAN, then it is a quiet NAN if: + // QuietNaNMask & bits(x) != 0 + // Else, it is a signalling NAN. + static constexpr BitsType quietNaNMask = + FloatProperties::quietNaNMask; +}; +#endif + +// Properties for long double on non-Windows x86 platforms. +#if defined(SPECIAL_X86_LONG_DOUBLE) +template <> struct FloatProperties { + typedef __uint128_t BitsType; + static_assert(sizeof(BitsType) == sizeof(long double), + "Unexpected size of 'long double' type."); + + static constexpr uint32_t bitWidth = sizeof(BitsType) << 3; + + static constexpr uint32_t mantissaWidth = 64; + static constexpr uint32_t exponentWidth = 15; + static constexpr BitsType mantissaMask = 0xffffffffffffffffU; + static constexpr BitsType signMask = (BitsType)0x00008000U << 64; + static constexpr BitsType exponentMask = ~(signMask | mantissaMask); + static constexpr uint32_t exponentOffset = 16383; + // If a number x is a NAN, then it is a quiet NAN if: + // QuietNaNMask & bits(x) != 0 + // Else, it is a signalling NAN. + static constexpr BitsType quietNaNMask = 0x8000000000000000U; +}; +#endif + +// Properties for long double on non x86 platform. +#if !defined(SPECIAL_X86_LONG_DOUBLE) +template <> struct FloatProperties { + typedef __uint128_t BitsType; + static_assert(sizeof(BitsType) == sizeof(long double), + "Unexpected size of 'long double' type."); + + static constexpr uint32_t bitWidth = sizeof(BitsType) << 3; + + static constexpr uint32_t mantissaWidth = 112; + static constexpr uint32_t exponentWidth = 15; + static constexpr BitsType mantissaMask = + ((BitsType)0x0000ffffffffffffU << 64) | (BitsType)0xffffffffffffffffU; + static constexpr BitsType signMask = (BitsType)0x8000000000000000U << 64; + static constexpr BitsType exponentMask = ~(signMask | mantissaMask); + static constexpr uint32_t exponentOffset = 16383; + + // If a number x is a NAN, then it is a quiet NAN if: + // QuietNaNMask & bits(x) != 0 + // Else, it is a signalling NAN. + static constexpr BitsType quietNaNMask = + (BitsType)0x0000800000000000U + << 64; // Has the most significant bit in the mantissa set to one. +}; +#endif + // Define the float type corresponding to the BitsType. template struct FloatType; @@ -69,6 +149,12 @@ typedef double Type; }; +template <> struct FloatType<__uint128_t> { + static_assert(sizeof(__uint128_t) == sizeof(long double), + "Unexpected size of 'double' type."); + typedef long double Type; +}; + template using FloatTypeT = typename FloatType::Type;