Author: Guillaume Chatelet Date: 2024-03-07T11:05:26+01:00 New Revision: f3ca6565d507bdcd9db5a363d627f6b69cb6f277
URL: https://github.com/llvm/llvm-project/commit/f3ca6565d507bdcd9db5a363d627f6b69cb6f277 DIFF: https://github.com/llvm/llvm-project/commit/f3ca6565d507bdcd9db5a363d627f6b69cb6f277.diff LOG: Revert "[libc] Remove UB specializations of type traits for `BigInt` (#84035)" This reverts commit 84f483dbeeba5ecadbf3e4a75bfb71525a3fa332. Added: Modified: libc/src/__support/CMakeLists.txt libc/src/__support/CPP/bit.h libc/src/__support/UInt.h libc/src/__support/float_to_string.h libc/src/__support/integer_to_string.h libc/test/UnitTest/CMakeLists.txt libc/test/UnitTest/LibcTest.cpp libc/test/UnitTest/LibcTest.h libc/test/UnitTest/TestLogger.cpp libc/test/src/__support/CPP/bit_test.cpp utils/bazel/llvm-project-overlay/libc/BUILD.bazel utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel Removed: ################################################################################ diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index 17c04aa57e6fd6..1a4b3e9a2145c0 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -95,7 +95,6 @@ add_header_library( HDRS integer_to_string.h DEPENDS - .uint libc.src.__support.common libc.src.__support.CPP.algorithm libc.src.__support.CPP.limits diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h index bc2f595845a95f..7d11e7d5c497e0 100644 --- a/libc/src/__support/CPP/bit.h +++ b/libc/src/__support/CPP/bit.h @@ -27,14 +27,13 @@ namespace LIBC_NAMESPACE::cpp { // This implementation of bit_cast requires trivially-constructible To, to avoid // UB in the implementation. -template <typename To, typename From> -LIBC_INLINE constexpr cpp::enable_if_t< - (sizeof(To) == sizeof(From)) && - cpp::is_trivially_constructible<To>::value && - cpp::is_trivially_copyable<To>::value && - cpp::is_trivially_copyable<From>::value, - To> -bit_cast(const From &from) { +template < + typename To, typename From, + typename = cpp::enable_if_t<sizeof(To) == sizeof(From) && + cpp::is_trivially_constructible<To>::value && + cpp::is_trivially_copyable<To>::value && + cpp::is_trivially_copyable<From>::value>> +LIBC_INLINE constexpr To bit_cast(const From &from) { MSAN_UNPOISON(&from, sizeof(From)); #if LIBC_HAS_BUILTIN(__builtin_bit_cast) return __builtin_bit_cast(To, from); @@ -52,10 +51,8 @@ bit_cast(const From &from) { #endif // LIBC_HAS_BUILTIN(__builtin_bit_cast) } -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, - bool> -has_single_bit(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr bool has_single_bit(T value) { return (value != 0) && ((value & (value - 1)) == 0); } @@ -73,9 +70,8 @@ has_single_bit(T value) { /// Only unsigned integral types are allowed. /// /// Returns cpp::numeric_limits<T>::digits on an input of 0. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -countr_zero(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int countr_zero(T value) { if (!value) return cpp::numeric_limits<T>::digits; if (value & 0x1) @@ -107,9 +103,8 @@ ADD_SPECIALIZATION(countr_zero, unsigned long long, __builtin_ctzll) /// Only unsigned integral types are allowed. /// /// Returns cpp::numeric_limits<T>::digits on an input of 0. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -countl_zero(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int countl_zero(T value) { if (!value) return cpp::numeric_limits<T>::digits; // Bisection method. @@ -140,9 +135,8 @@ ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll) /// Only unsigned integral types are allowed. /// /// Returns cpp::numeric_limits<T>::digits on an input of all ones. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -countl_one(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int countl_one(T value) { return cpp::countl_zero<T>(~value); } @@ -153,9 +147,8 @@ countl_one(T value) { /// Only unsigned integral types are allowed. /// /// Returns cpp::numeric_limits<T>::digits on an input of all ones. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -countr_one(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int countr_one(T value) { return cpp::countr_zero<T>(~value); } @@ -163,9 +156,8 @@ countr_one(T value) { /// Returns 0 otherwise. /// /// Ex. bit_width(5) == 3. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -bit_width(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int bit_width(T value) { return cpp::numeric_limits<T>::digits - cpp::countl_zero(value); } @@ -173,9 +165,8 @@ bit_width(T value) { /// nonzero. Returns 0 otherwise. /// /// Ex. bit_floor(5) == 4. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> -bit_floor(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr T bit_floor(T value) { if (!value) return 0; return T(1) << (cpp::bit_width(value) - 1); @@ -188,9 +179,8 @@ bit_floor(T value) { /// /// The return value is undefined if the input is larger than the largest power /// of two representable in T. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> -bit_ceil(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr T bit_ceil(T value) { if (value < 2) return 1; return T(1) << cpp::bit_width<T>(value - 1u); @@ -200,31 +190,28 @@ bit_ceil(T value) { // from https://blog.regehr.org/archives/1063. // Forward-declare rotr so that rotl can use it. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> -rotr(T value, int rotate); +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr T rotr(T value, int rotate); -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> -rotl(T value, int rotate) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr T rotl(T value, int rotate) { constexpr unsigned N = cpp::numeric_limits<T>::digits; rotate = rotate % N; if (!rotate) return value; if (rotate < 0) - return cpp::rotr<T>(value, -rotate); + return cpp::rotr(value, -rotate); return (value << rotate) | (value >> (N - rotate)); } -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> -rotr(T value, int rotate) { +template <typename T, typename> +[[nodiscard]] LIBC_INLINE constexpr T rotr(T value, int rotate) { constexpr unsigned N = cpp::numeric_limits<T>::digits; rotate = rotate % N; if (!rotate) return value; if (rotate < 0) - return cpp::rotl<T>(value, -rotate); + return cpp::rotl(value, -rotate); return (value >> rotate) | (value << (N - rotate)); } @@ -239,44 +226,33 @@ LIBC_INLINE constexpr To bit_or_static_cast(const From &from) { } } -// TODO: remove from 'bit.h' as it is not a standard function. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -first_leading_zero(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int first_leading_zero(T value) { return value == cpp::numeric_limits<T>::max() ? 0 : countl_one(value) + 1; } -// TODO: remove from 'bit.h' as it is not a standard function. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -first_leading_one(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int first_leading_one(T value) { return first_leading_zero(static_cast<T>(~value)); } -// TODO: remove from 'bit.h' as it is not a standard function. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -first_trailing_zero(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int first_trailing_zero(T value) { return value == cpp::numeric_limits<T>::max() ? 0 : countr_zero(static_cast<T>(~value)) + 1; } -// TODO: remove from 'bit.h' as it is not a standard function. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -first_trailing_one(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int first_trailing_one(T value) { return value == cpp::numeric_limits<T>::max() ? 0 : countr_zero(value) + 1; } /// Count number of 1's aka population count or hamming weight. /// /// Only unsigned integral types are allowed. -// TODO: rename as 'popcount' to follow the standard -// https://en.cppreference.com/w/cpp/numeric/popcount -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -count_ones(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int count_ones(T value) { int count = 0; for (int i = 0; i != cpp::numeric_limits<T>::digits; ++i) if ((value >> i) & 0x1) @@ -296,10 +272,8 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) // TODO: 128b specializations? #undef ADD_SPECIALIZATION -// TODO: remove from 'bit.h' as it is not a standard function. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> -count_zeros(T value) { +template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>> +[[nodiscard]] LIBC_INLINE constexpr int count_zeros(T value) { return count_ones<T>(static_cast<T>(~value)); } diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h index b3d8f00b9a01a5..5973e6fab1d7d5 100644 --- a/libc/src/__support/UInt.h +++ b/libc/src/__support/UInt.h @@ -43,9 +43,6 @@ struct BigInt { static_assert(is_integral_v<WordType> && is_unsigned_v<WordType>, "WordType must be unsigned integer."); - using word_type = WordType; - LIBC_INLINE_VAR static constexpr bool SIGNED = Signed; - LIBC_INLINE_VAR static constexpr size_t BITS = Bits; LIBC_INLINE_VAR static constexpr size_t WORD_SIZE = sizeof(WordType) * CHAR_BIT; @@ -53,10 +50,6 @@ struct BigInt { "Number of bits in BigInt should be a multiple of WORD_SIZE."); LIBC_INLINE_VAR static constexpr size_t WORD_COUNT = Bits / WORD_SIZE; - - using unsigned_type = BigInt<BITS, false, word_type>; - using signed_type = BigInt<BITS, true, word_type>; - cpp::array<WordType, WORD_COUNT> val{}; LIBC_INLINE constexpr BigInt() = default; @@ -586,33 +579,19 @@ struct BigInt { return *this; } - // TODO: remove and use cpp::countl_zero below. - [[nodiscard]] LIBC_INLINE constexpr int clz() const { - constexpr int word_digits = cpp::numeric_limits<word_type>::digits; - int leading_zeroes = 0; - for (auto i = val.size(); i > 0;) { - --i; - const int zeroes = countl_zero(val[i]); - leading_zeroes += zeroes; - if (zeroes != word_digits) + LIBC_INLINE constexpr uint64_t clz() { + uint64_t leading_zeroes = 0; + for (size_t i = WORD_COUNT; i > 0; --i) { + if (val[i - 1] == 0) { + leading_zeroes += WORD_SIZE; + } else { + leading_zeroes += countl_zero(val[i - 1]); break; + } } return leading_zeroes; } - // TODO: remove and use cpp::countr_zero below. - [[nodiscard]] LIBC_INLINE constexpr int ctz() const { - constexpr int word_digits = cpp::numeric_limits<word_type>::digits; - int trailing_zeroes = 0; - for (auto word : val) { - const int zeroes = countr_zero(word); - trailing_zeroes += zeroes; - if (zeroes != word_digits) - break; - } - return trailing_zeroes; - } - LIBC_INLINE constexpr void shift_left(size_t s) { if constexpr (Bits == WORD_SIZE) { // Use native types if possible. @@ -937,121 +916,64 @@ template <> class numeric_limits<Int<128>> { LIBC_INLINE_VAR static constexpr int digits = 128; }; -// type traits to determine whether a T is a cpp::BigInt. -template <typename T> struct is_big_int : cpp::false_type {}; - +// Provides is_integral of U/Int<128>, U/Int<192>, U/Int<256>. template <size_t Bits, bool Signed, typename T> -struct is_big_int<BigInt<Bits, Signed, T>> : cpp::true_type {}; - -template <class T> -LIBC_INLINE_VAR constexpr bool is_big_int_v = is_big_int<T>::value; - -// Specialization of cpp::bit_cast ('bit.h') from T to BigInt. -template <typename To, typename From> -LIBC_INLINE constexpr cpp::enable_if_t< - (sizeof(To) == sizeof(From)) && cpp::is_trivially_copyable<To>::value && - cpp::is_trivially_copyable<From>::value && is_big_int<To>::value, - To> -bit_cast(const From &from) { - To out; - using Storage = decltype(out.val); - out.val = cpp::bit_cast<Storage>(from); - return out; -} +struct is_integral<BigInt<Bits, Signed, T>> : cpp::true_type {}; -// Specialization of cpp::bit_cast ('bit.h') from BigInt to T. -template <typename To, size_t Bits> -LIBC_INLINE constexpr cpp::enable_if_t< - sizeof(To) == sizeof(UInt<Bits>) && - cpp::is_trivially_constructible<To>::value && - cpp::is_trivially_copyable<To>::value && - cpp::is_trivially_copyable<UInt<Bits>>::value, - To> -bit_cast(const UInt<Bits> &from) { - return cpp::bit_cast<To>(from.val); -} - -// Specialization of cpp::has_single_bit ('bit.h') for BigInt. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, bool> -has_single_bit(T value) { - int bits = 0; - for (auto word : value.val) { - if (word == 0) - continue; - bits += count_ones(word); - if (bits > 1) - return false; - } - return bits == 1; -} - -// Specialization of cpp::countr_zero ('bit.h') for BigInt. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int> -countr_zero(const T &value) { - return value.ctz(); -} +// Provides is_unsigned of UInt<128>, UInt<192>, UInt<256>. +template <size_t Bits, bool Signed, typename T> +struct is_unsigned<BigInt<Bits, Signed, T>> : cpp::bool_constant<!Signed> {}; -// Specialization of cpp::countl_zero ('bit.h') for BigInt. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int> -countl_zero(const T &value) { - return value.clz(); -} +template <size_t Bits, bool Signed, typename T> +struct make_unsigned<BigInt<Bits, Signed, T>> + : type_identity<BigInt<Bits, false, T>> {}; -// Specialization of cpp::countl_one ('bit.h') for BigInt. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int> -countl_one(T value) { - // TODO : Implement a faster version not involving operator~. - return cpp::countl_zero<T>(~value); -} +template <size_t Bits, bool Signed, typename T> +struct make_signed<BigInt<Bits, Signed, T>> + : type_identity<BigInt<Bits, true, T>> {}; -// Specialization of cpp::countr_one ('bit.h') for BigInt. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int> -countr_one(T value) { - // TODO : Implement a faster version not involving operator~. - return cpp::countr_zero<T>(~value); -} +namespace internal { +template <typename T> struct is_custom_uint : cpp::false_type {}; -// Specialization of cpp::bit_width ('bit.h') for BigInt. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, int> -bit_width(T value) { - return cpp::numeric_limits<T>::digits - cpp::countl_zero(value); -} +template <size_t Bits, bool Signed, typename T> +struct is_custom_uint<BigInt<Bits, Signed, T>> : cpp::true_type {}; +} // namespace internal -// Forward-declare rotr so that rotl can use it. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, T> -rotr(T value, int rotate); - -// Specialization of cpp::rotl ('bit.h') for BigInt. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, T> -rotl(T value, int rotate) { - constexpr unsigned N = cpp::numeric_limits<T>::digits; - rotate = rotate % N; - if (!rotate) - return value; - if (rotate < 0) - return cpp::rotr<T>(value, -rotate); - return (value << rotate) | (value >> (N - rotate)); +// bit_cast to UInt +// Note: The standard scheme for SFINAE selection is to have exactly one +// function instanciation valid at a time. This is usually done by having a +// predicate in one function and the negated predicate in the other one. +// e.g. +// template<typename = cpp::enable_if_t< is_custom_uint<To>::value == true> ... +// template<typename = cpp::enable_if_t< is_custom_uint<To>::value == false> ... +// +// Unfortunately this would make the default 'cpp::bit_cast' aware of +// 'is_custom_uint' (or any other customization). To prevent exposing all +// customizations in the original function, we create a diff erent function with +// four 'typename's instead of three - otherwise it would be considered as a +// redeclaration of the same function leading to "error: template parameter +// redefines default argument". +template <typename To, typename From, + typename = cpp::enable_if_t<sizeof(To) == sizeof(From) && + cpp::is_trivially_copyable<To>::value && + cpp::is_trivially_copyable<From>::value>, + typename = cpp::enable_if_t<internal::is_custom_uint<To>::value>> +LIBC_INLINE constexpr To bit_cast(const From &from) { + To out; + using Storage = decltype(out.val); + out.val = cpp::bit_cast<Storage>(from); + return out; } -// Specialization of cpp::rotr ('bit.h') for BigInt. -template <typename T> -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, T> -rotr(T value, int rotate) { - constexpr unsigned N = cpp::numeric_limits<T>::digits; - rotate = rotate % N; - if (!rotate) - return value; - if (rotate < 0) - return cpp::rotl<T>(value, -rotate); - return (value >> rotate) | (value << (N - rotate)); +// bit_cast from UInt +template < + typename To, size_t Bits, + typename = cpp::enable_if_t<sizeof(To) == sizeof(UInt<Bits>) && + cpp::is_trivially_constructible<To>::value && + cpp::is_trivially_copyable<To>::value && + cpp::is_trivially_copyable<UInt<Bits>>::value>> +LIBC_INLINE constexpr To bit_cast(const UInt<Bits> &from) { + return cpp::bit_cast<To>(from.val); } } // namespace LIBC_NAMESPACE::cpp diff --git a/libc/src/__support/float_to_string.h b/libc/src/__support/float_to_string.h index 27476433a94575..744842ced8d772 100644 --- a/libc/src/__support/float_to_string.h +++ b/libc/src/__support/float_to_string.h @@ -713,7 +713,7 @@ template <> class FloatToString<long double> { float_as_fixed.shift_left(SHIFT_AMOUNT); // If there are still digits above the decimal point, handle those. - if (float_as_fixed.clz() < static_cast<int>(EXTRA_INT_WIDTH)) { + if (float_as_fixed.clz() < EXTRA_INT_WIDTH) { cpp::UInt<EXTRA_INT_WIDTH> above_decimal_point = float_as_fixed >> FLOAT_AS_INT_WIDTH; diff --git a/libc/src/__support/integer_to_string.h b/libc/src/__support/integer_to_string.h index a5872dce652036..81ed21ccfca166 100644 --- a/libc/src/__support/integer_to_string.h +++ b/libc/src/__support/integer_to_string.h @@ -67,7 +67,6 @@ #include "src/__support/CPP/span.h" #include "src/__support/CPP/string_view.h" #include "src/__support/CPP/type_traits.h" -#include "src/__support/UInt.h" // is_big_int #include "src/__support/common.h" namespace LIBC_NAMESPACE { @@ -150,18 +149,6 @@ template <bool forward> class StringBufferWriterImpl { using StringBufferWriter = StringBufferWriterImpl<true>; using BackwardStringBufferWriter = StringBufferWriterImpl<false>; -template <typename T, class = void> struct IntegerWriterUnsigned {}; - -template <typename T> -struct IntegerWriterUnsigned<T, cpp::enable_if_t<cpp::is_integral_v<T>>> { - using type = cpp::make_unsigned_t<T>; -}; - -template <typename T> -struct IntegerWriterUnsigned<T, cpp::enable_if_t<cpp::is_big_int_v<T>>> { - using type = typename T::unsigned_type; -}; - } // namespace details namespace radix { @@ -176,7 +163,7 @@ template <size_t radix> using Custom = details::Fmt<radix>; // See file header for documentation. template <typename T, typename Fmt = radix::Dec> class IntegerToString { - static_assert(cpp::is_integral_v<T> || cpp::is_big_int_v<T>); + static_assert(cpp::is_integral_v<T>); LIBC_INLINE static constexpr size_t compute_buffer_size() { constexpr auto MAX_DIGITS = []() -> size_t { @@ -221,8 +208,8 @@ template <typename T, typename Fmt = radix::Dec> class IntegerToString { // An internal stateless structure that handles the number formatting logic. struct IntegerWriter { - static_assert(cpp::is_integral_v<T> || cpp::is_big_int_v<T>); - using UNSIGNED_T = typename details::IntegerWriterUnsigned<T>::type; + static_assert(cpp::is_integral_v<T>); + using UNSIGNED_T = cpp::make_unsigned_t<T>; LIBC_INLINE static char digit_char(uint8_t digit) { if (digit < 10) diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt index 36837c553efce1..4668f0061975f8 100644 --- a/libc/test/UnitTest/CMakeLists.txt +++ b/libc/test/UnitTest/CMakeLists.txt @@ -74,7 +74,6 @@ add_unittest_framework_library( libc.src.__support.CPP.type_traits libc.src.__support.fixed_point.fx_rep libc.src.__support.OSUtil.osutil - libc.src.__support.uint libc.src.__support.uint128 ) diff --git a/libc/test/UnitTest/LibcTest.cpp b/libc/test/UnitTest/LibcTest.cpp index 0340f7ed37100e..7b0e4fca83683b 100644 --- a/libc/test/UnitTest/LibcTest.cpp +++ b/libc/test/UnitTest/LibcTest.cpp @@ -38,8 +38,7 @@ TestLogger &operator<<(TestLogger &logger, Location Loc) { // When the value is UInt128, __uint128_t or wider, show its hexadecimal // digits. template <typename T> -cpp::enable_if_t<(cpp::is_integral_v<T> && (sizeof(T) > sizeof(uint64_t))) || - cpp::is_big_int_v<T>, +cpp::enable_if_t<cpp::is_integral_v<T> && (sizeof(T) > sizeof(uint64_t)), cpp::string> describeValue(T Value) { static_assert(sizeof(T) % 8 == 0, "Unsupported size of UInt"); @@ -48,10 +47,11 @@ describeValue(T Value) { } // When the value is of a standard integral type, just display it as normal. -template <typename T> -cpp::enable_if_t<cpp::is_integral_v<T> && (sizeof(T) <= sizeof(uint64_t)), +template <typename ValType> +cpp::enable_if_t<cpp::is_integral_v<ValType> && + sizeof(ValType) <= sizeof(uint64_t), cpp::string> -describeValue(T Value) { +describeValue(ValType Value) { return cpp::to_string(Value); } diff --git a/libc/test/UnitTest/LibcTest.h b/libc/test/UnitTest/LibcTest.h index d26d6490bcb572..639f6005832576 100644 --- a/libc/test/UnitTest/LibcTest.h +++ b/libc/test/UnitTest/LibcTest.h @@ -127,7 +127,6 @@ class Test { // of type promotion. template <typename ValType, cpp::enable_if_t<cpp::is_integral_v<ValType> || - cpp::is_big_int_v<ValType> || cpp::is_fixed_point_v<ValType>, int> = 0> bool test(TestCond Cond, ValType LHS, ValType RHS, const char *LHSStr, diff --git a/libc/test/UnitTest/TestLogger.cpp b/libc/test/UnitTest/TestLogger.cpp index 469b3a11d57d9b..6bb0e17dc3888e 100644 --- a/libc/test/UnitTest/TestLogger.cpp +++ b/libc/test/UnitTest/TestLogger.cpp @@ -2,7 +2,6 @@ #include "src/__support/CPP/string.h" #include "src/__support/CPP/string_view.h" #include "src/__support/OSUtil/io.h" // write_to_stderr -#include "src/__support/UInt.h" // is_big_int #include "src/__support/UInt128.h" #include <stdint.h> @@ -48,9 +47,8 @@ template <> TestLogger &TestLogger::operator<<(void *addr) { } template <typename T> TestLogger &TestLogger::operator<<(T t) { - if constexpr (cpp::is_big_int_v<T> || - (cpp::is_integral_v<T> && cpp::is_unsigned_v<T> && - (sizeof(T) > sizeof(uint64_t)))) { + if constexpr (cpp::is_integral_v<T> && cpp::is_unsigned_v<T> && + sizeof(T) > sizeof(uint64_t)) { static_assert(sizeof(T) % 8 == 0, "Unsupported size of UInt"); const IntegerToString<T, radix::Hex::WithPrefix> buffer(t); return *this << buffer.view(); @@ -70,7 +68,7 @@ template TestLogger &TestLogger::operator<< <unsigned short>(unsigned short); template TestLogger &TestLogger::operator<< <unsigned int>(unsigned int); template TestLogger &TestLogger::operator<< <unsigned long>(unsigned long); template TestLogger & - TestLogger::operator<< <unsigned long long>(unsigned long long); +TestLogger::operator<< <unsigned long long>(unsigned long long); #ifdef __SIZEOF_INT128__ template TestLogger &TestLogger::operator<< <__uint128_t>(__uint128_t); diff --git a/libc/test/src/__support/CPP/bit_test.cpp b/libc/test/src/__support/CPP/bit_test.cpp index 1e3d895e6453a7..115a5d505c4b7a 100644 --- a/libc/test/src/__support/CPP/bit_test.cpp +++ b/libc/test/src/__support/CPP/bit_test.cpp @@ -12,44 +12,21 @@ #include <stdint.h> -#include <iostream> - namespace LIBC_NAMESPACE::cpp { -using UnsignedTypesNoBigInt = testing::TypeList< -#if defined(__SIZEOF_INT128__) - __uint128_t, -#endif - unsigned char, unsigned short, unsigned int, unsigned long, - unsigned long long>; - -using UnsignedTypes = testing::TypeList< +using UnsignedTypes = + testing::TypeList<unsigned char, unsigned short, unsigned int, + unsigned long, unsigned long long, #if defined(__SIZEOF_INT128__) - __uint128_t, + __uint128_t, #endif - unsigned char, unsigned short, unsigned int, unsigned long, - unsigned long long, cpp::UInt<128>>; + cpp::UInt<128>>; TYPED_TEST(LlvmLibcBitTest, HasSingleBit, UnsignedTypes) { - constexpr auto ZERO = T(0); - constexpr auto ALL_ONES = T(~ZERO); - EXPECT_FALSE(has_single_bit<T>(ZERO)); - EXPECT_FALSE(has_single_bit<T>(ALL_ONES)); - + EXPECT_FALSE(has_single_bit<T>(T(0))); + EXPECT_FALSE(has_single_bit<T>(~T(0))); for (T value = 1; value; value <<= 1) EXPECT_TRUE(has_single_bit<T>(value)); - - // We test that if two bits are set has_single_bit returns false. - // We do this by setting the highest or lowest bit depending or where the - // current bit is. This is a bit convoluted but it helps catch a bug on BigInt - // where we have to work on an element-by-element basis. - constexpr auto MIDPOINT = T(ALL_ONES / 2); - constexpr auto LSB = T(1); - constexpr auto MSB = T(~(ALL_ONES >> 1)); - for (T value = 1; value; value <<= 1) { - auto two_bits_value = value | ((value <= MIDPOINT) ? MSB : LSB); - EXPECT_FALSE(has_single_bit<T>(two_bits_value)); - } } TYPED_TEST(LlvmLibcBitTest, CountLZero, UnsignedTypes) { @@ -229,39 +206,39 @@ TEST(LlvmLibcBitTest, Rotr) { rotr<uint64_t>(0x12345678deadbeefULL, -19)); } -TYPED_TEST(LlvmLibcBitTest, FirstLeadingZero, UnsignedTypesNoBigInt) { +TYPED_TEST(LlvmLibcBitTest, FirstLeadingZero, UnsignedTypes) { EXPECT_EQ(first_leading_zero<T>(cpp::numeric_limits<T>::max()), 0); for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) EXPECT_EQ(first_leading_zero<T>(~(T(1) << i)), cpp::numeric_limits<T>::digits - i); } -TYPED_TEST(LlvmLibcBitTest, FirstLeadingOne, UnsignedTypesNoBigInt) { +TYPED_TEST(LlvmLibcBitTest, FirstLeadingOne, UnsignedTypes) { EXPECT_EQ(first_leading_one<T>(static_cast<T>(0)), 0); for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) EXPECT_EQ(first_leading_one<T>(T(1) << i), cpp::numeric_limits<T>::digits - i); } -TYPED_TEST(LlvmLibcBitTest, FirstTrailingZero, UnsignedTypesNoBigInt) { +TYPED_TEST(LlvmLibcBitTest, FirstTrailingZero, UnsignedTypes) { EXPECT_EQ(first_trailing_zero<T>(cpp::numeric_limits<T>::max()), 0); for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) EXPECT_EQ(first_trailing_zero<T>(~(T(1) << i)), i + 1); } -TYPED_TEST(LlvmLibcBitTest, FirstTrailingOne, UnsignedTypesNoBigInt) { +TYPED_TEST(LlvmLibcBitTest, FirstTrailingOne, UnsignedTypes) { EXPECT_EQ(first_trailing_one<T>(cpp::numeric_limits<T>::max()), 0); for (int i = 0U; i != cpp::numeric_limits<T>::digits; ++i) EXPECT_EQ(first_trailing_one<T>(T(1) << i), i + 1); } -TYPED_TEST(LlvmLibcBitTest, CountZeros, UnsignedTypesNoBigInt) { +TYPED_TEST(LlvmLibcBitTest, CountZeros, UnsignedTypes) { EXPECT_EQ(count_zeros(T(0)), cpp::numeric_limits<T>::digits); for (int i = 0; i != cpp::numeric_limits<T>::digits; ++i) EXPECT_EQ(count_zeros<T>(cpp::numeric_limits<T>::max() >> i), i); } -TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypesNoBigInt) { +TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypes) { EXPECT_EQ(count_ones(T(0)), 0); for (int i = 0; i != cpp::numeric_limits<T>::digits; ++i) EXPECT_EQ(count_ones<T>(cpp::numeric_limits<T>::max() >> i), diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 5c6cf761ebe7de..49a454379e1c7a 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -507,7 +507,6 @@ libc_support_library( ":__support_cpp_span", ":__support_cpp_string_view", ":__support_cpp_type_traits", - ":__support_uint", ], ) diff --git a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel index 44692947af7c08..a5c18fbb68b398 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel @@ -18,7 +18,6 @@ libc_support_library( "//libc:__support_cpp_string", "//libc:__support_cpp_string_view", "//libc:__support_osutil_io", - "//libc:__support_uint", "//libc:__support_uint128", ], ) _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits