| author | |
| committer | |
| log | e68a75dabdae364cd50daa11c197ab372149e8a7 |
| tree | 6531b378f56f2bbdd4c17f1101c131be2a0133f2 |
| parent | a585482c352a77d4f4b6cc1ede616adf6db7d7b3 |
| signature |
45 files changed, 1206 insertions(+), 458 deletions(-)
lib/libcxx/libc/hdr/errno_macros.h+1-1| ... | ... | @@ -25,6 +25,6 @@ |
| 25 | 25 | |
| 26 | 26 | #include <errno.h> |
| 27 | 27 | |
| 28 | #endif // LLVM_LIBC_FULL_BUILD | |
| 28 | #endif // LIBC_FULL_BUILD | |
| 29 | 29 | |
| 30 | 30 | #endif // LLVM_LIBC_HDR_ERRNO_MACROS_H |
lib/libcxx/libc/hdr/fenv_macros.h+1-1| ... | ... | @@ -56,6 +56,6 @@ |
| 56 | 56 | #define FE_UPWARD 0x800 |
| 57 | 57 | #endif // FE_UPWARD |
| 58 | 58 | |
| 59 | #endif // LLVM_LIBC_FULL_BUILD | |
| 59 | #endif // LIBC_FULL_BUILD | |
| 60 | 60 | |
| 61 | 61 | #endif // LLVM_LIBC_HDR_FENV_MACROS_H |
lib/libcxx/libc/hdr/float_macros.h+1-1| ... | ... | @@ -17,6 +17,6 @@ |
| 17 | 17 | |
| 18 | 18 | #include <float.h> |
| 19 | 19 | |
| 20 | #endif // LLVM_LIBC_FULL_BUILD | |
| 20 | #endif // LIBC_FULL_BUILD | |
| 21 | 21 | |
| 22 | 22 | #endif // LLVM_LIBC_HDR_FLOAT_MACROS_H |
lib/libcxx/libc/hdr/limits_macros.h+1-1| ... | ... | @@ -17,6 +17,6 @@ |
| 17 | 17 | |
| 18 | 18 | #include <limits.h> |
| 19 | 19 | |
| 20 | #endif // LLVM_LIBC_FULL_BUILD | |
| 20 | #endif // LIBC_FULL_BUILD | |
| 21 | 21 | |
| 22 | 22 | #endif // LLVM_LIBC_HDR_LIMITS_MACROS_H |
lib/libcxx/libc/hdr/types/size_t.h created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | //===-- Proxy for size_t --------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | #ifndef LLVM_LIBC_HDR_TYPES_SIZE_T_H | |
| 9 | #define LLVM_LIBC_HDR_TYPES_SIZE_T_H | |
| 10 | ||
| 11 | #ifdef LIBC_FULL_BUILD | |
| 12 | ||
| 13 | #include "include/llvm-libc-types/size_t.h" | |
| 14 | ||
| 15 | #else | |
| 16 | ||
| 17 | #define __need_size_t | |
| 18 | #include <stddef.h> | |
| 19 | #undef __need_size_t | |
| 20 | ||
| 21 | #endif // LIBC_FULL_BUILD | |
| 22 | ||
| 23 | #endif // LLVM_LIBC_HDR_TYPES_SIZE_T_H |
lib/libcxx/libc/hdr/types/wchar_t.h+1-1| ... | ... | @@ -18,6 +18,6 @@ |
| 18 | 18 | |
| 19 | 19 | #include "hdr/wchar_overlay.h" |
| 20 | 20 | |
| 21 | #endif // LLVM_LIBC_FULL_BUILD | |
| 21 | #endif // LIBC_FULL_BUILD | |
| 22 | 22 | |
| 23 | 23 | #endif // LLVM_LIBC_HDR_TYPES_WCHAR_T_H |
lib/libcxx/libc/hdr/types/wint_t.h created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | //===-- Definition of wint_t.h --------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef LLVM_LIBC_HDR_TYPES_WINT_T_H | |
| 11 | #define LLVM_LIBC_HDR_TYPES_WINT_T_H | |
| 12 | ||
| 13 | #ifdef LIBC_FULL_BUILD | |
| 14 | ||
| 15 | #include "include/llvm-libc-types/wint_t.h" | |
| 16 | ||
| 17 | #else // overlay mode | |
| 18 | ||
| 19 | #include "hdr/wchar_overlay.h" | |
| 20 | ||
| 21 | #endif // LIBC_FULL_BUILD | |
| 22 | ||
| 23 | #endif // LLVM_LIBC_HDR_TYPES_WINT_T_H |
lib/libcxx/libc/include/llvm-libc-macros/cfloat128-macros.h+1-1| ... | ... | @@ -27,7 +27,7 @@ |
| 27 | 27 | #define LIBC_TYPES_HAS_CFLOAT128 |
| 28 | 28 | #endif |
| 29 | 29 | #elif defined(__GNUC__) |
| 30 | #if (defined(__STDC_IEC_60559_COMPLEX__) || defined(__SIZEOF_FLOAT128__)) && \ | |
| 30 | #if (defined(__STDC_IEC_60559_COMPLEX__) && defined(__SIZEOF_FLOAT128__)) && \ | |
| 31 | 31 | (__GNUC__ >= 13 || (!defined(__cplusplus))) |
| 32 | 32 | #define LIBC_TYPES_HAS_CFLOAT128 |
| 33 | 33 | #endif |
lib/libcxx/libc/include/llvm-libc-macros/float-macros.h+6| ... | ... | @@ -9,6 +9,12 @@ |
| 9 | 9 | #ifndef LLVM_LIBC_MACROS_FLOAT_MACROS_H |
| 10 | 10 | #define LLVM_LIBC_MACROS_FLOAT_MACROS_H |
| 11 | 11 | |
| 12 | // __has_builtin is a Clang extension; GCC < 10 doesn't define it, which | |
| 13 | // turns a bare `#if __has_builtin(...)` into a preprocessor syntax error. | |
| 14 | #ifndef __has_builtin | |
| 15 | #define __has_builtin(x) 0 | |
| 16 | #endif | |
| 17 | ||
| 12 | 18 | #ifndef FLT_RADIX |
| 13 | 19 | #define FLT_RADIX __FLT_RADIX__ |
| 14 | 20 | #endif // FLT_RADIX |
lib/libcxx/libc/include/llvm-libc-macros/float16-macros.h+2-1| ... | ... | @@ -12,7 +12,8 @@ |
| 12 | 12 | #include "../llvm-libc-types/float128.h" |
| 13 | 13 | |
| 14 | 14 | #if defined(__FLT16_MANT_DIG__) && \ |
| 15 | (!defined(__GNUC__) || __GNUC__ >= 13 || defined(__clang__)) && \ | |
| 15 | (!defined(__GNUC__) || __GNUC__ >= 13 || \ | |
| 16 | (defined(__clang__) && __clang_major__ >= 12)) && \ | |
| 16 | 17 | !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \ |
| 17 | 18 | !defined(_WIN32) |
| 18 | 19 | #define LIBC_TYPES_HAS_FLOAT16 |
lib/libcxx/libc/include/llvm-libc-macros/stdfix-macros.h+1-1| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | #ifndef LLVM_LIBC_MACROS_STDFIX_MACROS_H |
| 10 | 10 | #define LLVM_LIBC_MACROS_STDFIX_MACROS_H |
| 11 | 11 | |
| 12 | #ifdef __FRACT_FBIT__ | |
| 12 | #if defined(__FRACT_FBIT__) && defined(__clang__) | |
| 13 | 13 | // _Fract and _Accum types are available |
| 14 | 14 | #define LIBC_COMPILER_HAS_FIXED_POINT |
| 15 | 15 | #endif // __FRACT_FBIT__ |
lib/libcxx/libc/include/llvm-libc-types/size_t.h created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | //===-- Definition of size_t types ----------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef LLVM_LIBC_TYPES_SIZE_T_H | |
| 10 | #define LLVM_LIBC_TYPES_SIZE_T_H | |
| 11 | ||
| 12 | typedef __SIZE_TYPE__ size_t; | |
| 13 | ||
| 14 | #endif // LLVM_LIBC_TYPES_SIZE_T_H |
lib/libcxx/libc/src/__support/CPP/bit.h+46-14| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | // |
| 7 | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | // This is inspired by LLVM ADT/bit.h header. |
| 9 | // Some functions are missing, we can add them as needed (popcount, byteswap). | |
| 9 | // Some functions are missing, we can add them as needed. | |
| 10 | 10 | |
| 11 | 11 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H |
| 12 | 12 | #define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H |
| ... | ... | @@ -27,9 +27,14 @@ namespace cpp { |
| 27 | 27 | #endif |
| 28 | 28 | |
| 29 | 29 | template <unsigned N> |
| 30 | LIBC_INLINE static void inline_copy(const char *from, char *to) { | |
| 31 | #if __has_builtin(__builtin_memcpy_inline) | |
| 32 | __builtin_memcpy_inline(to, from, N); | |
| 30 | LIBC_INLINE constexpr void inline_copy(const char *from, char *to) { | |
| 31 | #if __has_builtin(__builtin_memcpy_inline) && \ | |
| 32 | defined(LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED) | |
| 33 | if (cpp::is_constant_evaluated()) | |
| 34 | for (unsigned i = 0; i < N; ++i) | |
| 35 | to[i] = from[i]; | |
| 36 | else | |
| 37 | __builtin_memcpy_inline(to, from, N); | |
| 33 | 38 | #else |
| 34 | 39 | for (unsigned i = 0; i < N; ++i) |
| 35 | 40 | to[i] = from[i]; |
| ... | ... | @@ -39,15 +44,14 @@ LIBC_INLINE static void inline_copy(const char *from, char *to) { |
| 39 | 44 | // This implementation of bit_cast requires trivially-constructible To, to avoid |
| 40 | 45 | // UB in the implementation. |
| 41 | 46 | template <typename To, typename From> |
| 42 | LIBC_INLINE constexpr cpp::enable_if_t< | |
| 47 | LIBC_INLINE static constexpr cpp::enable_if_t< | |
| 43 | 48 | (sizeof(To) == sizeof(From)) && |
| 44 | 49 | cpp::is_trivially_constructible<To>::value && |
| 45 | 50 | cpp::is_trivially_copyable<To>::value && |
| 46 | 51 | cpp::is_trivially_copyable<From>::value, |
| 47 | 52 | To> |
| 48 | 53 | bit_cast(const From &from) { |
| 49 | MSAN_UNPOISON(&from, sizeof(From)); | |
| 50 | #if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC) | |
| 54 | #if LIBC_HAS_BUILTIN_BIT_CAST | |
| 51 | 55 | return __builtin_bit_cast(To, from); |
| 52 | 56 | #else |
| 53 | 57 | To to{}; |
| ... | ... | @@ -60,14 +64,12 @@ bit_cast(const From &from) { |
| 60 | 64 | |
| 61 | 65 | // The following simple bit copy from a smaller type to maybe-larger type. |
| 62 | 66 | template <typename To, typename From> |
| 63 | LIBC_INLINE constexpr cpp::enable_if_t< | |
| 64 | (sizeof(To) >= sizeof(From)) && | |
| 65 | cpp::is_trivially_constructible<To>::value && | |
| 66 | cpp::is_trivially_copyable<To>::value && | |
| 67 | cpp::is_trivially_copyable<From>::value, | |
| 68 | void> | |
| 67 | LIBC_INLINE cpp::enable_if_t<(sizeof(To) >= sizeof(From)) && | |
| 68 | cpp::is_trivially_constructible<To>::value && | |
| 69 | cpp::is_trivially_copyable<To>::value && | |
| 70 | cpp::is_trivially_copyable<From>::value, | |
| 71 | void> | |
| 69 | 72 | bit_copy(const From &from, To &to) { |
| 70 | MSAN_UNPOISON(&from, sizeof(From)); | |
| 71 | 73 | char *dst = reinterpret_cast<char *>(&to); |
| 72 | 74 | const char *src = reinterpret_cast<const char *>(&from); |
| 73 | 75 | inline_copy<sizeof(From)>(src, dst); |
| ... | ... | @@ -330,6 +332,36 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) |
| 330 | 332 | #endif // __builtin_popcountg |
| 331 | 333 | #undef ADD_SPECIALIZATION |
| 332 | 334 | |
| 335 | /// Reverses the bytes in the given integer value. | |
| 336 | /// | |
| 337 | /// All integral types are allowed, matching C++23 std::byteswap semantics. | |
| 338 | /// Signed types delegate to the unsigned path via static_cast. | |
| 339 | /// | |
| 340 | /// The recursive decomposition generates optimal 'bswap' or 'rolw' | |
| 341 | /// instructions on Clang at -O2 without requiring compiler intrinsics. | |
| 342 | template <typename T> | |
| 343 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_integral_v<T>, T> | |
| 344 | byteswap(T value) { | |
| 345 | static_assert(sizeof(T) <= 16, "byteswap: unsupported type size"); | |
| 346 | if constexpr (!cpp::is_unsigned_v<T>) { | |
| 347 | using U = cpp::make_unsigned_t<T>; | |
| 348 | return static_cast<T>(byteswap(static_cast<U>(value))); | |
| 349 | } else if constexpr (sizeof(T) == 1) { | |
| 350 | return value; | |
| 351 | } else { | |
| 352 | constexpr unsigned half_bits = sizeof(T) * 8 / 2; | |
| 353 | using Half = cpp::conditional_t< | |
| 354 | sizeof(T) == 2, uint8_t, | |
| 355 | cpp::conditional_t< | |
| 356 | sizeof(T) == 4, uint16_t, | |
| 357 | cpp::conditional_t<sizeof(T) == 8, uint32_t, uint64_t>>>; | |
| 358 | Half lo = static_cast<Half>(value); | |
| 359 | Half hi = static_cast<Half>(value >> half_bits); | |
| 360 | return static_cast<T>((static_cast<T>(byteswap(lo)) << half_bits) | | |
| 361 | static_cast<T>(byteswap(hi))); | |
| 362 | } | |
| 363 | } | |
| 364 | ||
| 333 | 365 | } // namespace cpp |
| 334 | 366 | } // namespace LIBC_NAMESPACE_DECL |
| 335 | 367 |
lib/libcxx/libc/src/__support/CPP/iterator.h+29| ... | ... | @@ -9,6 +9,7 @@ |
| 9 | 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H |
| 10 | 10 | #define LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H |
| 11 | 11 | |
| 12 | #include "hdr/types/size_t.h" | |
| 12 | 13 | #include "src/__support/CPP/type_traits/enable_if.h" |
| 13 | 14 | #include "src/__support/CPP/type_traits/is_convertible.h" |
| 14 | 15 | #include "src/__support/CPP/type_traits/is_same.h" |
| ... | ... | @@ -18,9 +19,13 @@ |
| 18 | 19 | namespace LIBC_NAMESPACE_DECL { |
| 19 | 20 | namespace cpp { |
| 20 | 21 | |
| 22 | struct input_iterator_tag {}; | |
| 23 | struct random_access_iterator_tag : input_iterator_tag {}; | |
| 24 | ||
| 21 | 25 | template <typename T> struct iterator_traits; |
| 22 | 26 | template <typename T> struct iterator_traits<T *> { |
| 23 | 27 | using reference = T &; |
| 28 | using iterator_category = random_access_iterator_tag; | |
| 24 | 29 | using value_type = T; |
| 25 | 30 | }; |
| 26 | 31 | |
| ... | ... | @@ -93,6 +98,30 @@ public: |
| 93 | 98 | } |
| 94 | 99 | }; |
| 95 | 100 | |
| 101 | namespace cpp_internal { | |
| 102 | ||
| 103 | template <typename It> | |
| 104 | LIBC_INLINE constexpr size_t distance(It first, It last, | |
| 105 | random_access_iterator_tag) { | |
| 106 | return last - first; | |
| 107 | } | |
| 108 | ||
| 109 | template <typename It> | |
| 110 | LIBC_INLINE constexpr auto distance(It first, It last, input_iterator_tag) { | |
| 111 | size_t n = 0; | |
| 112 | for (; first != last; ++first) { | |
| 113 | ++n; | |
| 114 | } | |
| 115 | return n; | |
| 116 | } | |
| 117 | ||
| 118 | } // namespace cpp_internal | |
| 119 | ||
| 120 | template <typename It> LIBC_INLINE constexpr auto distance(It first, It last) { | |
| 121 | return cpp_internal::distance( | |
| 122 | first, last, typename iterator_traits<It>::iterator_category{}); | |
| 123 | } | |
| 124 | ||
| 96 | 125 | } // namespace cpp |
| 97 | 126 | } // namespace LIBC_NAMESPACE_DECL |
| 98 | 127 |
lib/libcxx/libc/src/__support/CPP/limits.h+26-62| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | //===-- A self contained equivalent of std::limits --------------*- C++ -*-===// | |
| 1 | //===-- A self contained equivalent of <limits> ----------------*- C++ -*-===// | |
| 2 | 2 | // |
| 3 | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | 4 | // See https://llvm.org/LICENSE.txt for license information. |
| ... | ... | @@ -13,78 +13,42 @@ |
| 13 | 13 | #include "src/__support/CPP/type_traits/is_integral.h" |
| 14 | 14 | #include "src/__support/CPP/type_traits/is_signed.h" |
| 15 | 15 | #include "src/__support/macros/attributes.h" // LIBC_INLINE |
| 16 | #include "src/__support/macros/config.h" | |
| 17 | #include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 | |
| 18 | 16 | |
| 19 | 17 | namespace LIBC_NAMESPACE_DECL { |
| 20 | 18 | namespace cpp { |
| 21 | 19 | |
| 22 | 20 | namespace internal { |
| 23 | 21 | |
| 24 | template <typename T, T min_value, T max_value> struct integer_impl { | |
| 25 | static_assert(cpp::is_integral_v<T>); | |
| 26 | LIBC_INLINE static constexpr T max() { return max_value; } | |
| 27 | LIBC_INLINE static constexpr T min() { return min_value; } | |
| 22 | template <typename T, bool is_integral> struct numeric_limits_impl {}; | |
| 23 | ||
| 24 | template <typename T> struct numeric_limits_impl<T, true> { | |
| 25 | LIBC_INLINE_VAR static constexpr bool is_signed = T(-1) < T(0); | |
| 26 | ||
| 28 | 27 | LIBC_INLINE_VAR static constexpr int digits = |
| 29 | CHAR_BIT * sizeof(T) - cpp::is_signed_v<T>; | |
| 28 | (CHAR_BIT * sizeof(T)) - is_signed; | |
| 29 | ||
| 30 | LIBC_INLINE static constexpr T min() { | |
| 31 | if constexpr (is_signed) { | |
| 32 | return T(T(1) << digits); | |
| 33 | } else { | |
| 34 | return 0; | |
| 35 | } | |
| 36 | } | |
| 37 | ||
| 38 | LIBC_INLINE static constexpr T max() { | |
| 39 | if constexpr (is_signed) { | |
| 40 | return T(T(~0) ^ min()); | |
| 41 | } else { | |
| 42 | return T(~0); | |
| 43 | } | |
| 44 | } | |
| 30 | 45 | }; |
| 31 | 46 | |
| 32 | 47 | } // namespace internal |
| 33 | 48 | |
| 34 | template <class T> struct numeric_limits {}; | |
| 35 | ||
| 36 | // TODO: Add numeric_limits specializations as needed for new types. | |
| 37 | template <> | |
| 38 | struct numeric_limits<short> | |
| 39 | : public internal::integer_impl<short, SHRT_MIN, SHRT_MAX> {}; | |
| 40 | ||
| 41 | template <> | |
| 42 | struct numeric_limits<unsigned short> | |
| 43 | : public internal::integer_impl<unsigned short, 0, USHRT_MAX> {}; | |
| 44 | ||
| 45 | template <> | |
| 46 | struct numeric_limits<int> | |
| 47 | : public internal::integer_impl<int, INT_MIN, INT_MAX> {}; | |
| 48 | ||
| 49 | template <> | |
| 50 | struct numeric_limits<unsigned int> | |
| 51 | : public internal::integer_impl<unsigned int, 0, UINT_MAX> {}; | |
| 52 | ||
| 53 | template <> | |
| 54 | struct numeric_limits<long> | |
| 55 | : public internal::integer_impl<long, LONG_MIN, LONG_MAX> {}; | |
| 56 | ||
| 57 | template <> | |
| 58 | struct numeric_limits<unsigned long> | |
| 59 | : public internal::integer_impl<unsigned long, 0, ULONG_MAX> {}; | |
| 60 | ||
| 61 | template <> | |
| 62 | struct numeric_limits<long long> | |
| 63 | : public internal::integer_impl<long long, LLONG_MIN, LLONG_MAX> {}; | |
| 64 | ||
| 65 | template <> | |
| 66 | struct numeric_limits<unsigned long long> | |
| 67 | : public internal::integer_impl<unsigned long long, 0, ULLONG_MAX> {}; | |
| 68 | ||
| 69 | template <> | |
| 70 | struct numeric_limits<char> | |
| 71 | : public internal::integer_impl<char, CHAR_MIN, CHAR_MAX> {}; | |
| 72 | ||
| 73 | template <> | |
| 74 | struct numeric_limits<signed char> | |
| 75 | : public internal::integer_impl<signed char, SCHAR_MIN, SCHAR_MAX> {}; | |
| 76 | ||
| 77 | template <> | |
| 78 | struct numeric_limits<unsigned char> | |
| 79 | : public internal::integer_impl<unsigned char, 0, UCHAR_MAX> {}; | |
| 80 | ||
| 81 | #ifdef LIBC_TYPES_HAS_INT128 | |
| 82 | // On platform where UInt128 resolves to __uint128_t, this specialization | |
| 83 | // provides the limits of UInt128. | |
| 84 | template <> | |
| 85 | struct numeric_limits<__uint128_t> | |
| 86 | : public internal::integer_impl<__uint128_t, 0, ~__uint128_t(0)> {}; | |
| 87 | #endif | |
| 49 | template <typename T> | |
| 50 | struct numeric_limits | |
| 51 | : public internal::numeric_limits_impl<T, is_integral_v<T>> {}; | |
| 88 | 52 | |
| 89 | 53 | } // namespace cpp |
| 90 | 54 | } // namespace LIBC_NAMESPACE_DECL |
lib/libcxx/libc/src/__support/CPP/string_view.h+79-62| ... | ... | @@ -18,46 +18,52 @@ |
| 18 | 18 | namespace LIBC_NAMESPACE_DECL { |
| 19 | 19 | namespace cpp { |
| 20 | 20 | |
| 21 | // This is very simple alternate of the std::string_view class. There is no | |
| 22 | // bounds check performed in any of the methods. The callers are expected to | |
| 23 | // do the checks before invoking the methods. | |
| 21 | template <typename CharT> class basic_string_view; | |
| 22 | ||
| 23 | using string_view = basic_string_view<char>; | |
| 24 | using wstring_view = basic_string_view<wchar_t>; | |
| 25 | ||
| 26 | // This is a very simple alternate of the std::basic_string_view class template. | |
| 27 | // There is no bounds check performed in any of the methods. The callers are | |
| 28 | // expected to do the checks before invoking the methods. | |
| 24 | 29 | // |
| 25 | 30 | // This class will be extended as needed in future. |
| 26 | class string_view { | |
| 31 | template <typename CharT> class basic_string_view { | |
| 27 | 32 | private: |
| 28 | const char *Data; | |
| 33 | const CharT *Data; | |
| 29 | 34 | size_t Len; |
| 30 | 35 | |
| 31 | LIBC_INLINE static size_t min(size_t A, size_t B) { return A <= B ? A : B; } | |
| 36 | LIBC_INLINE static constexpr size_t min(size_t A, size_t B) { | |
| 37 | return A <= B ? A : B; | |
| 38 | } | |
| 32 | 39 | |
| 33 | LIBC_INLINE static int compareMemory(const char *Lhs, const char *Rhs, | |
| 34 | size_t Length) { | |
| 40 | LIBC_INLINE static constexpr int compareN(const CharT *Lhs, const CharT *Rhs, | |
| 41 | size_t Length) { | |
| 35 | 42 | for (size_t i = 0; i < Length; ++i) |
| 36 | if (int Diff = (int)Lhs[i] - (int)Rhs[i]) | |
| 37 | return Diff; | |
| 43 | if (Lhs[i] != Rhs[i]) | |
| 44 | return Lhs[i] < Rhs[i] ? -1 : 1; | |
| 38 | 45 | return 0; |
| 39 | 46 | } |
| 40 | 47 | |
| 41 | LIBC_INLINE static constexpr size_t length(const char *Str) { | |
| 42 | for (const char *End = Str;; ++End) | |
| 43 | if (*End == '\0') | |
| 48 | LIBC_INLINE static constexpr size_t length(const CharT *Str) { | |
| 49 | for (const CharT *End = Str;; ++End) | |
| 50 | if (*End == CharT{0}) | |
| 44 | 51 | return static_cast<size_t>(End - Str); |
| 45 | 52 | } |
| 46 | 53 | |
| 47 | LIBC_INLINE bool equals(string_view Other) const { | |
| 48 | return (Len == Other.Len && | |
| 49 | compareMemory(Data, Other.Data, Other.Len) == 0); | |
| 54 | LIBC_INLINE constexpr bool equals(basic_string_view Other) const { | |
| 55 | return (Len == Other.Len && compareN(Data, Other.Data, Other.Len) == 0); | |
| 50 | 56 | } |
| 51 | 57 | |
| 52 | 58 | public: |
| 53 | using value_type = char; | |
| 59 | using value_type = CharT; | |
| 54 | 60 | using size_type = size_t; |
| 55 | 61 | using difference_type = ptrdiff_t; |
| 56 | using pointer = char *; | |
| 57 | using const_pointer = const char *; | |
| 58 | using reference = char &; | |
| 59 | using const_reference = const char &; | |
| 60 | using const_iterator = char *; | |
| 62 | using pointer = CharT *; | |
| 63 | using const_pointer = const CharT *; | |
| 64 | using reference = CharT &; | |
| 65 | using const_reference = const CharT &; | |
| 66 | using const_iterator = CharT *; | |
| 61 | 67 | using iterator = const_iterator; |
| 62 | 68 | |
| 63 | 69 | // special value equal to the maximum value representable by the type |
| ... | ... | @@ -65,124 +71,126 @@ public: |
| 65 | 71 | LIBC_INLINE_VAR static constexpr size_t npos = |
| 66 | 72 | cpp::numeric_limits<size_t>::max(); |
| 67 | 73 | |
| 68 | LIBC_INLINE constexpr string_view() : Data(nullptr), Len(0) {} | |
| 74 | LIBC_INLINE constexpr basic_string_view() : Data(nullptr), Len(0) {} | |
| 69 | 75 | |
| 70 | 76 | // Assumes Str is a null-terminated string. The length of the string does |
| 71 | 77 | // not include the terminating null character. |
| 72 | 78 | // Preconditions: [Str, Str + ​length(Str)) is a valid range. |
| 73 | LIBC_INLINE constexpr string_view(const char *Str) | |
| 79 | LIBC_INLINE constexpr basic_string_view(const CharT *Str) | |
| 74 | 80 | : Data(Str), Len(length(Str)) {} |
| 75 | 81 | |
| 76 | 82 | // Preconditions: [Str, Str + N) is a valid range. |
| 77 | LIBC_INLINE constexpr string_view(const char *Str, size_t N) | |
| 83 | LIBC_INLINE constexpr basic_string_view(const CharT *Str, size_t N) | |
| 78 | 84 | : Data(Str), Len(N) {} |
| 79 | 85 | |
| 80 | LIBC_INLINE constexpr const char *data() const { return Data; } | |
| 86 | LIBC_INLINE constexpr const CharT *data() const { return Data; } | |
| 81 | 87 | |
| 82 | // Returns the size of the string_view. | |
| 88 | // Returns the size of the basic_string_view. | |
| 83 | 89 | LIBC_INLINE constexpr size_t size() const { return Len; } |
| 84 | 90 | |
| 85 | // Returns whether the string_view is empty. | |
| 91 | // Returns whether the basic_string_view is empty. | |
| 86 | 92 | LIBC_INLINE constexpr bool empty() const { return Len == 0; } |
| 87 | 93 | |
| 88 | 94 | // Returns an iterator to the first character of the view. |
| 89 | LIBC_INLINE const char *begin() const { return Data; } | |
| 95 | LIBC_INLINE constexpr const CharT *begin() const { return Data; } | |
| 90 | 96 | |
| 91 | 97 | // Returns an iterator to the character following the last character of the |
| 92 | 98 | // view. |
| 93 | LIBC_INLINE const char *end() const { return Data + Len; } | |
| 99 | LIBC_INLINE constexpr const CharT *end() const { return Data + Len; } | |
| 94 | 100 | |
| 95 | 101 | // Returns a const reference to the character at specified location pos. |
| 96 | 102 | // No bounds checking is performed: the behavior is undefined if pos >= |
| 97 | 103 | // size(). |
| 98 | LIBC_INLINE constexpr const char &operator[](size_t Index) const { | |
| 104 | LIBC_INLINE constexpr const CharT &operator[](size_t Index) const { | |
| 99 | 105 | return Data[Index]; |
| 100 | 106 | } |
| 101 | 107 | |
| 102 | 108 | /// compare - Compare two strings; the result is -1, 0, or 1 if this string |
| 103 | 109 | /// is lexicographically less than, equal to, or greater than the \p Other. |
| 104 | LIBC_INLINE int compare(string_view Other) const { | |
| 110 | LIBC_INLINE constexpr int compare(basic_string_view Other) const { | |
| 105 | 111 | // Check the prefix for a mismatch. |
| 106 | if (int Res = compareMemory(Data, Other.Data, min(Len, Other.Len))) | |
| 107 | return Res < 0 ? -1 : 1; | |
| 112 | if (int Res = compareN(Data, Other.Data, min(Len, Other.Len))) | |
| 113 | return Res; | |
| 108 | 114 | // Otherwise the prefixes match, so we only need to check the lengths. |
| 109 | 115 | if (Len == Other.Len) |
| 110 | 116 | return 0; |
| 111 | 117 | return Len < Other.Len ? -1 : 1; |
| 112 | 118 | } |
| 113 | 119 | |
| 114 | LIBC_INLINE bool operator==(string_view Other) const { return equals(Other); } | |
| 115 | LIBC_INLINE bool operator!=(string_view Other) const { | |
| 120 | LIBC_INLINE constexpr bool operator==(basic_string_view Other) const { | |
| 121 | return equals(Other); | |
| 122 | } | |
| 123 | LIBC_INLINE constexpr bool operator!=(basic_string_view Other) const { | |
| 116 | 124 | return !(*this == Other); |
| 117 | 125 | } |
| 118 | LIBC_INLINE bool operator<(string_view Other) const { | |
| 126 | LIBC_INLINE constexpr bool operator<(basic_string_view Other) const { | |
| 119 | 127 | return compare(Other) == -1; |
| 120 | 128 | } |
| 121 | LIBC_INLINE bool operator<=(string_view Other) const { | |
| 129 | LIBC_INLINE constexpr bool operator<=(basic_string_view Other) const { | |
| 122 | 130 | return compare(Other) != 1; |
| 123 | 131 | } |
| 124 | LIBC_INLINE bool operator>(string_view Other) const { | |
| 132 | LIBC_INLINE constexpr bool operator>(basic_string_view Other) const { | |
| 125 | 133 | return compare(Other) == 1; |
| 126 | 134 | } |
| 127 | LIBC_INLINE bool operator>=(string_view Other) const { | |
| 135 | LIBC_INLINE constexpr bool operator>=(basic_string_view Other) const { | |
| 128 | 136 | return compare(Other) != -1; |
| 129 | 137 | } |
| 130 | 138 | |
| 131 | 139 | // Moves the start of the view forward by n characters. |
| 132 | 140 | // The behavior is undefined if n > size(). |
| 133 | LIBC_INLINE void remove_prefix(size_t N) { | |
| 141 | LIBC_INLINE constexpr void remove_prefix(size_t N) { | |
| 134 | 142 | Len -= N; |
| 135 | 143 | Data += N; |
| 136 | 144 | } |
| 137 | 145 | |
| 138 | 146 | // Moves the end of the view back by n characters. |
| 139 | 147 | // The behavior is undefined if n > size(). |
| 140 | LIBC_INLINE void remove_suffix(size_t N) { Len -= N; } | |
| 148 | LIBC_INLINE constexpr void remove_suffix(size_t N) { Len -= N; } | |
| 141 | 149 | |
| 142 | 150 | // Check if this string starts with the given Prefix. |
| 143 | LIBC_INLINE bool starts_with(string_view Prefix) const { | |
| 144 | return Len >= Prefix.Len && | |
| 145 | compareMemory(Data, Prefix.Data, Prefix.Len) == 0; | |
| 151 | LIBC_INLINE constexpr bool starts_with(basic_string_view Prefix) const { | |
| 152 | return Len >= Prefix.Len && compareN(Data, Prefix.Data, Prefix.Len) == 0; | |
| 146 | 153 | } |
| 147 | 154 | |
| 148 | 155 | // Check if this string starts with the given Prefix. |
| 149 | LIBC_INLINE bool starts_with(const char Prefix) const { | |
| 156 | LIBC_INLINE constexpr bool starts_with(const CharT Prefix) const { | |
| 150 | 157 | return !empty() && front() == Prefix; |
| 151 | 158 | } |
| 152 | 159 | |
| 153 | 160 | // Check if this string ends with the given Prefix. |
| 154 | LIBC_INLINE bool ends_with(const char Suffix) const { | |
| 161 | LIBC_INLINE constexpr bool ends_with(const CharT Suffix) const { | |
| 155 | 162 | return !empty() && back() == Suffix; |
| 156 | 163 | } |
| 157 | 164 | |
| 158 | 165 | // Check if this string ends with the given Suffix. |
| 159 | LIBC_INLINE bool ends_with(string_view Suffix) const { | |
| 166 | LIBC_INLINE constexpr bool ends_with(basic_string_view Suffix) const { | |
| 160 | 167 | return Len >= Suffix.Len && |
| 161 | compareMemory(end() - Suffix.Len, Suffix.Data, Suffix.Len) == 0; | |
| 168 | compareN(end() - Suffix.Len, Suffix.Data, Suffix.Len) == 0; | |
| 162 | 169 | } |
| 163 | 170 | |
| 164 | 171 | // Return a reference to the substring from [Start, Start + N). |
| 165 | 172 | // |
| 166 | // Start The index of the starting character in the substring; if the index is | |
| 167 | // npos or greater than the length of the string then the empty substring will | |
| 168 | // be returned. | |
| 173 | // Start The index of the starting character in the substring; if the index | |
| 174 | // is npos or greater than the length of the string then the empty substring | |
| 175 | // will be returned. | |
| 169 | 176 | // |
| 170 | 177 | // N The number of characters to included in the substring. If N exceeds the |
| 171 | 178 | // number of characters remaining in the string, the string suffix (starting |
| 172 | 179 | // with Start) will be returned. |
| 173 | LIBC_INLINE string_view substr(size_t Start, size_t N = npos) const { | |
| 180 | LIBC_INLINE constexpr basic_string_view substr(size_t Start, | |
| 181 | size_t N = npos) const { | |
| 174 | 182 | Start = min(Start, Len); |
| 175 | return string_view(Data + Start, min(N, Len - Start)); | |
| 183 | return basic_string_view(Data + Start, min(N, Len - Start)); | |
| 176 | 184 | } |
| 177 | 185 | |
| 178 | 186 | // front - Get the first character in the string. |
| 179 | LIBC_INLINE char front() const { return Data[0]; } | |
| 187 | LIBC_INLINE constexpr CharT front() const { return Data[0]; } | |
| 180 | 188 | |
| 181 | 189 | // back - Get the last character in the string. |
| 182 | LIBC_INLINE char back() const { return Data[Len - 1]; } | |
| 190 | LIBC_INLINE constexpr CharT back() const { return Data[Len - 1]; } | |
| 183 | 191 | |
| 184 | 192 | // Finds the first occurence of c in this view, starting at position From. |
| 185 | LIBC_INLINE constexpr size_t find_first_of(const char c, | |
| 193 | LIBC_INLINE constexpr size_t find_first_of(const CharT c, | |
| 186 | 194 | size_t From = 0) const { |
| 187 | 195 | for (size_t Pos = From; Pos < size(); ++Pos) |
| 188 | 196 | if ((*this)[Pos] == c) |
| ... | ... | @@ -191,7 +199,7 @@ public: |
| 191 | 199 | } |
| 192 | 200 | |
| 193 | 201 | // Finds the last occurence of c in this view, ending at position End. |
| 194 | LIBC_INLINE constexpr size_t find_last_of(const char c, | |
| 202 | LIBC_INLINE constexpr size_t find_last_of(const CharT c, | |
| 195 | 203 | size_t End = npos) const { |
| 196 | 204 | End = End >= size() ? size() : End + 1; |
| 197 | 205 | for (; End > 0; --End) |
| ... | ... | @@ -200,9 +208,18 @@ public: |
| 200 | 208 | return npos; |
| 201 | 209 | } |
| 202 | 210 | |
| 203 | // Finds the first character not equal to c in this view, starting at position | |
| 204 | // From. | |
| 205 | LIBC_INLINE constexpr size_t find_first_not_of(const char c, | |
| 211 | LIBC_INLINE constexpr size_t find_last_not_of(const char c, | |
| 212 | size_t end = npos) const { | |
| 213 | end = end >= size() ? size() : end + 1; | |
| 214 | for (; end > 0; --end) | |
| 215 | if ((*this)[end - 1] != c) | |
| 216 | return end - 1; | |
| 217 | return npos; | |
| 218 | } | |
| 219 | ||
| 220 | // Finds the first character not equal to c in this view, starting at | |
| 221 | // position From. | |
| 222 | LIBC_INLINE constexpr size_t find_first_not_of(const CharT c, | |
| 206 | 223 | size_t From = 0) const { |
| 207 | 224 | for (size_t Pos = From; Pos < size(); ++Pos) |
| 208 | 225 | if ((*this)[Pos] != c) |
| ... | ... | @@ -211,7 +228,7 @@ public: |
| 211 | 228 | } |
| 212 | 229 | |
| 213 | 230 | // Check if this view contains the given character. |
| 214 | LIBC_INLINE constexpr bool contains(char c) const { | |
| 231 | LIBC_INLINE constexpr bool contains(CharT c) const { | |
| 215 | 232 | return find_first_of(c) != npos; |
| 216 | 233 | } |
| 217 | 234 | }; |
lib/libcxx/libc/src/__support/CPP/type_traits/is_assignable.h created+63| ... | ... | @@ -0,0 +1,63 @@ |
| 1 | //===------------------------------------------------------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // \file | |
| 10 | // This file contains a free-standing implementation of is_assignable | |
| 11 | // type trait. | |
| 12 | // | |
| 13 | //===----------------------------------------------------------------------===// | |
| 14 | ||
| 15 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ASSIGNABLE_H | |
| 16 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ASSIGNABLE_H | |
| 17 | ||
| 18 | #include "src/__support/CPP/type_traits/bool_constant.h" | |
| 19 | #include "src/__support/CPP/utility/declval.h" | |
| 20 | #include "src/__support/macros/attributes.h" | |
| 21 | #include "src/__support/macros/config.h" | |
| 22 | ||
| 23 | namespace LIBC_NAMESPACE_DECL { | |
| 24 | namespace cpp { | |
| 25 | ||
| 26 | namespace is_assignable_detail { | |
| 27 | ||
| 28 | #if LIBC_HAS_BUILTIN_IS_ASSIGNABLE | |
| 29 | ||
| 30 | template <typename T, typename U> | |
| 31 | struct is_assignable_impl : public bool_constant<__is_assignable(T, U)> {}; | |
| 32 | ||
| 33 | #else | |
| 34 | // Fallback SFINAE implementation for GCC 7 and older toolchains | |
| 35 | ||
| 36 | template <typename T, typename U> struct is_assignable_impl { | |
| 37 | private: | |
| 38 | template <typename T1, typename U1> | |
| 39 | LIBC_INLINE static auto test(int) | |
| 40 | -> decltype(declval<T1>() = declval<U1>(), bool_constant<true>()); | |
| 41 | ||
| 42 | template <typename, typename> | |
| 43 | LIBC_INLINE static auto test(...) -> bool_constant<false>; | |
| 44 | ||
| 45 | public: | |
| 46 | using type = decltype(test<T, U>(0)); | |
| 47 | }; | |
| 48 | ||
| 49 | #endif // LIBC_HAS_BUILTIN_IS_ASSIGNABLE | |
| 50 | ||
| 51 | } // namespace is_assignable_detail | |
| 52 | ||
| 53 | // is_assignable | |
| 54 | template <typename T, typename U> | |
| 55 | struct is_assignable : public is_assignable_detail::is_assignable_impl<T, U> {}; | |
| 56 | ||
| 57 | template <typename T, typename U> | |
| 58 | LIBC_INLINE_VAR constexpr bool is_assignable_v = is_assignable<T, U>::value; | |
| 59 | ||
| 60 | } // namespace cpp | |
| 61 | } // namespace LIBC_NAMESPACE_DECL | |
| 62 | ||
| 63 | #endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ASSIGNABLE_H |
lib/libcxx/libc/src/__support/CPP/type_traits/is_constant_evaluated.h+4| ... | ... | @@ -15,7 +15,11 @@ namespace LIBC_NAMESPACE_DECL { |
| 15 | 15 | namespace cpp { |
| 16 | 16 | |
| 17 | 17 | LIBC_INLINE constexpr bool is_constant_evaluated() { |
| 18 | #if LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED | |
| 18 | 19 | return __builtin_is_constant_evaluated(); |
| 20 | #else | |
| 21 | return false; | |
| 22 | #endif | |
| 19 | 23 | } |
| 20 | 24 | |
| 21 | 25 | } // namespace cpp |
lib/libcxx/libc/src/__support/CPP/type_traits/is_constructible.h created+65| ... | ... | @@ -0,0 +1,65 @@ |
| 1 | //===------------------------------------------------------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // | |
| 9 | // \file | |
| 10 | // This file contains a free-standing implementation of is_constructible | |
| 11 | // type trait. | |
| 12 | // | |
| 13 | //===----------------------------------------------------------------------===// | |
| 14 | ||
| 15 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTRUCTIBLE_H | |
| 16 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTRUCTIBLE_H | |
| 17 | ||
| 18 | #include "src/__support/CPP/type_traits/bool_constant.h" | |
| 19 | #include "src/__support/CPP/utility/declval.h" | |
| 20 | #include "src/__support/macros/attributes.h" | |
| 21 | #include "src/__support/macros/config.h" | |
| 22 | ||
| 23 | namespace LIBC_NAMESPACE_DECL { | |
| 24 | namespace cpp { | |
| 25 | ||
| 26 | namespace is_contructible_detail { | |
| 27 | ||
| 28 | #if LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE | |
| 29 | ||
| 30 | template <typename T, typename... Args> | |
| 31 | struct is_constructible_impl | |
| 32 | : public bool_constant<__is_constructible(T, Args...)> {}; | |
| 33 | ||
| 34 | #else | |
| 35 | // Fallback SFINAE implementation for GCC 7 and older toolchains | |
| 36 | ||
| 37 | template <typename T, typename... Args> struct is_constructible_impl { | |
| 38 | private: | |
| 39 | template <typename T1, typename... Args1> | |
| 40 | LIBC_INLINE static auto test(int) | |
| 41 | -> decltype(T1(declval<Args1>()...), bool_constant<true>()); | |
| 42 | ||
| 43 | template <typename, typename...> | |
| 44 | LIBC_INLINE static auto test(...) -> bool_constant<false>; | |
| 45 | ||
| 46 | public: | |
| 47 | using type = decltype(test<T, Args...>(0)); | |
| 48 | }; | |
| 49 | ||
| 50 | #endif // LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE | |
| 51 | ||
| 52 | } // namespace is_contructible_detail | |
| 53 | ||
| 54 | template <typename T, typename... Args> | |
| 55 | struct is_constructible | |
| 56 | : public is_contructible_detail::is_constructible_impl<T, Args...> {}; | |
| 57 | ||
| 58 | template <typename T, typename... Args> | |
| 59 | LIBC_INLINE_VAR constexpr bool is_constructible_v = | |
| 60 | is_constructible<T, Args...>::value; | |
| 61 | ||
| 62 | } // namespace cpp | |
| 63 | } // namespace LIBC_NAMESPACE_DECL | |
| 64 | ||
| 65 | #endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTRUCTIBLE_H |
lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_assignable.h+3-4| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_ASSIGNABLE_H |
| 10 | 10 | |
| 11 | 11 | #include "src/__support/CPP/type_traits/add_lvalue_reference.h" |
| 12 | #include "src/__support/CPP/type_traits/integral_constant.h" | |
| 12 | #include "src/__support/CPP/type_traits/is_assignable.h" | |
| 13 | 13 | #include "src/__support/macros/config.h" |
| 14 | 14 | |
| 15 | 15 | namespace LIBC_NAMESPACE_DECL { |
| ... | ... | @@ -18,9 +18,8 @@ namespace cpp { |
| 18 | 18 | // is copy assignable |
| 19 | 19 | template <class T> |
| 20 | 20 | struct is_copy_assignable |
| 21 | : public integral_constant< | |
| 22 | bool, __is_assignable(cpp::add_lvalue_reference_t<T>, | |
| 23 | cpp::add_lvalue_reference_t<const T>)> {}; | |
| 21 | : public cpp::is_assignable<cpp::add_lvalue_reference_t<T>, | |
| 22 | cpp::add_lvalue_reference_t<const T>> {}; | |
| 24 | 23 | |
| 25 | 24 | template <class T> |
| 26 | 25 | LIBC_INLINE_VAR constexpr bool is_copy_assignable_v = |
lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_constructible.h+2-3| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_CONSTRUCTIBLE_H |
| 10 | 10 | |
| 11 | 11 | #include "src/__support/CPP/type_traits/add_lvalue_reference.h" |
| 12 | #include "src/__support/CPP/type_traits/integral_constant.h" | |
| 12 | #include "src/__support/CPP/type_traits/is_constructible.h" | |
| 13 | 13 | #include "src/__support/macros/config.h" |
| 14 | 14 | |
| 15 | 15 | namespace LIBC_NAMESPACE_DECL { |
| ... | ... | @@ -18,8 +18,7 @@ namespace cpp { |
| 18 | 18 | // is copy constructible |
| 19 | 19 | template <class T> |
| 20 | 20 | struct is_copy_constructible |
| 21 | : public integral_constant< | |
| 22 | bool, __is_constructible(T, cpp::add_lvalue_reference_t<const T>)> {}; | |
| 21 | : public cpp::is_constructible<T, cpp::add_lvalue_reference_t<const T>> {}; | |
| 23 | 22 | |
| 24 | 23 | template <class T> |
| 25 | 24 | LIBC_INLINE_VAR constexpr bool is_copy_constructible_v = |
lib/libcxx/libc/src/__support/CPP/type_traits/is_integral.h+10-5| ... | ... | @@ -26,13 +26,18 @@ private: |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | public: |
| 29 | LIBC_INLINE_VAR static constexpr bool value = __is_unqualified_any_of< | |
| 30 | T, | |
| 29 | LIBC_INLINE_VAR static constexpr bool value = | |
| 30 | __is_unqualified_any_of<T, | |
| 31 | 31 | #ifdef LIBC_TYPES_HAS_INT128 |
| 32 | __int128_t, __uint128_t, | |
| 32 | __int128_t, __uint128_t, | |
| 33 | 33 | #endif |
| 34 | char, signed char, unsigned char, short, unsigned short, int, | |
| 35 | unsigned int, long, unsigned long, long long, unsigned long long, bool>(); | |
| 34 | #ifdef __cpp_char8_t | |
| 35 | char8_t, | |
| 36 | #endif | |
| 37 | char16_t, char32_t, wchar_t, char, signed char, | |
| 38 | unsigned char, short, unsigned short, int, | |
| 39 | unsigned int, long, unsigned long, long long, | |
| 40 | unsigned long long, bool>(); | |
| 36 | 41 | }; |
| 37 | 42 | template <typename T> |
| 38 | 43 | LIBC_INLINE_VAR constexpr bool is_integral_v = is_integral<T>::value; |
lib/libcxx/libc/src/__support/CPP/type_traits/is_move_assignable.h+3-4| ... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 | |
| 11 | 11 | #include "src/__support/CPP/type_traits/add_lvalue_reference.h" |
| 12 | 12 | #include "src/__support/CPP/type_traits/add_rvalue_reference.h" |
| 13 | #include "src/__support/CPP/type_traits/integral_constant.h" | |
| 13 | #include "src/__support/CPP/type_traits/is_assignable.h" | |
| 14 | 14 | #include "src/__support/macros/config.h" |
| 15 | 15 | |
| 16 | 16 | namespace LIBC_NAMESPACE_DECL { |
| ... | ... | @@ -19,9 +19,8 @@ namespace cpp { |
| 19 | 19 | // is move assignable |
| 20 | 20 | template <class T> |
| 21 | 21 | struct is_move_assignable |
| 22 | : public integral_constant<bool, __is_assignable( | |
| 23 | cpp::add_lvalue_reference_t<T>, | |
| 24 | cpp::add_rvalue_reference_t<T>)> {}; | |
| 22 | : public cpp::is_assignable<cpp::add_lvalue_reference_t<T>, | |
| 23 | cpp::add_rvalue_reference_t<T>> {}; | |
| 25 | 24 | |
| 26 | 25 | template <class T> |
| 27 | 26 | LIBC_INLINE_VAR constexpr bool is_move_assignable_v = |
lib/libcxx/libc/src/__support/CPP/type_traits/is_move_constructible.h+2-3| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MOVE_CONSTRUCTIBLE_H |
| 10 | 10 | |
| 11 | 11 | #include "src/__support/CPP/type_traits/add_rvalue_reference.h" |
| 12 | #include "src/__support/CPP/type_traits/integral_constant.h" | |
| 12 | #include "src/__support/CPP/type_traits/is_constructible.h" | |
| 13 | 13 | #include "src/__support/macros/config.h" |
| 14 | 14 | |
| 15 | 15 | namespace LIBC_NAMESPACE_DECL { |
| ... | ... | @@ -18,8 +18,7 @@ namespace cpp { |
| 18 | 18 | // is move constructible |
| 19 | 19 | template <class T> |
| 20 | 20 | struct is_move_constructible |
| 21 | : public integral_constant<bool, __is_constructible( | |
| 22 | T, cpp::add_rvalue_reference_t<T>)> {}; | |
| 21 | : public cpp::is_constructible<T, cpp::add_rvalue_reference_t<T>> {}; | |
| 23 | 22 | |
| 24 | 23 | template <class T> |
| 25 | 24 | LIBC_INLINE_VAR constexpr bool is_move_constructible_v = |
lib/libcxx/libc/src/__support/CPP/type_traits/is_unsigned.h+3-3| ... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 | |
| 11 | 11 | #include "include/llvm-libc-macros/stdfix-macros.h" |
| 12 | 12 | #include "src/__support/CPP/type_traits/bool_constant.h" |
| 13 | #include "src/__support/CPP/type_traits/is_arithmetic.h" | |
| 13 | #include "src/__support/CPP/type_traits/is_integral.h" | |
| 14 | 14 | #include "src/__support/CPP/type_traits/is_same.h" |
| 15 | 15 | #include "src/__support/CPP/type_traits/remove_cv.h" |
| 16 | 16 | #include "src/__support/macros/attributes.h" |
| ... | ... | @@ -23,7 +23,7 @@ namespace cpp { |
| 23 | 23 | |
| 24 | 24 | #ifndef LIBC_COMPILER_HAS_FIXED_POINT |
| 25 | 25 | template <typename T> |
| 26 | struct is_unsigned : bool_constant<(is_arithmetic_v<T> && (T(-1) > T(0)))> { | |
| 26 | struct is_unsigned : bool_constant<(is_integral_v<T> && (T(-1) > T(0)))> { | |
| 27 | 27 | LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; } |
| 28 | 28 | LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; } |
| 29 | 29 | }; |
| ... | ... | @@ -37,7 +37,7 @@ private: |
| 37 | 37 | |
| 38 | 38 | public: |
| 39 | 39 | LIBC_INLINE_VAR static constexpr bool value = |
| 40 | (is_arithmetic_v<T> && (T(-1) > T(0))) || | |
| 40 | (is_integral_v<T> && (T(-1) > T(0))) || | |
| 41 | 41 | __is_unqualified_any_of<T, unsigned short fract, unsigned fract, |
| 42 | 42 | unsigned long fract, unsigned short accum, |
| 43 | 43 | unsigned accum, unsigned long accum, |
lib/libcxx/libc/src/__support/FPUtil/FPBits.h+16-13| ... | ... | @@ -798,7 +798,9 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() { |
| 798 | 798 | return FPType::IEEE754_Binary64; |
| 799 | 799 | else if constexpr (LDBL_MANT_DIG == 64) |
| 800 | 800 | return FPType::X86_Binary80; |
| 801 | else if constexpr (LDBL_MANT_DIG == 113) | |
| 801 | // TODO: properly treat double-double type. | |
| 802 | // else if constexpr (LDBL_MANT_DIG == 113) | |
| 803 | else | |
| 802 | 804 | return FPType::IEEE754_Binary128; |
| 803 | 805 | } |
| 804 | 806 | #if defined(LIBC_TYPES_HAS_FLOAT16) |
| ... | ... | @@ -833,21 +835,22 @@ struct FPBits final : public internal::FPRepImpl<get_fp_type<T>(), FPBits<T>> { |
| 833 | 835 | // Constructors. |
| 834 | 836 | LIBC_INLINE constexpr FPBits() = default; |
| 835 | 837 | |
| 836 | template <typename XType> LIBC_INLINE constexpr explicit FPBits(XType x) { | |
| 837 | using Unqual = typename cpp::remove_cv_t<XType>; | |
| 838 | if constexpr (cpp::is_same_v<Unqual, T>) { | |
| 839 | UP::bits = cpp::bit_cast<StorageType>(x); | |
| 840 | } else if constexpr (cpp::is_same_v<Unqual, StorageType>) { | |
| 841 | UP::bits = x; | |
| 842 | } else { | |
| 843 | // We don't want accidental type promotions/conversions, so we require | |
| 844 | // exact type match. | |
| 845 | static_assert(cpp::always_false<XType>); | |
| 846 | } | |
| 838 | template < | |
| 839 | typename XType, | |
| 840 | cpp::enable_if_t<cpp::is_same_v<cpp::remove_cv_t<XType>, T>, int> = 0> | |
| 841 | LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR explicit FPBits(XType x) { | |
| 842 | UP::bits = cpp::bit_cast<StorageType>(x); | |
| 847 | 843 | } |
| 848 | 844 | |
| 845 | template <typename XType, | |
| 846 | cpp::enable_if_t< | |
| 847 | cpp::is_same_v<cpp::remove_cv_t<XType>, StorageType>, int> = 0> | |
| 848 | LIBC_INLINE constexpr explicit FPBits(XType x) : UP(x) {} | |
| 849 | ||
| 849 | 850 | // Floating-point conversions. |
| 850 | LIBC_INLINE constexpr T get_val() const { return cpp::bit_cast<T>(UP::bits); } | |
| 851 | LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR T get_val() const { | |
| 852 | return cpp::bit_cast<T>(UP::bits); | |
| 853 | } | |
| 851 | 854 | }; |
| 852 | 855 | |
| 853 | 856 | } // namespace fputil |
lib/libcxx/libc/src/__support/FPUtil/rounding_mode.h+25-5| ... | ... | @@ -24,8 +24,12 @@ namespace generic { |
| 24 | 24 | // 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO |
| 25 | 25 | // = 0x1.000002f for FE_UPWARD. |
| 26 | 26 | LIBC_INLINE bool fenv_is_round_up() { |
| 27 | #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 28 | return false; | |
| 29 | #else | |
| 27 | 30 | static volatile float x = 0x1.0p-25f; |
| 28 | 31 | return (1.0f + x != 1.0f); |
| 32 | #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 29 | 33 | } |
| 30 | 34 | |
| 31 | 35 | // Quick free-standing test whether fegetround() == FE_DOWNWARD. |
| ... | ... | @@ -33,8 +37,12 @@ LIBC_INLINE bool fenv_is_round_up() { |
| 33 | 37 | // -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO |
| 34 | 38 | // = -0x1.000002f for FE_DOWNWARD. |
| 35 | 39 | LIBC_INLINE bool fenv_is_round_down() { |
| 40 | #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 41 | return false; | |
| 42 | #else | |
| 36 | 43 | static volatile float x = 0x1.0p-25f; |
| 37 | 44 | return (-1.0f - x != -1.0f); |
| 45 | #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 38 | 46 | } |
| 39 | 47 | |
| 40 | 48 | // Quick free-standing test whether fegetround() == FE_TONEAREST. |
| ... | ... | @@ -44,9 +52,13 @@ LIBC_INLINE bool fenv_is_round_down() { |
| 44 | 52 | // 1.5f - 2^-24 = 1.5f for FE_TONEAREST, FE_UPWARD |
| 45 | 53 | // = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO |
| 46 | 54 | LIBC_INLINE bool fenv_is_round_to_nearest() { |
| 55 | #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 56 | return true; | |
| 57 | #else | |
| 47 | 58 | static volatile float x = 0x1.0p-24f; |
| 48 | 59 | float y = 1.5f + x; |
| 49 | 60 | return (y == 1.5f - x); |
| 61 | #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 50 | 62 | } |
| 51 | 63 | |
| 52 | 64 | // Quick free-standing test whether fegetround() == FE_TOWARDZERO. |
| ... | ... | @@ -60,13 +72,20 @@ LIBC_INLINE bool fenv_is_round_to_nearest() { |
| 60 | 72 | // = 2^-22 for FE_TONEAREST, FE_UPWARD |
| 61 | 73 | // = 0 for FE_DOWNWARD |
| 62 | 74 | LIBC_INLINE bool fenv_is_round_to_zero() { |
| 75 | #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 76 | return false; | |
| 77 | #else | |
| 63 | 78 | static volatile float x = 0x1.0p-24f; |
| 64 | 79 | float y = x; |
| 65 | 80 | return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f); |
| 81 | #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 66 | 82 | } |
| 67 | 83 | |
| 68 | 84 | // Quick free standing get rounding mode based on the above observations. |
| 69 | 85 | LIBC_INLINE int quick_get_round() { |
| 86 | #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 87 | return FE_TONEAREST; | |
| 88 | #else | |
| 70 | 89 | static volatile float x = 0x1.0p-24f; |
| 71 | 90 | float y = x; |
| 72 | 91 | float z = (0x1.000002p0f + y) + (-1.0f - y); |
| ... | ... | @@ -76,11 +95,12 @@ LIBC_INLINE int quick_get_round() { |
| 76 | 95 | if (z == 0x1.0p-23f) |
| 77 | 96 | return FE_TOWARDZERO; |
| 78 | 97 | return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD; |
| 98 | #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 79 | 99 | } |
| 80 | 100 | |
| 81 | 101 | } // namespace generic |
| 82 | 102 | |
| 83 | LIBC_INLINE static constexpr bool fenv_is_round_up() { | |
| 103 | LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_up() { | |
| 84 | 104 | if (cpp::is_constant_evaluated()) { |
| 85 | 105 | return false; |
| 86 | 106 | } else { |
| ... | ... | @@ -88,7 +108,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_up() { |
| 88 | 108 | } |
| 89 | 109 | } |
| 90 | 110 | |
| 91 | LIBC_INLINE static constexpr bool fenv_is_round_down() { | |
| 111 | LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_down() { | |
| 92 | 112 | if (cpp::is_constant_evaluated()) { |
| 93 | 113 | return false; |
| 94 | 114 | } else { |
| ... | ... | @@ -96,7 +116,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_down() { |
| 96 | 116 | } |
| 97 | 117 | } |
| 98 | 118 | |
| 99 | LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() { | |
| 119 | LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_to_nearest() { | |
| 100 | 120 | if (cpp::is_constant_evaluated()) { |
| 101 | 121 | return true; |
| 102 | 122 | } else { |
| ... | ... | @@ -104,7 +124,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() { |
| 104 | 124 | } |
| 105 | 125 | } |
| 106 | 126 | |
| 107 | LIBC_INLINE static constexpr bool fenv_is_round_to_zero() { | |
| 127 | LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_to_zero() { | |
| 108 | 128 | if (cpp::is_constant_evaluated()) { |
| 109 | 129 | return false; |
| 110 | 130 | } else { |
| ... | ... | @@ -113,7 +133,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_zero() { |
| 113 | 133 | } |
| 114 | 134 | |
| 115 | 135 | // Quick free standing get rounding mode based on the above observations. |
| 116 | LIBC_INLINE static constexpr int quick_get_round() { | |
| 136 | LIBC_INLINE LIBC_CONSTEXPR_DEFAULT int quick_get_round() { | |
| 117 | 137 | if (cpp::is_constant_evaluated()) { |
| 118 | 138 | return FE_TONEAREST; |
| 119 | 139 | } else { |
lib/libcxx/libc/src/__support/big_int.h+35-49| ... | ... | @@ -242,10 +242,9 @@ LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst, |
| 242 | 242 | |
| 243 | 243 | template <typename word, size_t N> |
| 244 | 244 | LIBC_INLINE constexpr bool is_negative(const cpp::array<word, N> &array) { |
| 245 | using signed_word = cpp::make_signed_t<word>; | |
| 246 | return cpp::bit_cast<signed_word>(array.back()) < 0; | |
| 245 | constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits; | |
| 246 | return (array.back() >> (WORD_BITS - 1)) != 0; | |
| 247 | 247 | } |
| 248 | ||
| 249 | 248 | // An enum for the shift function below. |
| 250 | 249 | enum Direction { LEFT, RIGHT }; |
| 251 | 250 | |
| ... | ... | @@ -257,9 +256,11 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array, |
| 257 | 256 | size_t offset) { |
| 258 | 257 | static_assert(direction == LEFT || direction == RIGHT); |
| 259 | 258 | constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits; |
| 259 | #if LIBC_HAS_BUILTIN_BIT_CAST | |
| 260 | 260 | #ifdef LIBC_TYPES_HAS_INT128 |
| 261 | 261 | constexpr size_t TOTAL_BITS = N * WORD_BITS; |
| 262 | if constexpr (TOTAL_BITS == 128) { | |
| 262 | if constexpr (TOTAL_BITS == 128 && | |
| 263 | __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) { | |
| 263 | 264 | using type = cpp::conditional_t<is_signed, __int128_t, __uint128_t>; |
| 264 | 265 | auto tmp = cpp::bit_cast<type>(array); |
| 265 | 266 | if constexpr (direction == LEFT) |
| ... | ... | @@ -269,6 +270,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array, |
| 269 | 270 | return cpp::bit_cast<cpp::array<word, N>>(tmp); |
| 270 | 271 | } |
| 271 | 272 | #endif |
| 273 | #endif // LIBC_HAS_BUILTIN_BIT_CAST | |
| 274 | ||
| 272 | 275 | if (LIBC_UNLIKELY(offset == 0)) |
| 273 | 276 | return array; |
| 274 | 277 | const bool is_neg = is_signed && is_negative(array); |
| ... | ... | @@ -336,8 +339,8 @@ private: |
| 336 | 339 | "WordType must be unsigned integer."); |
| 337 | 340 | |
| 338 | 341 | struct Division { |
| 339 | BigInt quotient; | |
| 340 | BigInt remainder; | |
| 342 | BigInt quotient{}; | |
| 343 | BigInt remainder{}; | |
| 341 | 344 | }; |
| 342 | 345 | |
| 343 | 346 | public: |
| ... | ... | @@ -355,7 +358,7 @@ public: |
| 355 | 358 | |
| 356 | 359 | LIBC_INLINE_VAR static constexpr size_t WORD_COUNT = Bits / WORD_SIZE; |
| 357 | 360 | |
| 358 | cpp::array<WordType, WORD_COUNT> val{}; // zero initialized. | |
| 361 | cpp::array<WordType, WORD_COUNT> val; | |
| 359 | 362 | |
| 360 | 363 | LIBC_INLINE constexpr BigInt() = default; |
| 361 | 364 | |
| ... | ... | @@ -363,9 +366,10 @@ public: |
| 363 | 366 | |
| 364 | 367 | template <size_t OtherBits, bool OtherSigned, typename OtherWordType> |
| 365 | 368 | LIBC_INLINE constexpr BigInt( |
| 366 | const BigInt<OtherBits, OtherSigned, OtherWordType> &other) { | |
| 369 | const BigInt<OtherBits, OtherSigned, OtherWordType> &other) | |
| 370 | : val{} { | |
| 367 | 371 | using BigIntOther = BigInt<OtherBits, OtherSigned, OtherWordType>; |
| 368 | const bool should_sign_extend = Signed && other.is_neg(); | |
| 372 | [[maybe_unused]] const bool should_sign_extend = Signed && other.is_neg(); | |
| 369 | 373 | |
| 370 | 374 | static_assert(!(Bits == OtherBits && WORD_SIZE != BigIntOther::WORD_SIZE) && |
| 371 | 375 | "This is currently untested for casting between bigints with " |
| ... | ... | @@ -453,20 +457,22 @@ public: |
| 453 | 457 | } |
| 454 | 458 | |
| 455 | 459 | // Construct a BigInt from a C array. |
| 456 | template <size_t N> LIBC_INLINE constexpr BigInt(const WordType (&nums)[N]) { | |
| 460 | template <size_t N> | |
| 461 | LIBC_INLINE constexpr BigInt(const WordType (&nums)[N]) : val{} { | |
| 457 | 462 | static_assert(N == WORD_COUNT); |
| 458 | 463 | for (size_t i = 0; i < WORD_COUNT; ++i) |
| 459 | 464 | val[i] = nums[i]; |
| 460 | 465 | } |
| 461 | 466 | |
| 462 | 467 | LIBC_INLINE constexpr explicit BigInt( |
| 463 | const cpp::array<WordType, WORD_COUNT> &words) { | |
| 468 | const cpp::array<WordType, WORD_COUNT> &words) | |
| 469 | : val{} { | |
| 464 | 470 | val = words; |
| 465 | 471 | } |
| 466 | 472 | |
| 467 | 473 | // Initialize the first word to |v| and the rest to 0. |
| 468 | 474 | template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T>>> |
| 469 | LIBC_INLINE constexpr BigInt(T v) { | |
| 475 | LIBC_INLINE constexpr BigInt(T v) : val{} { | |
| 470 | 476 | constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT; |
| 471 | 477 | const bool is_neg = v < 0; |
| 472 | 478 | for (size_t i = 0; i < WORD_COUNT; ++i) { |
| ... | ... | @@ -488,7 +494,7 @@ public: |
| 488 | 494 | LIBC_INLINE static constexpr BigInt one() { return BigInt(1); } |
| 489 | 495 | LIBC_INLINE static constexpr BigInt all_ones() { return ~zero(); } |
| 490 | 496 | LIBC_INLINE static constexpr BigInt min() { |
| 491 | BigInt out; | |
| 497 | BigInt out{}; | |
| 492 | 498 | if constexpr (SIGNED) |
| 493 | 499 | out.set_msb(); |
| 494 | 500 | return out; |
| ... | ... | @@ -601,7 +607,7 @@ public: |
| 601 | 607 | template <size_t OtherBits> |
| 602 | 608 | LIBC_INLINE constexpr auto |
| 603 | 609 | ful_mul(const BigInt<OtherBits, Signed, WordType> &other) const { |
| 604 | BigInt<Bits + OtherBits, Signed, WordType> result; | |
| 610 | BigInt<Bits + OtherBits, Signed, WordType> result{}; | |
| 605 | 611 | multiword::multiply_with_carry(result.val, val, other.val); |
| 606 | 612 | return result; |
| 607 | 613 | } |
| ... | ... | @@ -633,7 +639,7 @@ public: |
| 633 | 639 | // 256 4 16 10 3 |
| 634 | 640 | // 512 8 64 36 7 |
| 635 | 641 | LIBC_INLINE constexpr BigInt quick_mul_hi(const BigInt &other) const { |
| 636 | BigInt result; | |
| 642 | BigInt result{}; | |
| 637 | 643 | multiword::quick_mul_hi(result.val, val, other.val); |
| 638 | 644 | return result; |
| 639 | 645 | } |
| ... | ... | @@ -686,7 +692,7 @@ public: |
| 686 | 692 | // And finally we perform some extra alignment steps for the remaining bits. |
| 687 | 693 | LIBC_INLINE constexpr cpp::optional<BigInt> |
| 688 | 694 | div_uint_half_times_pow_2(multiword::half_width_t<WordType> x, size_t e) { |
| 689 | BigInt remainder; | |
| 695 | BigInt remainder{}; | |
| 690 | 696 | if (x == 0) |
| 691 | 697 | return cpp::nullopt; |
| 692 | 698 | if (e >= Bits) { |
| ... | ... | @@ -694,7 +700,7 @@ public: |
| 694 | 700 | *this = BigInt<Bits, false, WordType>(); |
| 695 | 701 | return remainder; |
| 696 | 702 | } |
| 697 | BigInt quotient; | |
| 703 | BigInt quotient{}; | |
| 698 | 704 | WordType x_word = static_cast<WordType>(x); |
| 699 | 705 | constexpr size_t LOG2_WORD_SIZE = |
| 700 | 706 | static_cast<size_t>(cpp::bit_width(WORD_SIZE) - 1); |
| ... | ... | @@ -846,13 +852,13 @@ public: |
| 846 | 852 | #define DEFINE_BINOP(OP) \ |
| 847 | 853 | LIBC_INLINE friend constexpr BigInt operator OP(const BigInt &lhs, \ |
| 848 | 854 | const BigInt &rhs) { \ |
| 849 | BigInt result; \ | |
| 855 | BigInt result{}; \ | |
| 850 | 856 | for (size_t i = 0; i < WORD_COUNT; ++i) \ |
| 851 | 857 | result[i] = lhs[i] OP rhs[i]; \ |
| 852 | 858 | return result; \ |
| 853 | 859 | } \ |
| 854 | LIBC_INLINE friend constexpr BigInt operator OP##=(BigInt &lhs, \ | |
| 855 | const BigInt &rhs) { \ | |
| 860 | LIBC_INLINE friend constexpr BigInt operator OP## = \ | |
| 861 | (BigInt & lhs, const BigInt &rhs) { \ | |
| 856 | 862 | for (size_t i = 0; i < WORD_COUNT; ++i) \ |
| 857 | 863 | lhs[i] OP## = rhs[i]; \ |
| 858 | 864 | return lhs; \ |
| ... | ... | @@ -864,7 +870,7 @@ public: |
| 864 | 870 | #undef DEFINE_BINOP |
| 865 | 871 | |
| 866 | 872 | LIBC_INLINE constexpr BigInt operator~() const { |
| 867 | BigInt result; | |
| 873 | BigInt result{}; | |
| 868 | 874 | for (size_t i = 0; i < WORD_COUNT; ++i) |
| 869 | 875 | result[i] = static_cast<WordType>(~val[i]); |
| 870 | 876 | return result; |
| ... | ... | @@ -1004,7 +1010,7 @@ private: |
| 1004 | 1010 | LIBC_INLINE constexpr static Division divide_unsigned(const BigInt &dividend, |
| 1005 | 1011 | const BigInt &divider) { |
| 1006 | 1012 | BigInt remainder = dividend; |
| 1007 | BigInt quotient; | |
| 1013 | BigInt quotient{}; | |
| 1008 | 1014 | if (remainder >= divider) { |
| 1009 | 1015 | BigInt subtractor = divider; |
| 1010 | 1016 | int cur_bit = multiword::countl_zero(subtractor.val) - |
| ... | ... | @@ -1181,31 +1187,6 @@ LIBC_INLINE_VAR constexpr bool is_unsigned_integral_or_big_int_v = |
| 1181 | 1187 | |
| 1182 | 1188 | namespace cpp { |
| 1183 | 1189 | |
| 1184 | // Specialization of cpp::bit_cast ('bit.h') from T to BigInt. | |
| 1185 | template <typename To, typename From> | |
| 1186 | LIBC_INLINE constexpr cpp::enable_if_t< | |
| 1187 | (sizeof(To) == sizeof(From)) && cpp::is_trivially_copyable<To>::value && | |
| 1188 | cpp::is_trivially_copyable<From>::value && is_big_int<To>::value, | |
| 1189 | To> | |
| 1190 | bit_cast(const From &from) { | |
| 1191 | To out; | |
| 1192 | using Storage = decltype(out.val); | |
| 1193 | out.val = cpp::bit_cast<Storage>(from); | |
| 1194 | return out; | |
| 1195 | } | |
| 1196 | ||
| 1197 | // Specialization of cpp::bit_cast ('bit.h') from BigInt to T. | |
| 1198 | template <typename To, size_t Bits> | |
| 1199 | LIBC_INLINE constexpr cpp::enable_if_t< | |
| 1200 | sizeof(To) == sizeof(UInt<Bits>) && | |
| 1201 | cpp::is_trivially_constructible<To>::value && | |
| 1202 | cpp::is_trivially_copyable<To>::value && | |
| 1203 | cpp::is_trivially_copyable<UInt<Bits>>::value, | |
| 1204 | To> | |
| 1205 | bit_cast(const UInt<Bits> &from) { | |
| 1206 | return cpp::bit_cast<To>(from.val); | |
| 1207 | } | |
| 1208 | ||
| 1209 | 1190 | // Specialization of cpp::popcount ('bit.h') for BigInt. |
| 1210 | 1191 | template <typename T> |
| 1211 | 1192 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int> |
| ... | ... | @@ -1311,7 +1292,7 @@ mask_trailing_ones() { |
| 1311 | 1292 | return T::all_ones(); |
| 1312 | 1293 | constexpr size_t QUOTIENT = count / T::WORD_SIZE; |
| 1313 | 1294 | constexpr size_t REMAINDER = count % T::WORD_SIZE; |
| 1314 | T out; // zero initialized | |
| 1295 | T out{}; | |
| 1315 | 1296 | for (size_t i = 0; i <= QUOTIENT; ++i) |
| 1316 | 1297 | out[i] = i < QUOTIENT |
| 1317 | 1298 | ? cpp::numeric_limits<typename T::word_type>::max() |
| ... | ... | @@ -1327,7 +1308,7 @@ LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() { |
| 1327 | 1308 | return T::all_ones(); |
| 1328 | 1309 | constexpr size_t QUOTIENT = (T::BITS - count - 1U) / T::WORD_SIZE; |
| 1329 | 1310 | constexpr size_t REMAINDER = count % T::WORD_SIZE; |
| 1330 | T out; // zero initialized | |
| 1311 | T out{}; | |
| 1331 | 1312 | for (size_t i = QUOTIENT; i < T::WORD_COUNT; ++i) |
| 1332 | 1313 | out[i] = i > QUOTIENT |
| 1333 | 1314 | ? cpp::numeric_limits<typename T::word_type>::max() |
| ... | ... | @@ -1386,6 +1367,11 @@ first_trailing_one(T value) { |
| 1386 | 1367 | return value == 0 ? 0 : cpp::countr_zero(value) + 1; |
| 1387 | 1368 | } |
| 1388 | 1369 | |
| 1370 | static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible< | |
| 1371 | LIBC_NAMESPACE::BigInt<128, false>>::value); | |
| 1372 | static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable< | |
| 1373 | LIBC_NAMESPACE::BigInt<128, false>>::value); | |
| 1374 | ||
| 1389 | 1375 | } // namespace LIBC_NAMESPACE_DECL |
| 1390 | 1376 | |
| 1391 | 1377 | #endif // LLVM_LIBC_SRC___SUPPORT_BIG_INT_H |
lib/libcxx/libc/src/__support/common.h+45-32| ... | ... | @@ -22,6 +22,10 @@ |
| 22 | 22 | #define LLVM_LIBC_FUNCTION_ATTR |
| 23 | 23 | #endif |
| 24 | 24 | |
| 25 | #ifndef LLVM_LIBC_VARIABLE_ATTR | |
| 26 | #define LLVM_LIBC_VARIABLE_ATTR | |
| 27 | #endif | |
| 28 | ||
| 25 | 29 | // clang-format off |
| 26 | 30 | // Allow each function `func` to have extra attributes specified by defining: |
| 27 | 31 | // `LLVM_LIBC_FUNCTION_ATTR_func` macro, which should always start with |
| ... | ... | @@ -33,7 +37,9 @@ |
| 33 | 37 | // clang-format on |
| 34 | 38 | #define LLVM_LIBC_EMPTY |
| 35 | 39 | |
| 40 | #define GET_NOTHING(...) 0 | |
| 36 | 41 | #define GET_SECOND(first, second, ...) second |
| 42 | #define GET_FIFTH(first, second, third, fourth, fifth, ...) fifth | |
| 37 | 43 | #define EXPAND_THEN_SECOND(name) GET_SECOND(name, LLVM_LIBC_EMPTY) |
| 38 | 44 | |
| 39 | 45 | #define LLVM_LIBC_ATTR(name) EXPAND_THEN_SECOND(LLVM_LIBC_FUNCTION_ATTR_##name) |
| ... | ... | @@ -44,50 +50,57 @@ |
| 44 | 50 | // symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`. |
| 45 | 51 | #if defined(LIBC_COPT_PUBLIC_PACKAGING) && !defined(LIBC_COMPILER_IS_MSVC) |
| 46 | 52 | #ifndef __APPLE__ |
| 47 | #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \ | |
| 53 | #define LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, c_alias) \ | |
| 48 | 54 | LLVM_LIBC_ATTR(name) \ |
| 49 | 55 | LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \ |
| 50 | __##name##_impl__ asm(#name); \ | |
| 51 | decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \ | |
| 56 | __##name##_impl__ asm(c_alias); \ | |
| 57 | decltype(LIBC_NAMESPACE::name) name [[gnu::alias(c_alias)]]; \ | |
| 52 | 58 | type __##name##_impl__ arglist |
| 53 | 59 | #else // __APPLE__ |
| 54 | #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \ | |
| 60 | #define LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, c_alias) \ | |
| 55 | 61 | LLVM_LIBC_ATTR(name) \ |
| 56 | LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) name asm("_" #name); \ | |
| 62 | LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) name asm( \ | |
| 63 | "_" c_alias); \ | |
| 57 | 64 | type name arglist |
| 58 | 65 | #endif // __APPLE__ |
| 66 | ||
| 59 | 67 | #else // LIBC_COPT_PUBLIC_PACKAGING |
| 60 | #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) type name arglist | |
| 68 | #define LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, c_alias) \ | |
| 69 | type name arglist | |
| 61 | 70 | #endif // LIBC_COPT_PUBLIC_PACKAGING |
| 62 | 71 | |
| 63 | // This extra layer of macro allows `name` to be a macro to rename a function. | |
| 64 | #define LLVM_LIBC_FUNCTION(type, name, arglist) \ | |
| 65 | LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) | |
| 72 | #define LLVM_LIBC_FUNCTION_IMPL_3(type, name, arglist) \ | |
| 73 | LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, #name) | |
| 66 | 74 | |
| 67 | namespace LIBC_NAMESPACE_DECL { | |
| 68 | namespace internal { | |
| 69 | LIBC_INLINE constexpr bool same_string(char const *lhs, char const *rhs) { | |
| 70 | for (; *lhs || *rhs; ++lhs, ++rhs) | |
| 71 | if (*lhs != *rhs) | |
| 72 | return false; | |
| 73 | return true; | |
| 74 | } | |
| 75 | } // namespace internal | |
| 76 | } // namespace LIBC_NAMESPACE_DECL | |
| 75 | // LLVM_LIBC_FUNCTION(type, name, arglist) is equivalent to | |
| 76 | // LLVM_LIBC_FUNCTION(type, name, arglist, #name) | |
| 77 | #define LLVM_LIBC_FUNCTION(...) \ | |
| 78 | GET_FIFTH(__VA_ARGS__, LLVM_LIBC_FUNCTION_IMPL_4, LLVM_LIBC_FUNCTION_IMPL_3, \ | |
| 79 | GET_NOTHING)(__VA_ARGS__) | |
| 77 | 80 | |
| 78 | #define __LIBC_MACRO_TO_STRING(str) #str | |
| 79 | #define LIBC_MACRO_TO_STRING(str) __LIBC_MACRO_TO_STRING(str) | |
| 81 | // At the moment, [[gnu::alias()]] is not supported on MacOS, and it is needed | |
| 82 | // to cleanly export and alias the C++ symbol `LIBC_NAMESPACE::func` with the C | |
| 83 | // symbol `func`. So for public packaging on MacOS, we will only export the C | |
| 84 | // symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`. | |
| 85 | #if defined(LIBC_COPT_PUBLIC_PACKAGING) && !defined(LIBC_COMPILER_IS_MSVC) | |
| 86 | #ifndef __APPLE__ | |
| 87 | #define LLVM_LIBC_VARIABLE_IMPL(type, name) \ | |
| 88 | LLVM_LIBC_ATTR(name) \ | |
| 89 | extern LLVM_LIBC_VARIABLE_ATTR decltype(LIBC_NAMESPACE::name) \ | |
| 90 | __##name##_impl__ asm(#name); \ | |
| 91 | extern decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \ | |
| 92 | type __##name##_impl__ | |
| 93 | #else // __APPLE__ | |
| 94 | #define LLVM_LIBC_VARIABLE_IMPL(type, name) \ | |
| 95 | LLVM_LIBC_ATTR(name) \ | |
| 96 | extern LLVM_LIBC_VARIABLE_ATTR decltype(LIBC_NAMESPACE::name) name asm( \ | |
| 97 | "_" #name); \ | |
| 98 | type name | |
| 99 | #endif // __APPLE__ | |
| 100 | #else // LIBC_COPT_PUBLIC_PACKAGING | |
| 101 | #define LLVM_LIBC_VARIABLE_IMPL(type, name) type name | |
| 102 | #endif // LIBC_COPT_PUBLIC_PACKAGING | |
| 80 | 103 | |
| 81 | // LLVM_LIBC_IS_DEFINED checks whether a particular macro is defined. | |
| 82 | // Usage: constexpr bool kUseAvx = LLVM_LIBC_IS_DEFINED(__AVX__); | |
| 83 | // | |
| 84 | // This works by comparing the stringified version of the macro with and without | |
| 85 | // evaluation. If FOO is not undefined both stringifications yield "FOO". If FOO | |
| 86 | // is defined, one stringification yields "FOO" while the other yields its | |
| 87 | // stringified value "1". | |
| 88 | #define LLVM_LIBC_IS_DEFINED(macro) \ | |
| 89 | !LIBC_NAMESPACE::internal::same_string( \ | |
| 90 | LLVM_LIBC_IS_DEFINED__EVAL_AND_STRINGIZE(macro), #macro) | |
| 91 | #define LLVM_LIBC_IS_DEFINED__EVAL_AND_STRINGIZE(s) #s | |
| 104 | #define LLVM_LIBC_VARIABLE(type, name) LLVM_LIBC_VARIABLE_IMPL(type, name) | |
| 92 | 105 | |
| 93 | 106 | #endif // LLVM_LIBC_SRC___SUPPORT_COMMON_H |
lib/libcxx/libc/src/__support/ctype_utils.h+27-15| ... | ... | @@ -37,7 +37,7 @@ namespace internal { |
| 37 | 37 | // EBCDIC. Technically we could use some smaller ranges, but that's even harder |
| 38 | 38 | // to read. |
| 39 | 39 | |
| 40 | LIBC_INLINE static constexpr bool islower(char ch) { | |
| 40 | LIBC_INLINE constexpr bool islower(char ch) { | |
| 41 | 41 | switch (ch) { |
| 42 | 42 | case 'a': |
| 43 | 43 | case 'b': |
| ... | ... | @@ -71,7 +71,7 @@ LIBC_INLINE static constexpr bool islower(char ch) { |
| 71 | 71 | } |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | LIBC_INLINE static constexpr bool isupper(char ch) { | |
| 74 | LIBC_INLINE constexpr bool isupper(char ch) { | |
| 75 | 75 | switch (ch) { |
| 76 | 76 | case 'A': |
| 77 | 77 | case 'B': |
| ... | ... | @@ -105,7 +105,7 @@ LIBC_INLINE static constexpr bool isupper(char ch) { |
| 105 | 105 | } |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | LIBC_INLINE static constexpr bool isdigit(char ch) { | |
| 108 | LIBC_INLINE constexpr bool isdigit(char ch) { | |
| 109 | 109 | switch (ch) { |
| 110 | 110 | case '0': |
| 111 | 111 | case '1': |
| ... | ... | @@ -123,7 +123,7 @@ LIBC_INLINE static constexpr bool isdigit(char ch) { |
| 123 | 123 | } |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | LIBC_INLINE static constexpr char tolower(char ch) { | |
| 126 | LIBC_INLINE constexpr char tolower(char ch) { | |
| 127 | 127 | switch (ch) { |
| 128 | 128 | case 'A': |
| 129 | 129 | return 'a'; |
| ... | ... | @@ -182,7 +182,7 @@ LIBC_INLINE static constexpr char tolower(char ch) { |
| 182 | 182 | } |
| 183 | 183 | } |
| 184 | 184 | |
| 185 | LIBC_INLINE static constexpr char toupper(char ch) { | |
| 185 | LIBC_INLINE constexpr char toupper(char ch) { | |
| 186 | 186 | switch (ch) { |
| 187 | 187 | case 'a': |
| 188 | 188 | return 'A'; |
| ... | ... | @@ -241,7 +241,7 @@ LIBC_INLINE static constexpr char toupper(char ch) { |
| 241 | 241 | } |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | LIBC_INLINE static constexpr bool isalpha(char ch) { | |
| 244 | LIBC_INLINE constexpr bool isalpha(char ch) { | |
| 245 | 245 | switch (ch) { |
| 246 | 246 | case 'a': |
| 247 | 247 | case 'b': |
| ... | ... | @@ -301,7 +301,7 @@ LIBC_INLINE static constexpr bool isalpha(char ch) { |
| 301 | 301 | } |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | LIBC_INLINE static constexpr bool isalnum(char ch) { | |
| 304 | LIBC_INLINE constexpr bool isalnum(char ch) { | |
| 305 | 305 | switch (ch) { |
| 306 | 306 | case 'a': |
| 307 | 307 | case 'b': |
| ... | ... | @@ -371,7 +371,8 @@ LIBC_INLINE static constexpr bool isalnum(char ch) { |
| 371 | 371 | } |
| 372 | 372 | } |
| 373 | 373 | |
| 374 | LIBC_INLINE static constexpr int b36_char_to_int(char ch) { | |
| 374 | #ifndef LIBC_COPT_CTYPE_SMALLER_ASCII | |
| 375 | LIBC_INLINE constexpr int b36_char_to_int(char ch) { | |
| 375 | 376 | switch (ch) { |
| 376 | 377 | case '0': |
| 377 | 378 | return 0; |
| ... | ... | @@ -475,8 +476,21 @@ LIBC_INLINE static constexpr int b36_char_to_int(char ch) { |
| 475 | 476 | return 0; |
| 476 | 477 | } |
| 477 | 478 | } |
| 479 | #else // LIBC_COPT_SMALL_ASCII_CTYPE | |
| 480 | // This version assumes ASCII for the tolower, but generates smaller code since | |
| 481 | // the switch version of this function ends up with a table. This should only be | |
| 482 | // used when the target is known to be ASCII. | |
| 483 | LIBC_INLINE constexpr int b36_char_to_int(char ch) { | |
| 484 | if (ch >= '0' && ch <= '9') | |
| 485 | return ch - '0'; | |
| 486 | char ch_unsafe_lower = ch | 32; | |
| 487 | if (ch_unsafe_lower >= 'a' && ch_unsafe_lower <= 'z') | |
| 488 | return ch_unsafe_lower - 'a' + 10; | |
| 489 | return 0; | |
| 490 | } | |
| 491 | #endif // LIBC_COPT_SMALL_ASCII_CTYPE | |
| 478 | 492 | |
| 479 | LIBC_INLINE static constexpr char int_to_b36_char(int num) { | |
| 493 | LIBC_INLINE constexpr char int_to_b36_char(int num) { | |
| 480 | 494 | // Can't actually use LIBC_ASSERT here because it depends on integer_to_string |
| 481 | 495 | // which depends on this. |
| 482 | 496 | |
| ... | ... | @@ -559,7 +573,7 @@ LIBC_INLINE static constexpr char int_to_b36_char(int num) { |
| 559 | 573 | } |
| 560 | 574 | } |
| 561 | 575 | |
| 562 | LIBC_INLINE static constexpr bool isspace(char ch) { | |
| 576 | LIBC_INLINE constexpr bool isspace(char ch) { | |
| 563 | 577 | switch (ch) { |
| 564 | 578 | case ' ': |
| 565 | 579 | case '\t': |
| ... | ... | @@ -574,14 +588,12 @@ LIBC_INLINE static constexpr bool isspace(char ch) { |
| 574 | 588 | } |
| 575 | 589 | |
| 576 | 590 | // not yet encoding independent. |
| 577 | LIBC_INLINE static constexpr bool isgraph(char ch) { | |
| 578 | return 0x20 < ch && ch < 0x7f; | |
| 579 | } | |
| 591 | LIBC_INLINE constexpr bool isgraph(char ch) { return 0x20 < ch && ch < 0x7f; } | |
| 580 | 592 | |
| 581 | 593 | // An overload which provides a way to compare input with specific character |
| 582 | 594 | // values, when input can be of a regular or a wide character type. |
| 583 | LIBC_INLINE static constexpr bool is_char_or_wchar(char ch, char c_value, | |
| 584 | [[maybe_unused]] wchar_t) { | |
| 595 | LIBC_INLINE constexpr bool is_char_or_wchar(char ch, char c_value, | |
| 596 | [[maybe_unused]] wchar_t) { | |
| 585 | 597 | return (ch == c_value); |
| 586 | 598 | } |
| 587 | 599 |
lib/libcxx/libc/src/__support/high_precision_decimal.h+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | //===-- High Precision Decimal ----------------------------------*- C++ -*-===// |
| 2 | 2 | // |
| 3 | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See httpss//llvm.org/LICENSE.txt for license information. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | 6 | // |
| 7 | 7 | //===----------------------------------------------------------------------===// |
lib/libcxx/libc/src/__support/libc_assert.h+4-11| ... | ... | @@ -25,8 +25,9 @@ |
| 25 | 25 | #include "src/__support/OSUtil/exit.h" |
| 26 | 26 | #include "src/__support/OSUtil/io.h" |
| 27 | 27 | #include "src/__support/integer_to_string.h" |
| 28 | #include "src/__support/macros/attributes.h" // For LIBC_INLINE | |
| 28 | #include "src/__support/macros/attributes.h" // For LIBC_INLINE | |
| 29 | 29 | #include "src/__support/macros/config.h" |
| 30 | #include "src/__support/macros/macro-utils.h" | |
| 30 | 31 | #include "src/__support/macros/optimization.h" // For LIBC_UNLIKELY |
| 31 | 32 | |
| 32 | 33 | namespace LIBC_NAMESPACE_DECL { |
| ... | ... | @@ -65,19 +66,11 @@ LIBC_INLINE void report_assertion_failure(const char *assertion, |
| 65 | 66 | } while (false) |
| 66 | 67 | #else |
| 67 | 68 | |
| 68 | // Convert __LINE__ to a string using macros. The indirection is necessary | |
| 69 | // because otherwise it will turn "__LINE__" into a string, not its value. The | |
| 70 | // value is evaluated in the indirection step. | |
| 71 | #define __LIBC_MACRO_TO_STR(x) #x | |
| 72 | #define __LIBC_MACRO_TO_STR_INDIR(y) __LIBC_MACRO_TO_STR(y) | |
| 73 | #define __LIBC_LINE_STR__ __LIBC_MACRO_TO_STR_INDIR(__LINE__) | |
| 74 | ||
| 75 | 69 | #define LIBC_ASSERT(COND) \ |
| 76 | 70 | do { \ |
| 77 | 71 | if (LIBC_UNLIKELY(!(COND))) { \ |
| 78 | LIBC_NAMESPACE::write_to_stderr(__FILE__ ":" __LIBC_LINE_STR__ \ | |
| 79 | ": Assertion failed: '" #COND \ | |
| 80 | "' in function: '"); \ | |
| 72 | LIBC_NAMESPACE::write_to_stderr(__FILE__ ":" LLVM_LIBC_STRINGIFY( \ | |
| 73 | __LINE__) ": Assertion failed: '" #COND "' in function: '"); \ | |
| 81 | 74 | LIBC_NAMESPACE::write_to_stderr(__PRETTY_FUNCTION__); \ |
| 82 | 75 | LIBC_NAMESPACE::write_to_stderr("'\n"); \ |
| 83 | 76 | LIBC_NAMESPACE::internal::exit(0xFF); \ |
lib/libcxx/libc/src/__support/macros/attributes.h+74| ... | ... | @@ -29,6 +29,80 @@ |
| 29 | 29 | #define LIBC_INLINE_ASM __asm__ __volatile__ |
| 30 | 30 | #define LIBC_UNUSED __attribute__((unused)) |
| 31 | 31 | |
| 32 | #ifndef LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED | |
| 33 | #if (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 900)) || \ | |
| 34 | (defined(LIBC_COMPILER_IS_CLANG) && LIBC_COMPILER_CLANG_VER >= 900) | |
| 35 | #define LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED 1 | |
| 36 | #else | |
| 37 | #define LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED \ | |
| 38 | (__has_builtin(__builtin_is_constant_evaluated)) | |
| 39 | #endif // (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 900)) || | |
| 40 | // (defined(LIBC_COMPILER_IS_CLANG) && LIBC_COMPILER_CLANG | |
| 41 | #endif // LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED | |
| 42 | ||
| 43 | #ifndef LIBC_HAS_BUILTIN_BIT_CAST | |
| 44 | #if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC) | |
| 45 | #define LIBC_HAS_BUILTIN_BIT_CAST 1 | |
| 46 | #else | |
| 47 | #define LIBC_HAS_BUILTIN_BIT_CAST 0 | |
| 48 | #endif // has_builtin(__builtin_bit_cast) | |
| 49 | #endif // LIBC_HAS_BUILTIN_BIT_CAST | |
| 50 | ||
| 51 | #if LIBC_HAS_BUILTIN_BIT_CAST | |
| 52 | #define LIBC_BIT_CAST_CONSTEXPR constexpr | |
| 53 | #define LIBC_BIT_CAST_CONSTEXPR_VAR constexpr | |
| 54 | #else | |
| 55 | #define LIBC_BIT_CAST_CONSTEXPR | |
| 56 | #define LIBC_BIT_CAST_CONSTEXPR_VAR const | |
| 57 | #endif // LIBC_HAS_BUILTIN_BIT_CAST | |
| 58 | ||
| 59 | #ifndef LIBC_HAS_CONSTANT_EVALUATION | |
| 60 | #define LIBC_HAS_CONSTANT_EVALUATION \ | |
| 61 | (LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED && LIBC_HAS_BUILTIN_BIT_CAST) | |
| 62 | #endif // LIBC_HAS_CONSTANT_EVALUATION | |
| 63 | ||
| 64 | #if LIBC_HAS_CONSTANT_EVALUATION | |
| 65 | #define LIBC_CONSTEXPR_DEFAULT constexpr | |
| 66 | #define LIBC_CONSTEXPR_VAR_DEFAULT constexpr | |
| 67 | #else | |
| 68 | #define LIBC_CONSTEXPR_DEFAULT | |
| 69 | #define LIBC_CONSTEXPR_VAR_DEFAULT const | |
| 70 | #endif // LIBC_HAS_CONSTANT_EVALUATION | |
| 71 | ||
| 72 | // TODO: Remove the macro once Clang/LLVM bump their minimum compilers' version. | |
| 73 | // The reason for indirection is GCC is known to fail with constexpr qualified | |
| 74 | // functions that doesn't produce constant expression. | |
| 75 | // Also, there are some circular dependency in the generic functions without | |
| 76 | // __builtin_func for the following functions: | |
| 77 | // fputil::fma | |
| 78 | // fputil::sqrt | |
| 79 | #if LIBC_ENABLE_CONSTEXPR && LIBC_HAS_CONSTANT_EVALUATION | |
| 80 | #define LIBC_USE_CONSTEXPR | |
| 81 | #define LIBC_CONSTEXPR constexpr | |
| 82 | #define LIBC_CONSTEXPR_VAR constexpr | |
| 83 | #else | |
| 84 | #define LIBC_CONSTEXPR | |
| 85 | #define LIBC_CONSTEXPR_VAR const | |
| 86 | #endif // LIBC_USE_CONSTEXPR | |
| 87 | ||
| 88 | #ifndef LIBC_HAS_BUILTIN_IS_ASSIGNABLE | |
| 89 | #if (__has_builtin(__is_assignable) || \ | |
| 90 | (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 800))) | |
| 91 | #define LIBC_HAS_BUILTIN_IS_ASSIGNABLE 1 | |
| 92 | #else | |
| 93 | #define LIBC_HAS_BUILTIN_IS_ASSIGNABLE 0 | |
| 94 | #endif | |
| 95 | #endif // LIBC_HAS_BUILTIN_IS_ASSIGNABLE | |
| 96 | ||
| 97 | #ifndef LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE | |
| 98 | #if (__has_builtin(__is_constructible) || \ | |
| 99 | (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 800))) | |
| 100 | #define LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1 | |
| 101 | #else | |
| 102 | #define LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE 0 | |
| 103 | #endif | |
| 104 | #endif // LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE | |
| 105 | ||
| 32 | 106 | // Uses the platform specific specialization |
| 33 | 107 | #define LIBC_THREAD_MODE_PLATFORM 0 |
| 34 | 108 |
lib/libcxx/libc/src/__support/macros/config.h+14| ... | ... | @@ -48,6 +48,10 @@ |
| 48 | 48 | |
| 49 | 49 | #define __builtin_prefetch(X, Y, Z) |
| 50 | 50 | |
| 51 | #define LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED 1 | |
| 52 | #define LIBC_HAS_BUILTIN_IS_ASSIGNABLE 1 | |
| 53 | #define LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1 | |
| 54 | ||
| 51 | 55 | #endif // LIBC_COMPILER_IS_MSVC |
| 52 | 56 | |
| 53 | 57 | #ifdef __clang__ |
| ... | ... | @@ -66,4 +70,14 @@ |
| 66 | 70 | #define LIBC_NAMESPACE_DECL LIBC_NAMESPACE |
| 67 | 71 | #endif |
| 68 | 72 | |
| 73 | // IMPORTANT (USE WITH CAUTION): This macro is intended to be used at the top of | |
| 74 | // the file and set to 1. It alters the signatures of some functions to have | |
| 75 | // constexpr qualifier and forces the use of constexpr-compatible | |
| 76 | // implementation, which might be a completely different code path or | |
| 77 | // instructions. Some of these functions exploit platform-specific non-constexpr | |
| 78 | // implementations to achieve certain goals, thus it is disabled by default. | |
| 79 | #ifndef LIBC_ENABLE_CONSTEXPR | |
| 80 | #define LIBC_ENABLE_CONSTEXPR 0 | |
| 81 | #endif | |
| 82 | ||
| 69 | 83 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H |
lib/libcxx/libc/src/__support/macros/macro-utils.h created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | //===-- Macros used by other macros ----------------------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | ||
| 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_MACRO_UTILS_H | |
| 10 | #define LLVM_LIBC_SRC___SUPPORT_MACROS_MACRO_UTILS_H | |
| 11 | ||
| 12 | // Stringify the argument after an extra pass of macro expansion. | |
| 13 | #define LLVM_LIBC_STRINGIFY(x) LLVM_LIBC_STRINGIFY_IMPL(x) | |
| 14 | #define LLVM_LIBC_STRINGIFY_IMPL(x) #x | |
| 15 | ||
| 16 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_MACRO_UTILS_H |
lib/libcxx/libc/src/__support/macros/optimization.h+18-7| ... | ... | @@ -32,8 +32,13 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) { |
| 32 | 32 | #define LIBC_LOOP_NOUNROLL _Pragma("nounroll") |
| 33 | 33 | #define LIBC_LOOP_UNROLL _Pragma("unroll") |
| 34 | 34 | #elif defined(LIBC_COMPILER_IS_GCC) |
| 35 | #if LIBC_COMPILER_GCC_VER >= 800 | |
| 35 | 36 | #define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0") |
| 36 | 37 | #define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048") |
| 38 | #else | |
| 39 | #define LIBC_LOOP_NOUNROLL | |
| 40 | #define LIBC_LOOP_UNROLL | |
| 41 | #endif | |
| 37 | 42 | #elif defined(LIBC_COMPILER_IS_MSVC) |
| 38 | 43 | #define LIBC_LOOP_NOUNROLL |
| 39 | 44 | #define LIBC_LOOP_UNROLL |
| ... | ... | @@ -47,33 +52,39 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) { |
| 47 | 52 | #define LIBC_MATH_SMALL_TABLES 0x02 |
| 48 | 53 | #define LIBC_MATH_NO_ERRNO 0x04 |
| 49 | 54 | #define LIBC_MATH_NO_EXCEPT 0x08 |
| 55 | #define LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT 0x10 | |
| 56 | #define LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY 0x20 | |
| 50 | 57 | #define LIBC_MATH_FAST \ |
| 51 | 58 | (LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | \ |
| 52 | LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT) | |
| 53 | #define LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT 0x10 | |
| 59 | LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT | \ | |
| 60 | LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY) | |
| 54 | 61 | |
| 55 | 62 | #ifndef LIBC_MATH |
| 56 | 63 | #define LIBC_MATH 0 |
| 57 | 64 | #endif // LIBC_MATH |
| 58 | 65 | |
| 59 | #if (LIBC_MATH & LIBC_MATH_SKIP_ACCURATE_PASS) | |
| 66 | #if ((LIBC_MATH) & LIBC_MATH_SKIP_ACCURATE_PASS) | |
| 60 | 67 | #define LIBC_MATH_HAS_SKIP_ACCURATE_PASS |
| 61 | 68 | #endif |
| 62 | 69 | |
| 63 | #if (LIBC_MATH & LIBC_MATH_SMALL_TABLES) | |
| 70 | #if ((LIBC_MATH) & LIBC_MATH_SMALL_TABLES) | |
| 64 | 71 | #define LIBC_MATH_HAS_SMALL_TABLES |
| 65 | 72 | #endif |
| 66 | 73 | |
| 67 | #if (LIBC_MATH & LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT) | |
| 74 | #if ((LIBC_MATH) & LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT) | |
| 68 | 75 | #define LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT |
| 69 | 76 | #endif |
| 70 | 77 | |
| 71 | #if (LIBC_MATH & LIBC_MATH_NO_ERRNO) | |
| 78 | #if ((LIBC_MATH) & LIBC_MATH_NO_ERRNO) | |
| 72 | 79 | #define LIBC_MATH_HAS_NO_ERRNO |
| 73 | 80 | #endif |
| 74 | 81 | |
| 75 | #if (LIBC_MATH & LIBC_MATH_NO_EXCEPT) | |
| 82 | #if ((LIBC_MATH) & LIBC_MATH_NO_EXCEPT) | |
| 76 | 83 | #define LIBC_MATH_HAS_NO_EXCEPT |
| 77 | 84 | #endif |
| 78 | 85 | |
| 86 | #if ((LIBC_MATH) & LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY) | |
| 87 | #define LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 88 | #endif | |
| 89 | ||
| 79 | 90 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H |
lib/libcxx/libc/src/__support/macros/properties/architectures.h+6-1| ... | ... | @@ -13,11 +13,16 @@ |
| 13 | 13 | #define LIBC_TARGET_ARCH_IS_AMDGPU |
| 14 | 14 | #endif |
| 15 | 15 | |
| 16 | #if defined(__SPIRV__) | |
| 17 | #define LIBC_TARGET_ARCH_IS_SPIRV | |
| 18 | #endif | |
| 19 | ||
| 16 | 20 | #if defined(__NVPTX__) |
| 17 | 21 | #define LIBC_TARGET_ARCH_IS_NVPTX |
| 18 | 22 | #endif |
| 19 | 23 | |
| 20 | #if defined(LIBC_TARGET_ARCH_IS_NVPTX) || defined(LIBC_TARGET_ARCH_IS_AMDGPU) | |
| 24 | #if defined(LIBC_TARGET_ARCH_IS_NVPTX) || \ | |
| 25 | defined(LIBC_TARGET_ARCH_IS_AMDGPU) || defined(LIBC_TARGET_ARCH_IS_SPIRV) | |
| 21 | 26 | #define LIBC_TARGET_ARCH_IS_GPU |
| 22 | 27 | #endif |
| 23 | 28 |
lib/libcxx/libc/src/__support/macros/properties/cpu_features.h+7-2| ... | ... | @@ -56,6 +56,10 @@ |
| 56 | 56 | #define LIBC_TARGET_CPU_HAS_AVX512BW |
| 57 | 57 | #endif |
| 58 | 58 | |
| 59 | #if defined(__AVX512F__) || defined(__AVX2__) | |
| 60 | #define LIBC_TARGET_CPU_HAS_GATHER | |
| 61 | #endif | |
| 62 | ||
| 59 | 63 | #if defined(__ARM_FP) |
| 60 | 64 | #if (__ARM_FP & 0x2) |
| 61 | 65 | #define LIBC_TARGET_CPU_HAS_ARM_FPU_HALF |
| ... | ... | @@ -91,13 +95,14 @@ |
| 91 | 95 | #endif // LIBC_TARGET_CPU_HAS_RISCV_FPU_DOUBLE |
| 92 | 96 | #endif // __riscv_flen |
| 93 | 97 | |
| 94 | #if defined(__NVPTX__) || defined(__AMDGPU__) | |
| 98 | #if defined(__NVPTX__) || defined(__AMDGPU__) || defined(__SPIRV__) | |
| 95 | 99 | #define LIBC_TARGET_CPU_HAS_FPU_FLOAT |
| 96 | 100 | #define LIBC_TARGET_CPU_HAS_FPU_DOUBLE |
| 97 | 101 | #endif |
| 98 | 102 | |
| 99 | 103 | #if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \ |
| 100 | defined(__NVPTX__) || defined(__AMDGPU__) || defined(__riscv_flen) | |
| 104 | defined(__NVPTX__) || defined(__AMDGPU__) || defined(__riscv_flen) || \ | |
| 105 | defined(__SPIRV__) | |
| 101 | 106 | #define LIBC_TARGET_CPU_HAS_FMA |
| 102 | 107 | // Provide a more fine-grained control of FMA instruction for ARM targets. |
| 103 | 108 | #if defined(LIBC_TARGET_CPU_HAS_FPU_HALF) |
lib/libcxx/libc/src/__support/macros/sanitizer.h+7-6| ... | ... | @@ -26,24 +26,25 @@ |
| 26 | 26 | #ifdef LIBC_HAS_MEMORY_SANITIZER |
| 27 | 27 | // Only perform MSAN unpoison in non-constexpr context. |
| 28 | 28 | #include <sanitizer/msan_interface.h> |
| 29 | #define MSAN_UNPOISON(addr, size) \ | |
| 29 | #define LIBC_MSAN_UNPOISON(addr, size) \ | |
| 30 | 30 | do { \ |
| 31 | 31 | if (!__builtin_is_constant_evaluated()) \ |
| 32 | 32 | __msan_unpoison(addr, size); \ |
| 33 | 33 | } while (0) |
| 34 | 34 | #else |
| 35 | #define MSAN_UNPOISON(ptr, size) | |
| 35 | #define LIBC_MSAN_UNPOISON(ptr, size) | |
| 36 | 36 | #endif |
| 37 | 37 | |
| 38 | 38 | #ifdef LIBC_HAS_ADDRESS_SANITIZER |
| 39 | 39 | #include <sanitizer/asan_interface.h> |
| 40 | #define ASAN_POISON_MEMORY_REGION(addr, size) \ | |
| 40 | #define LIBC_ASAN_POISON_MEMORY_REGION(addr, size) \ | |
| 41 | 41 | __asan_poison_memory_region((addr), (size)) |
| 42 | #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ | |
| 42 | #define LIBC_ASAN_UNPOISON_MEMORY_REGION(addr, size) \ | |
| 43 | 43 | __asan_unpoison_memory_region((addr), (size)) |
| 44 | 44 | #else |
| 45 | #define ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size)) | |
| 46 | #define ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size)) | |
| 45 | #define LIBC_ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size)) | |
| 46 | #define LIBC_ASAN_UNPOISON_MEMORY_REGION(addr, size) \ | |
| 47 | ((void)(addr), (void)(size)) | |
| 47 | 48 | #endif |
| 48 | 49 | |
| 49 | 50 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_SANITIZER_H |
lib/libcxx/libc/src/__support/math_extras.h+15| ... | ... | @@ -80,6 +80,21 @@ template <typename T> |
| 80 | 80 | #endif // __builtin_sub_overflow |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | template <typename T> | |
| 84 | [[nodiscard]] LIBC_INLINE constexpr bool mul_overflow(T a, T b, T &res) { | |
| 85 | #if __has_builtin(__builtin_mul_overflow) | |
| 86 | return __builtin_mul_overflow(a, b, &res); | |
| 87 | #else | |
| 88 | T max = cpp::numeric_limits<T>::max(); | |
| 89 | T min = cpp::numeric_limits<T>::min(); | |
| 90 | bool overflow = (b > 0 && (a > max / b || a < min / b)) || | |
| 91 | (b < 0 && (a < max / b || a > min / b)); | |
| 92 | if (!overflow) | |
| 93 | res = a * b; | |
| 94 | return overflow; | |
| 95 | #endif | |
| 96 | } | |
| 97 | ||
| 83 | 98 | #define RETURN_IF(TYPE, BUILTIN) \ |
| 84 | 99 | if constexpr (cpp::is_same_v<T, TYPE>) \ |
| 85 | 100 | return BUILTIN(a, b, carry_in, &carry_out); |
lib/libcxx/libc/src/__support/str_to_float.h+14-9| ... | ... | @@ -124,7 +124,7 @@ eisel_lemire(ExpandedFloat<T> init_num, |
| 124 | 124 | // Wider Approximation |
| 125 | 125 | UInt128 final_approx; |
| 126 | 126 | // The halfway constant is used to check if the bits that will be shifted away |
| 127 | // intially are all 1. For doubles this is 64 (bitstype size) - 52 (final | |
| 127 | // initially are all 1. For doubles this is 64 (bitstype size) - 52 (final | |
| 128 | 128 | // mantissa size) - 3 (we shift away the last two bits separately for |
| 129 | 129 | // accuracy, and the most significant bit is ignored.) = 9 bits. Similarly, |
| 130 | 130 | // it's 6 bits for floats in this case. |
| ... | ... | @@ -262,7 +262,7 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num, |
| 262 | 262 | (final_approx_lower < approx_lower ? 1 : 0); |
| 263 | 263 | |
| 264 | 264 | // The halfway constant is used to check if the bits that will be shifted away |
| 265 | // intially are all 1. For 80 bit floats this is 128 (bitstype size) - 64 | |
| 265 | // initially are all 1. For 80 bit floats this is 128 (bitstype size) - 64 | |
| 266 | 266 | // (final mantissa size) - 3 (we shift away the last two bits separately for |
| 267 | 267 | // accuracy, and the most significant bit is ignored.) = 61 bits. Similarly, |
| 268 | 268 | // it's 12 bits for 128 bit floats in this case. |
| ... | ... | @@ -680,17 +680,15 @@ template <> LIBC_INLINE constexpr int32_t get_lower_bound<double>() { |
| 680 | 680 | // accuracy. |
| 681 | 681 | template <typename T, typename CharType> |
| 682 | 682 | LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float( |
| 683 | ExpandedFloat<T> init_num, bool truncated, RoundDirection round, | |
| 684 | const CharType *__restrict numStart, | |
| 683 | ExpandedFloat<T> init_num, [[maybe_unused]] bool truncated, | |
| 684 | RoundDirection round, const CharType *__restrict numStart, | |
| 685 | 685 | const size_t num_len = cpp::numeric_limits<size_t>::max()) { |
| 686 | 686 | using FPBits = typename fputil::FPBits<T>; |
| 687 | using StorageType = typename FPBits::StorageType; | |
| 688 | 687 | |
| 689 | StorageType mantissa = init_num.mantissa; | |
| 690 | 688 | int32_t exp10 = init_num.exponent; |
| 691 | 689 | |
| 692 | 690 | FloatConvertReturn<T> output; |
| 693 | cpp::optional<ExpandedFloat<T>> opt_output; | |
| 691 | [[maybe_unused]] cpp::optional<ExpandedFloat<T>> opt_output; | |
| 694 | 692 | |
| 695 | 693 | // If the exponent is too large and can't be represented in this size of |
| 696 | 694 | // float, return inf. These bounds are relatively loose, but are mostly |
| ... | ... | @@ -725,6 +723,8 @@ LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float( |
| 725 | 723 | |
| 726 | 724 | #ifndef LIBC_COPT_STRTOFLOAT_DISABLE_EISEL_LEMIRE |
| 727 | 725 | // Try Eisel-Lemire |
| 726 | using StorageType = typename FPBits::StorageType; | |
| 727 | StorageType mantissa = init_num.mantissa; | |
| 728 | 728 | opt_output = eisel_lemire<T>(init_num, round); |
| 729 | 729 | if (opt_output.has_value()) { |
| 730 | 730 | if (!truncated) { |
| ... | ... | @@ -1093,7 +1093,7 @@ hexadecimal_string_to_float(const CharType *__restrict src, |
| 1093 | 1093 | } |
| 1094 | 1094 | |
| 1095 | 1095 | template <typename T, typename CharType> |
| 1096 | LIBC_INLINE typename fputil::FPBits<T>::StorageType | |
| 1096 | LIBC_INLINE constexpr typename fputil::FPBits<T>::StorageType | |
| 1097 | 1097 | nan_mantissa_from_ncharseq(const CharType *str, size_t len) { |
| 1098 | 1098 | using FPBits = typename fputil::FPBits<T>; |
| 1099 | 1099 | using StorageType = typename FPBits::StorageType; |
| ... | ... | @@ -1129,7 +1129,9 @@ strtofloatingpoint(const CharType *__restrict src) { |
| 1129 | 1129 | |
| 1130 | 1130 | size_t index = first_non_whitespace(src); |
| 1131 | 1131 | int sign = get_sign(src + index); |
| 1132 | #ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 1132 | 1133 | bool is_positive = (sign >= 0); |
| 1134 | #endif | |
| 1133 | 1135 | index += (sign != 0); |
| 1134 | 1136 | |
| 1135 | 1137 | if (sign < 0) { |
| ... | ... | @@ -1146,6 +1148,7 @@ strtofloatingpoint(const CharType *__restrict src) { |
| 1146 | 1148 | } |
| 1147 | 1149 | |
| 1148 | 1150 | RoundDirection round_direction = RoundDirection::Nearest; |
| 1151 | #ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 1149 | 1152 | switch (fputil::quick_get_round()) { |
| 1150 | 1153 | case FE_TONEAREST: |
| 1151 | 1154 | round_direction = RoundDirection::Nearest; |
| ... | ... | @@ -1160,6 +1163,7 @@ strtofloatingpoint(const CharType *__restrict src) { |
| 1160 | 1163 | round_direction = RoundDirection::Down; |
| 1161 | 1164 | break; |
| 1162 | 1165 | } |
| 1166 | #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | |
| 1163 | 1167 | |
| 1164 | 1168 | StrToNumResult<ExpandedFloat<T>> parse_result({0, 0}); |
| 1165 | 1169 | if (base == 16) { |
| ... | ... | @@ -1221,7 +1225,8 @@ strtofloatingpoint(const CharType *__restrict src) { |
| 1221 | 1225 | return {result.get_val(), static_cast<ptrdiff_t>(index), error}; |
| 1222 | 1226 | } |
| 1223 | 1227 | |
| 1224 | template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) { | |
| 1228 | template <class T> | |
| 1229 | LIBC_INLINE constexpr StrToNumResult<T> strtonan(const char *arg) { | |
| 1225 | 1230 | using FPBits = typename fputil::FPBits<T>; |
| 1226 | 1231 | using StorageType = typename FPBits::StorageType; |
| 1227 | 1232 |
lib/libcxx/libc/src/__support/str_to_integer.h+21-2| ... | ... | @@ -33,7 +33,7 @@ namespace internal { |
| 33 | 33 | // Returns the idx to the first character in src that is not a whitespace |
| 34 | 34 | // character (as determined by isspace()) |
| 35 | 35 | template <typename CharType> |
| 36 | LIBC_INLINE size_t | |
| 36 | LIBC_INLINE constexpr size_t | |
| 37 | 37 | first_non_whitespace(const CharType *__restrict src, |
| 38 | 38 | size_t src_len = cpp::numeric_limits<size_t>::max()) { |
| 39 | 39 | size_t src_cur = 0; |
| ... | ... | @@ -65,6 +65,18 @@ LIBC_INLINE static bool is_hex_start(const CharType *__restrict src, |
| 65 | 65 | b36_char_to_int(src[2]) < 16; |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | // checks if the next 3 characters of the string pointer are the start of a | |
| 69 | // binary number. Does not advance the string pointer. | |
| 70 | template <typename CharType> | |
| 71 | LIBC_INLINE static bool is_binary_start(const CharType *__restrict src, | |
| 72 | size_t src_len) { | |
| 73 | if (src_len < 3) | |
| 74 | return false; | |
| 75 | return is_char_or_wchar(src[0], '0', L'0') && | |
| 76 | is_char_or_wchar(tolower(src[1]), 'b', L'b') && isalnum(src[2]) && | |
| 77 | b36_char_to_int(src[2]) < 2; | |
| 78 | } | |
| 79 | ||
| 68 | 80 | // Takes the address of the string pointer and parses the base from the start of |
| 69 | 81 | // it. |
| 70 | 82 | template <typename CharType> |
| ... | ... | @@ -75,6 +87,10 @@ LIBC_INLINE static int infer_base(const CharType *__restrict src, |
| 75 | 87 | // with values 10 through 15 respectively." (C standard 6.4.4.1) |
| 76 | 88 | if (is_hex_start(src, src_len)) |
| 77 | 89 | return 16; |
| 90 | // A binary number is defined as "the prefix 0b or 0B optionally followed | |
| 91 | // by a sequence of letters and digits." (C standard 7.24.1.7) | |
| 92 | if (is_binary_start(src, src_len)) | |
| 93 | return 2; | |
| 78 | 94 | // An octal number is defined as "the prefix 0 optionally followed by a |
| 79 | 95 | // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any |
| 80 | 96 | // number that starts with 0, including just 0, is an octal number. |
| ... | ... | @@ -94,7 +110,7 @@ LIBC_INLINE static int infer_base(const CharType *__restrict src, |
| 94 | 110 | // Takes a pointer to a string and the base to convert to. This function is used |
| 95 | 111 | // as the backend for all of the string to int functions. |
| 96 | 112 | template <typename T, typename CharType> |
| 97 | LIBC_INLINE StrToNumResult<T> | |
| 113 | LIBC_INLINE constexpr StrToNumResult<T> | |
| 98 | 114 | strtointeger(const CharType *__restrict src, int base, |
| 99 | 115 | const size_t src_len = cpp::numeric_limits<size_t>::max()) { |
| 100 | 116 | using ResultType = make_integral_or_big_int_unsigned_t<T>; |
| ... | ... | @@ -120,6 +136,9 @@ strtointeger(const CharType *__restrict src, int base, |
| 120 | 136 | if (base == 16 && is_hex_start(src + src_cur, src_len - src_cur)) |
| 121 | 137 | src_cur = src_cur + 2; |
| 122 | 138 | |
| 139 | if (base == 2 && is_binary_start(src + src_cur, src_len - src_cur)) | |
| 140 | src_cur = src_cur + 2; | |
| 141 | ||
| 123 | 142 | constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>; |
| 124 | 143 | ResultType constexpr NEGATIVE_MAX = |
| 125 | 144 | !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1 |
lib/libcxx/libc/src/__support/wctype/wctype_classification_utils.h created+66| ... | ... | @@ -0,0 +1,66 @@ |
| 1 | //===-- Utils for wctype classification functions ---------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | // DO NOT EDIT MANUALLY. | |
| 9 | // This file is generated by libc/utils/wctype_utils scripts. | |
| 10 | ||
| 11 | #ifndef LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CLASSIFICATION_UTILS_H | |
| 12 | #define LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CLASSIFICATION_UTILS_H | |
| 13 | ||
| 14 | #include "hdr/stdint_proxy.h" | |
| 15 | #include "hdr/types/wchar_t.h" | |
| 16 | #include "src/__support/CPP/limits.h" | |
| 17 | #include "src/__support/libc_assert.h" | |
| 18 | #include "src/__support/macros/attributes.h" | |
| 19 | #include "src/__support/macros/config.h" | |
| 20 | ||
| 21 | namespace LIBC_NAMESPACE_DECL { | |
| 22 | ||
| 23 | // Property flags for Unicode categories | |
| 24 | enum PropertyFlag : uint8_t { | |
| 25 | UPPER = 1 << 0, | |
| 26 | LOWER = 1 << 1, | |
| 27 | ALPHA = 1 << 2, | |
| 28 | SPACE = 1 << 3, | |
| 29 | PRINT = 1 << 4, | |
| 30 | BLANK = 1 << 5, | |
| 31 | CNTRL = 1 << 6, | |
| 32 | PUNCT = 1 << 7, | |
| 33 | }; | |
| 34 | ||
| 35 | static_assert(4352 <= cpp::numeric_limits<unsigned short>::max()); | |
| 36 | static_assert(39168 <= cpp::numeric_limits<unsigned short>::max()); | |
| 37 | ||
| 38 | LIBC_INLINE_VAR constexpr uint16_t LEVEL1_SIZE = 4352; | |
| 39 | LIBC_INLINE_VAR constexpr uint16_t LEVEL2_SIZE = 39168; | |
| 40 | ||
| 41 | // Level 1 table: indexed by (codepoint >> 8), stores level2 block offsets | |
| 42 | extern const uint16_t LEVEL1[LEVEL1_SIZE]; | |
| 43 | ||
| 44 | // Level 2 table: blocks of 256 property flags | |
| 45 | extern const uint8_t LEVEL2[LEVEL2_SIZE]; | |
| 46 | ||
| 47 | // Returns the Unicode property flag for a given wide character. | |
| 48 | LIBC_INLINE uint8_t lookup_properties(const wchar_t wc) { | |
| 49 | // Out of Unicode range | |
| 50 | if (static_cast<uint32_t>(wc) > 0x10FFFF) { | |
| 51 | return 0; | |
| 52 | } | |
| 53 | ||
| 54 | uint16_t l1_idx = static_cast<uint16_t>(wc >> 8); | |
| 55 | LIBC_ASSERT(l1_idx < LEVEL1_SIZE); | |
| 56 | ||
| 57 | uint16_t l2_offset = LEVEL1[l1_idx]; | |
| 58 | uint16_t l2_idx = l2_offset + (wc & 0xFF); | |
| 59 | LIBC_ASSERT(l2_idx < LEVEL2_SIZE); | |
| 60 | ||
| 61 | return LEVEL2[l2_idx]; | |
| 62 | } | |
| 63 | ||
| 64 | } // namespace LIBC_NAMESPACE_DECL | |
| 65 | ||
| 66 | #endif // LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CLASSIFICATION_UTILS_H |
lib/libcxx/libc/src/__support/wctype/wctype_conversion_utils.h created+34| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | //===----------------------------------------------------------------------===// | |
| 8 | /// | |
| 9 | /// \file | |
| 10 | /// Interface for wctype conversion functions. | |
| 11 | /// | |
| 12 | //===----------------------------------------------------------------------===// | |
| 13 | ||
| 14 | #ifndef LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CONVERSION_UTILS_H | |
| 15 | #define LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CONVERSION_UTILS_H | |
| 16 | ||
| 17 | #include "hdr/types/wchar_t.h" | |
| 18 | #include "hdr/types/wint_t.h" | |
| 19 | #include "src/__support/macros/attributes.h" | |
| 20 | #include "src/__support/macros/config.h" | |
| 21 | ||
| 22 | namespace LIBC_NAMESPACE_DECL { | |
| 23 | namespace wctype_internal { | |
| 24 | ||
| 25 | // Helper functions for non-ASCII case conversions. | |
| 26 | // These are implemented in wctype_conversion_utils.cpp using the generated | |
| 27 | // maps. | |
| 28 | wint_t tolower(wchar_t wch); | |
| 29 | wint_t toupper(wchar_t wch); | |
| 30 | ||
| 31 | } // namespace wctype_internal | |
| 32 | } // namespace LIBC_NAMESPACE_DECL | |
| 33 | ||
| 34 | #endif // LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CONVERSION_UTILS_H |
lib/libcxx/libc/src/__support/wctype_utils.h+351-137| ... | ... | @@ -13,6 +13,18 @@ |
| 13 | 13 | #include "src/__support/macros/attributes.h" // LIBC_INLINE |
| 14 | 14 | #include "src/__support/macros/config.h" |
| 15 | 15 | |
| 16 | #define LIBC_WCTYPE_MODE_ASCII 0 | |
| 17 | #define LIBC_WCTYPE_MODE_UTF8 1 | |
| 18 | ||
| 19 | #ifndef LIBC_CONF_WCTYPE_MODE | |
| 20 | #define LIBC_CONF_WCTYPE_MODE LIBC_WCTYPE_MODE_ASCII | |
| 21 | #endif | |
| 22 | ||
| 23 | #if LIBC_CONF_WCTYPE_MODE == LIBC_WCTYPE_MODE_UTF8 | |
| 24 | #include "src/__support/wctype/wctype_classification_utils.h" | |
| 25 | #include "src/__support/wctype/wctype_conversion_utils.h" | |
| 26 | #endif | |
| 27 | ||
| 16 | 28 | namespace LIBC_NAMESPACE_DECL { |
| 17 | 29 | namespace internal { |
| 18 | 30 | |
| ... | ... | @@ -38,8 +50,8 @@ namespace internal { |
| 38 | 50 | // This assumes the character ranges are contiguous, which they aren't in |
| 39 | 51 | // EBCDIC. Technically we could use some smaller ranges, but that's even harder |
| 40 | 52 | // to read. |
| 41 | ||
| 42 | LIBC_INLINE static constexpr bool islower(wchar_t wch) { | |
| 53 | namespace ascii { | |
| 54 | LIBC_INLINE constexpr bool islower(wchar_t wch) { | |
| 43 | 55 | switch (wch) { |
| 44 | 56 | case L'a': |
| 45 | 57 | case L'b': |
| ... | ... | @@ -73,7 +85,7 @@ LIBC_INLINE static constexpr bool islower(wchar_t wch) { |
| 73 | 85 | } |
| 74 | 86 | } |
| 75 | 87 | |
| 76 | LIBC_INLINE static constexpr bool isupper(wchar_t wch) { | |
| 88 | LIBC_INLINE constexpr bool isupper(wchar_t wch) { | |
| 77 | 89 | switch (wch) { |
| 78 | 90 | case L'A': |
| 79 | 91 | case L'B': |
| ... | ... | @@ -107,7 +119,7 @@ LIBC_INLINE static constexpr bool isupper(wchar_t wch) { |
| 107 | 119 | } |
| 108 | 120 | } |
| 109 | 121 | |
| 110 | LIBC_INLINE static constexpr bool isdigit(wchar_t wch) { | |
| 122 | LIBC_INLINE constexpr bool isdigit(wchar_t wch) { | |
| 111 | 123 | switch (wch) { |
| 112 | 124 | case L'0': |
| 113 | 125 | case L'1': |
| ... | ... | @@ -125,125 +137,169 @@ LIBC_INLINE static constexpr bool isdigit(wchar_t wch) { |
| 125 | 137 | } |
| 126 | 138 | } |
| 127 | 139 | |
| 128 | LIBC_INLINE static constexpr wchar_t tolower(wchar_t wch) { | |
| 140 | LIBC_INLINE constexpr bool isalpha(wchar_t wch) { | |
| 129 | 141 | switch (wch) { |
| 142 | case L'a': | |
| 143 | case L'b': | |
| 144 | case L'c': | |
| 145 | case L'd': | |
| 146 | case L'e': | |
| 147 | case L'f': | |
| 148 | case L'g': | |
| 149 | case L'h': | |
| 150 | case L'i': | |
| 151 | case L'j': | |
| 152 | case L'k': | |
| 153 | case L'l': | |
| 154 | case L'm': | |
| 155 | case L'n': | |
| 156 | case L'o': | |
| 157 | case L'p': | |
| 158 | case L'q': | |
| 159 | case L'r': | |
| 160 | case L's': | |
| 161 | case L't': | |
| 162 | case L'u': | |
| 163 | case L'v': | |
| 164 | case L'w': | |
| 165 | case L'x': | |
| 166 | case L'y': | |
| 167 | case L'z': | |
| 130 | 168 | case L'A': |
| 131 | return L'a'; | |
| 132 | 169 | case L'B': |
| 133 | return L'b'; | |
| 134 | 170 | case L'C': |
| 135 | return L'c'; | |
| 136 | 171 | case L'D': |
| 137 | return L'd'; | |
| 138 | 172 | case L'E': |
| 139 | return L'e'; | |
| 140 | 173 | case L'F': |
| 141 | return L'f'; | |
| 142 | 174 | case L'G': |
| 143 | return L'g'; | |
| 144 | 175 | case L'H': |
| 145 | return L'h'; | |
| 146 | 176 | case L'I': |
| 147 | return L'i'; | |
| 148 | 177 | case L'J': |
| 149 | return L'j'; | |
| 150 | 178 | case L'K': |
| 151 | return L'k'; | |
| 152 | 179 | case L'L': |
| 153 | return L'l'; | |
| 154 | 180 | case L'M': |
| 155 | return L'm'; | |
| 156 | 181 | case L'N': |
| 157 | return L'n'; | |
| 158 | 182 | case L'O': |
| 159 | return L'o'; | |
| 160 | 183 | case L'P': |
| 161 | return L'p'; | |
| 162 | 184 | case L'Q': |
| 163 | return L'q'; | |
| 164 | 185 | case L'R': |
| 165 | return L'r'; | |
| 166 | 186 | case L'S': |
| 167 | return L's'; | |
| 168 | 187 | case L'T': |
| 169 | return L't'; | |
| 170 | 188 | case L'U': |
| 171 | return L'u'; | |
| 172 | 189 | case L'V': |
| 173 | return L'v'; | |
| 174 | 190 | case L'W': |
| 175 | return L'w'; | |
| 176 | 191 | case L'X': |
| 177 | return L'x'; | |
| 178 | 192 | case L'Y': |
| 179 | return L'y'; | |
| 180 | 193 | case L'Z': |
| 181 | return L'z'; | |
| 194 | return true; | |
| 182 | 195 | default: |
| 183 | return wch; | |
| 196 | return false; | |
| 184 | 197 | } |
| 185 | 198 | } |
| 186 | 199 | |
| 187 | LIBC_INLINE static constexpr wchar_t toupper(wchar_t wch) { | |
| 200 | LIBC_INLINE constexpr bool isalnum(wchar_t wch) { | |
| 188 | 201 | switch (wch) { |
| 189 | 202 | case L'a': |
| 190 | return L'A'; | |
| 191 | 203 | case L'b': |
| 192 | return L'B'; | |
| 193 | 204 | case L'c': |
| 194 | return L'C'; | |
| 195 | 205 | case L'd': |
| 196 | return L'D'; | |
| 197 | 206 | case L'e': |
| 198 | return L'E'; | |
| 199 | 207 | case L'f': |
| 200 | return L'F'; | |
| 201 | 208 | case L'g': |
| 202 | return L'G'; | |
| 203 | 209 | case L'h': |
| 204 | return L'H'; | |
| 205 | 210 | case L'i': |
| 206 | return L'I'; | |
| 207 | 211 | case L'j': |
| 208 | return L'J'; | |
| 209 | 212 | case L'k': |
| 210 | return L'K'; | |
| 211 | 213 | case L'l': |
| 212 | return L'L'; | |
| 213 | 214 | case L'm': |
| 214 | return L'M'; | |
| 215 | 215 | case L'n': |
| 216 | return L'N'; | |
| 217 | 216 | case L'o': |
| 218 | return L'O'; | |
| 219 | 217 | case L'p': |
| 220 | return L'P'; | |
| 221 | 218 | case L'q': |
| 222 | return L'Q'; | |
| 223 | 219 | case L'r': |
| 224 | return L'R'; | |
| 225 | 220 | case L's': |
| 226 | return L'S'; | |
| 227 | 221 | case L't': |
| 228 | return L'T'; | |
| 229 | 222 | case L'u': |
| 230 | return L'U'; | |
| 231 | 223 | case L'v': |
| 232 | return L'V'; | |
| 233 | 224 | case L'w': |
| 234 | return L'W'; | |
| 235 | 225 | case L'x': |
| 236 | return L'X'; | |
| 237 | 226 | case L'y': |
| 238 | return L'Y'; | |
| 239 | 227 | case L'z': |
| 240 | return L'Z'; | |
| 228 | case L'A': | |
| 229 | case L'B': | |
| 230 | case L'C': | |
| 231 | case L'D': | |
| 232 | case L'E': | |
| 233 | case L'F': | |
| 234 | case L'G': | |
| 235 | case L'H': | |
| 236 | case L'I': | |
| 237 | case L'J': | |
| 238 | case L'K': | |
| 239 | case L'L': | |
| 240 | case L'M': | |
| 241 | case L'N': | |
| 242 | case L'O': | |
| 243 | case L'P': | |
| 244 | case L'Q': | |
| 245 | case L'R': | |
| 246 | case L'S': | |
| 247 | case L'T': | |
| 248 | case L'U': | |
| 249 | case L'V': | |
| 250 | case L'W': | |
| 251 | case L'X': | |
| 252 | case L'Y': | |
| 253 | case L'Z': | |
| 254 | case L'0': | |
| 255 | case L'1': | |
| 256 | case L'2': | |
| 257 | case L'3': | |
| 258 | case L'4': | |
| 259 | case L'5': | |
| 260 | case L'6': | |
| 261 | case L'7': | |
| 262 | case L'8': | |
| 263 | case L'9': | |
| 264 | return true; | |
| 241 | 265 | default: |
| 242 | return wch; | |
| 266 | return false; | |
| 267 | } | |
| 268 | } | |
| 269 | ||
| 270 | LIBC_INLINE constexpr bool isspace(wchar_t wch) { | |
| 271 | switch (wch) { | |
| 272 | case L' ': | |
| 273 | case L'\t': | |
| 274 | case L'\n': | |
| 275 | case L'\v': | |
| 276 | case L'\f': | |
| 277 | case L'\r': | |
| 278 | return true; | |
| 279 | default: | |
| 280 | return false; | |
| 281 | } | |
| 282 | } | |
| 283 | ||
| 284 | LIBC_INLINE constexpr bool isblank(wchar_t wch) { | |
| 285 | switch (wch) { | |
| 286 | case L' ': | |
| 287 | case L'\t': | |
| 288 | return true; | |
| 289 | default: | |
| 290 | return false; | |
| 243 | 291 | } |
| 244 | 292 | } |
| 245 | 293 | |
| 246 | LIBC_INLINE static constexpr bool isalpha(wchar_t wch) { | |
| 294 | LIBC_INLINE constexpr bool isgraph(wchar_t wch) { | |
| 295 | return 0x20 < wch && wch < 0x7f; | |
| 296 | } | |
| 297 | ||
| 298 | LIBC_INLINE constexpr bool isprint(wchar_t wch) { | |
| 299 | return (static_cast<unsigned>(wch) - ' ') < 95; | |
| 300 | } | |
| 301 | ||
| 302 | LIBC_INLINE constexpr bool isxdigit(wchar_t wch) { | |
| 247 | 303 | switch (wch) { |
| 248 | 304 | case L'a': |
| 249 | 305 | case L'b': |
| ... | ... | @@ -251,129 +307,301 @@ LIBC_INLINE static constexpr bool isalpha(wchar_t wch) { |
| 251 | 307 | case L'd': |
| 252 | 308 | case L'e': |
| 253 | 309 | case L'f': |
| 254 | case L'g': | |
| 255 | case L'h': | |
| 256 | case L'i': | |
| 257 | case L'j': | |
| 258 | case L'k': | |
| 259 | case L'l': | |
| 260 | case L'm': | |
| 261 | case L'n': | |
| 262 | case L'o': | |
| 263 | case L'p': | |
| 264 | case L'q': | |
| 265 | case L'r': | |
| 266 | case L's': | |
| 267 | case L't': | |
| 268 | case L'u': | |
| 269 | case L'v': | |
| 270 | case L'w': | |
| 271 | case L'x': | |
| 272 | case L'y': | |
| 273 | case L'z': | |
| 274 | 310 | case L'A': |
| 275 | 311 | case L'B': |
| 276 | 312 | case L'C': |
| 277 | 313 | case L'D': |
| 278 | 314 | case L'E': |
| 279 | 315 | case L'F': |
| 316 | case L'0': | |
| 317 | case L'1': | |
| 318 | case L'2': | |
| 319 | case L'3': | |
| 320 | case L'4': | |
| 321 | case L'5': | |
| 322 | case L'6': | |
| 323 | case L'7': | |
| 324 | case L'8': | |
| 325 | case L'9': | |
| 326 | return true; | |
| 327 | default: | |
| 328 | return false; | |
| 329 | } | |
| 330 | } | |
| 331 | ||
| 332 | LIBC_INLINE constexpr bool iscntrl(wchar_t wch) { | |
| 333 | return (wch < 0x20 || wch == 0x7f); | |
| 334 | } | |
| 335 | ||
| 336 | LIBC_INLINE constexpr bool ispunct(wchar_t wch) { | |
| 337 | return !isalnum(wch) && isgraph(wch); | |
| 338 | } | |
| 339 | ||
| 340 | LIBC_INLINE constexpr wchar_t tolower(wchar_t wch) { | |
| 341 | switch (wch) { | |
| 342 | case L'A': | |
| 343 | return L'a'; | |
| 344 | case L'B': | |
| 345 | return L'b'; | |
| 346 | case L'C': | |
| 347 | return L'c'; | |
| 348 | case L'D': | |
| 349 | return L'd'; | |
| 350 | case L'E': | |
| 351 | return L'e'; | |
| 352 | case L'F': | |
| 353 | return L'f'; | |
| 280 | 354 | case L'G': |
| 355 | return L'g'; | |
| 281 | 356 | case L'H': |
| 357 | return L'h'; | |
| 282 | 358 | case L'I': |
| 359 | return L'i'; | |
| 283 | 360 | case L'J': |
| 361 | return L'j'; | |
| 284 | 362 | case L'K': |
| 363 | return L'k'; | |
| 285 | 364 | case L'L': |
| 365 | return L'l'; | |
| 286 | 366 | case L'M': |
| 367 | return L'm'; | |
| 287 | 368 | case L'N': |
| 369 | return L'n'; | |
| 288 | 370 | case L'O': |
| 371 | return L'o'; | |
| 289 | 372 | case L'P': |
| 373 | return L'p'; | |
| 290 | 374 | case L'Q': |
| 375 | return L'q'; | |
| 291 | 376 | case L'R': |
| 377 | return L'r'; | |
| 292 | 378 | case L'S': |
| 379 | return L's'; | |
| 293 | 380 | case L'T': |
| 381 | return L't'; | |
| 294 | 382 | case L'U': |
| 383 | return L'u'; | |
| 295 | 384 | case L'V': |
| 385 | return L'v'; | |
| 296 | 386 | case L'W': |
| 387 | return L'w'; | |
| 297 | 388 | case L'X': |
| 389 | return L'x'; | |
| 298 | 390 | case L'Y': |
| 391 | return L'y'; | |
| 299 | 392 | case L'Z': |
| 300 | return true; | |
| 393 | return L'z'; | |
| 301 | 394 | default: |
| 302 | return false; | |
| 395 | return wch; | |
| 303 | 396 | } |
| 304 | 397 | } |
| 305 | 398 | |
| 306 | LIBC_INLINE static constexpr bool isalnum(wchar_t wch) { | |
| 399 | LIBC_INLINE constexpr wchar_t toupper(wchar_t wch) { | |
| 307 | 400 | switch (wch) { |
| 308 | 401 | case L'a': |
| 402 | return L'A'; | |
| 309 | 403 | case L'b': |
| 404 | return L'B'; | |
| 310 | 405 | case L'c': |
| 406 | return L'C'; | |
| 311 | 407 | case L'd': |
| 408 | return L'D'; | |
| 312 | 409 | case L'e': |
| 410 | return L'E'; | |
| 313 | 411 | case L'f': |
| 412 | return L'F'; | |
| 314 | 413 | case L'g': |
| 414 | return L'G'; | |
| 315 | 415 | case L'h': |
| 416 | return L'H'; | |
| 316 | 417 | case L'i': |
| 418 | return L'I'; | |
| 317 | 419 | case L'j': |
| 420 | return L'J'; | |
| 318 | 421 | case L'k': |
| 422 | return L'K'; | |
| 319 | 423 | case L'l': |
| 424 | return L'L'; | |
| 320 | 425 | case L'm': |
| 426 | return L'M'; | |
| 321 | 427 | case L'n': |
| 428 | return L'N'; | |
| 322 | 429 | case L'o': |
| 430 | return L'O'; | |
| 323 | 431 | case L'p': |
| 432 | return L'P'; | |
| 324 | 433 | case L'q': |
| 434 | return L'Q'; | |
| 325 | 435 | case L'r': |
| 436 | return L'R'; | |
| 326 | 437 | case L's': |
| 438 | return L'S'; | |
| 327 | 439 | case L't': |
| 440 | return L'T'; | |
| 328 | 441 | case L'u': |
| 442 | return L'U'; | |
| 329 | 443 | case L'v': |
| 444 | return L'V'; | |
| 330 | 445 | case L'w': |
| 446 | return L'W'; | |
| 331 | 447 | case L'x': |
| 448 | return L'X'; | |
| 332 | 449 | case L'y': |
| 450 | return L'Y'; | |
| 333 | 451 | case L'z': |
| 334 | case L'A': | |
| 335 | case L'B': | |
| 336 | case L'C': | |
| 337 | case L'D': | |
| 338 | case L'E': | |
| 339 | case L'F': | |
| 340 | case L'G': | |
| 341 | case L'H': | |
| 342 | case L'I': | |
| 343 | case L'J': | |
| 344 | case L'K': | |
| 345 | case L'L': | |
| 346 | case L'M': | |
| 347 | case L'N': | |
| 348 | case L'O': | |
| 349 | case L'P': | |
| 350 | case L'Q': | |
| 351 | case L'R': | |
| 352 | case L'S': | |
| 353 | case L'T': | |
| 354 | case L'U': | |
| 355 | case L'V': | |
| 356 | case L'W': | |
| 357 | case L'X': | |
| 358 | case L'Y': | |
| 359 | case L'Z': | |
| 360 | case L'0': | |
| 361 | case L'1': | |
| 362 | case L'2': | |
| 363 | case L'3': | |
| 364 | case L'4': | |
| 365 | case L'5': | |
| 366 | case L'6': | |
| 367 | case L'7': | |
| 368 | case L'8': | |
| 369 | case L'9': | |
| 370 | return true; | |
| 452 | return L'Z'; | |
| 371 | 453 | default: |
| 372 | return false; | |
| 454 | return wch; | |
| 455 | } | |
| 456 | } | |
| 457 | ||
| 458 | } // namespace ascii | |
| 459 | ||
| 460 | LIBC_INLINE constexpr bool islower(wchar_t wch) { | |
| 461 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 462 | return ascii::islower(wch); | |
| 463 | #else | |
| 464 | if (static_cast<uint32_t>(wch) < 128) { | |
| 465 | return ascii::islower(wch); | |
| 466 | } | |
| 467 | return lookup_properties(wch) & PropertyFlag::LOWER; | |
| 468 | #endif | |
| 469 | } | |
| 470 | ||
| 471 | LIBC_INLINE constexpr bool isupper(wchar_t wch) { | |
| 472 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 473 | return ascii::isupper(wch); | |
| 474 | #else | |
| 475 | if (static_cast<uint32_t>(wch) < 128) { | |
| 476 | return ascii::isupper(wch); | |
| 477 | } | |
| 478 | return lookup_properties(wch) & PropertyFlag::UPPER; | |
| 479 | #endif | |
| 480 | } | |
| 481 | ||
| 482 | LIBC_INLINE constexpr bool isdigit(wchar_t wch) { | |
| 483 | // In C.UT8, only ASCII digits are considered digits | |
| 484 | return ascii::isdigit(wch); | |
| 485 | } | |
| 486 | ||
| 487 | LIBC_INLINE constexpr bool isalpha(wchar_t wch) { | |
| 488 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 489 | return ascii::isalpha(wch); | |
| 490 | #else | |
| 491 | if (static_cast<uint32_t>(wch) < 128) { | |
| 492 | return ascii::isalpha(wch); | |
| 493 | } | |
| 494 | return lookup_properties(wch) & PropertyFlag::ALPHA; | |
| 495 | #endif | |
| 496 | } | |
| 497 | ||
| 498 | LIBC_INLINE constexpr bool isalnum(wchar_t wch) { | |
| 499 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 500 | return ascii::isalnum(wch); | |
| 501 | #else | |
| 502 | if (static_cast<uint32_t>(wch) < 128) { | |
| 503 | return ascii::isalnum(wch); | |
| 504 | } | |
| 505 | // Only need to check ALPHA, digit cases are covered by ASCII path | |
| 506 | return lookup_properties(wch) & PropertyFlag::ALPHA; | |
| 507 | #endif | |
| 508 | } | |
| 509 | ||
| 510 | LIBC_INLINE constexpr bool isspace(wchar_t wch) { | |
| 511 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 512 | return ascii::isspace(wch); | |
| 513 | #else | |
| 514 | if (static_cast<uint32_t>(wch) < 128) { | |
| 515 | return ascii::isspace(wch); | |
| 516 | } | |
| 517 | return lookup_properties(wch) & PropertyFlag::SPACE; | |
| 518 | #endif | |
| 519 | } | |
| 520 | ||
| 521 | LIBC_INLINE constexpr bool isblank(wchar_t wch) { | |
| 522 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 523 | return ascii::isblank(wch); | |
| 524 | #else | |
| 525 | if (static_cast<uint32_t>(wch) < 128) { | |
| 526 | return ascii::isblank(wch); | |
| 373 | 527 | } |
| 528 | return lookup_properties(wch) & PropertyFlag::BLANK; | |
| 529 | #endif | |
| 374 | 530 | } |
| 375 | 531 | |
| 376 | LIBC_INLINE static constexpr int b36_char_to_int(wchar_t wch) { | |
| 532 | LIBC_INLINE constexpr bool isgraph(wchar_t wch) { | |
| 533 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 534 | return ascii::isgraph(wch); | |
| 535 | #else | |
| 536 | if (static_cast<uint32_t>(wch) < 128) { | |
| 537 | return ascii::isgraph(wch); | |
| 538 | } | |
| 539 | // print && !space | |
| 540 | return (lookup_properties(wch) & | |
| 541 | (PropertyFlag::PRINT | PropertyFlag::SPACE)) == PropertyFlag::PRINT; | |
| 542 | #endif | |
| 543 | } | |
| 544 | ||
| 545 | LIBC_INLINE constexpr bool isprint(wchar_t wch) { | |
| 546 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 547 | return ascii::isprint(wch); | |
| 548 | #else | |
| 549 | if (static_cast<uint32_t>(wch) < 128) { | |
| 550 | return ascii::isprint(wch); | |
| 551 | } | |
| 552 | return lookup_properties(wch) & PropertyFlag::PRINT; | |
| 553 | #endif | |
| 554 | } | |
| 555 | LIBC_INLINE constexpr bool isxdigit(wchar_t wch) { | |
| 556 | // Hexadecimal digits are the same in C.UTF8 as in ASCII | |
| 557 | return ascii::isxdigit(wch); | |
| 558 | } | |
| 559 | ||
| 560 | LIBC_INLINE constexpr bool iscntrl(wchar_t wch) { | |
| 561 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 562 | return ascii::iscntrl(wch); | |
| 563 | #else | |
| 564 | if (static_cast<uint32_t>(wch) < 128) { | |
| 565 | return ascii::iscntrl(wch); | |
| 566 | } | |
| 567 | return lookup_properties(wch) & PropertyFlag::CNTRL; | |
| 568 | #endif | |
| 569 | } | |
| 570 | ||
| 571 | LIBC_INLINE constexpr bool ispunct(wchar_t wch) { | |
| 572 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 573 | return ascii::ispunct(wch); | |
| 574 | #else | |
| 575 | if (static_cast<uint32_t>(wch) < 128) { | |
| 576 | return ascii::ispunct(wch); | |
| 577 | } | |
| 578 | return lookup_properties(wch) & PropertyFlag::PUNCT; | |
| 579 | #endif | |
| 580 | } | |
| 581 | ||
| 582 | LIBC_INLINE constexpr wchar_t tolower(wchar_t wch) { | |
| 583 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 584 | return ascii::tolower(wch); | |
| 585 | #else | |
| 586 | if (static_cast<uint32_t>(wch) < 128) { | |
| 587 | return ascii::tolower(wch); | |
| 588 | } | |
| 589 | return static_cast<wchar_t>(wctype_internal::tolower(wch)); | |
| 590 | #endif | |
| 591 | } | |
| 592 | ||
| 593 | LIBC_INLINE constexpr wchar_t toupper(wchar_t wch) { | |
| 594 | #if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8 | |
| 595 | return ascii::toupper(wch); | |
| 596 | #else | |
| 597 | if (static_cast<uint32_t>(wch) < 128) { | |
| 598 | return ascii::toupper(wch); | |
| 599 | } | |
| 600 | return static_cast<wchar_t>(wctype_internal::toupper(wch)); | |
| 601 | #endif | |
| 602 | } | |
| 603 | ||
| 604 | LIBC_INLINE constexpr int b36_char_to_int(wchar_t wch) { | |
| 377 | 605 | switch (wch) { |
| 378 | 606 | case L'0': |
| 379 | 607 | return 0; |
| ... | ... | @@ -561,20 +789,6 @@ LIBC_INLINE static constexpr wchar_t int_to_b36_wchar(int num) { |
| 561 | 789 | } |
| 562 | 790 | } |
| 563 | 791 | |
| 564 | LIBC_INLINE static constexpr bool isspace(wchar_t wch) { | |
| 565 | switch (wch) { | |
| 566 | case L' ': | |
| 567 | case L'\t': | |
| 568 | case L'\n': | |
| 569 | case L'\v': | |
| 570 | case L'\f': | |
| 571 | case L'\r': | |
| 572 | return true; | |
| 573 | default: | |
| 574 | return false; | |
| 575 | } | |
| 576 | } | |
| 577 | ||
| 578 | 792 | // An overload which provides a way to compare input with specific character |
| 579 | 793 | // values, when input can be of a regular or a wide character type. |
| 580 | 794 | LIBC_INLINE static constexpr bool |