| 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,6 +25,6 @@ |
| 25 | 25 | ||
| 26 | #include <errno.h> | 26 | #include <errno.h> |
| 27 | 27 | ||
| 28 | #endif // LLVM_LIBC_FULL_BUILD | 28 | #endif // LIBC_FULL_BUILD |
| 29 | 29 | ||
| 30 | #endif // LLVM_LIBC_HDR_ERRNO_MACROS_H | 30 | #endif // LLVM_LIBC_HDR_ERRNO_MACROS_H |
lib/libcxx/libc/hdr/fenv_macros.h+1-1| ... | @@ -56,6 +56,6 @@ | ... | @@ -56,6 +56,6 @@ |
| 56 | #define FE_UPWARD 0x800 | 56 | #define FE_UPWARD 0x800 |
| 57 | #endif // FE_UPWARD | 57 | #endif // FE_UPWARD |
| 58 | 58 | ||
| 59 | #endif // LLVM_LIBC_FULL_BUILD | 59 | #endif // LIBC_FULL_BUILD |
| 60 | 60 | ||
| 61 | #endif // LLVM_LIBC_HDR_FENV_MACROS_H | 61 | #endif // LLVM_LIBC_HDR_FENV_MACROS_H |
lib/libcxx/libc/hdr/float_macros.h+1-1| ... | @@ -17,6 +17,6 @@ | ... | @@ -17,6 +17,6 @@ |
| 17 | 17 | ||
| 18 | #include <float.h> | 18 | #include <float.h> |
| 19 | 19 | ||
| 20 | #endif // LLVM_LIBC_FULL_BUILD | 20 | #endif // LIBC_FULL_BUILD |
| 21 | 21 | ||
| 22 | #endif // LLVM_LIBC_HDR_FLOAT_MACROS_H | 22 | #endif // LLVM_LIBC_HDR_FLOAT_MACROS_H |
lib/libcxx/libc/hdr/limits_macros.h+1-1| ... | @@ -17,6 +17,6 @@ | ... | @@ -17,6 +17,6 @@ |
| 17 | 17 | ||
| 18 | #include <limits.h> | 18 | #include <limits.h> |
| 19 | 19 | ||
| 20 | #endif // LLVM_LIBC_FULL_BUILD | 20 | #endif // LIBC_FULL_BUILD |
| 21 | 21 | ||
| 22 | #endif // LLVM_LIBC_HDR_LIMITS_MACROS_H | 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,6 +18,6 @@ |
| 18 | 18 | ||
| 19 | #include "hdr/wchar_overlay.h" | 19 | #include "hdr/wchar_overlay.h" |
| 20 | 20 | ||
| 21 | #endif // LLVM_LIBC_FULL_BUILD | 21 | #endif // LIBC_FULL_BUILD |
| 22 | 22 | ||
| 23 | #endif // LLVM_LIBC_HDR_TYPES_WCHAR_T_H | 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,7 +27,7 @@ |
| 27 | #define LIBC_TYPES_HAS_CFLOAT128 | 27 | #define LIBC_TYPES_HAS_CFLOAT128 |
| 28 | #endif | 28 | #endif |
| 29 | #elif defined(__GNUC__) | 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 | (__GNUC__ >= 13 || (!defined(__cplusplus))) | 31 | (__GNUC__ >= 13 || (!defined(__cplusplus))) |
| 32 | #define LIBC_TYPES_HAS_CFLOAT128 | 32 | #define LIBC_TYPES_HAS_CFLOAT128 |
| 33 | #endif | 33 | #endif |
lib/libcxx/libc/include/llvm-libc-macros/float-macros.h+6| ... | @@ -9,6 +9,12 @@ | ... | @@ -9,6 +9,12 @@ |
| 9 | #ifndef LLVM_LIBC_MACROS_FLOAT_MACROS_H | 9 | #ifndef LLVM_LIBC_MACROS_FLOAT_MACROS_H |
| 10 | #define LLVM_LIBC_MACROS_FLOAT_MACROS_H | 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 | #ifndef FLT_RADIX | 18 | #ifndef FLT_RADIX |
| 13 | #define FLT_RADIX __FLT_RADIX__ | 19 | #define FLT_RADIX __FLT_RADIX__ |
| 14 | #endif // FLT_RADIX | 20 | #endif // FLT_RADIX |
lib/libcxx/libc/include/llvm-libc-macros/float16-macros.h+2-1| ... | @@ -12,7 +12,8 @@ | ... | @@ -12,7 +12,8 @@ |
| 12 | #include "../llvm-libc-types/float128.h" | 12 | #include "../llvm-libc-types/float128.h" |
| 13 | 13 | ||
| 14 | #if defined(__FLT16_MANT_DIG__) && \ | 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 | !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \ | 17 | !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \ |
| 17 | !defined(_WIN32) | 18 | !defined(_WIN32) |
| 18 | #define LIBC_TYPES_HAS_FLOAT16 | 19 | #define LIBC_TYPES_HAS_FLOAT16 |
lib/libcxx/libc/include/llvm-libc-macros/stdfix-macros.h+1-1| ... | @@ -9,7 +9,7 @@ | ... | @@ -9,7 +9,7 @@ |
| 9 | #ifndef LLVM_LIBC_MACROS_STDFIX_MACROS_H | 9 | #ifndef LLVM_LIBC_MACROS_STDFIX_MACROS_H |
| 10 | #define LLVM_LIBC_MACROS_STDFIX_MACROS_H | 10 | #define LLVM_LIBC_MACROS_STDFIX_MACROS_H |
| 11 | 11 | ||
| 12 | #ifdef __FRACT_FBIT__ | 12 | #if defined(__FRACT_FBIT__) && defined(__clang__) |
| 13 | // _Fract and _Accum types are available | 13 | // _Fract and _Accum types are available |
| 14 | #define LIBC_COMPILER_HAS_FIXED_POINT | 14 | #define LIBC_COMPILER_HAS_FIXED_POINT |
| 15 | #endif // __FRACT_FBIT__ | 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,7 +6,7 @@ |
| 6 | // | 6 | // |
| 7 | //===----------------------------------------------------------------------===// | 7 | //===----------------------------------------------------------------------===// |
| 8 | // This is inspired by LLVM ADT/bit.h header. | 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 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H | 11 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H |
| 12 | #define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H | 12 | #define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H |
| ... | @@ -27,9 +27,14 @@ namespace cpp { | ... | @@ -27,9 +27,14 @@ namespace cpp { |
| 27 | #endif | 27 | #endif |
| 28 | 28 | ||
| 29 | template <unsigned N> | 29 | template <unsigned N> |
| 30 | LIBC_INLINE static void inline_copy(const char *from, char *to) { | 30 | LIBC_INLINE constexpr void inline_copy(const char *from, char *to) { |
| 31 | #if __has_builtin(__builtin_memcpy_inline) | 31 | #if __has_builtin(__builtin_memcpy_inline) && \ |
| 32 | __builtin_memcpy_inline(to, from, N); | 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 | #else | 38 | #else |
| 34 | for (unsigned i = 0; i < N; ++i) | 39 | for (unsigned i = 0; i < N; ++i) |
| 35 | to[i] = from[i]; | 40 | to[i] = from[i]; |
| ... | @@ -39,15 +44,14 @@ LIBC_INLINE static void inline_copy(const char *from, char *to) { | ... | @@ -39,15 +44,14 @@ LIBC_INLINE static void inline_copy(const char *from, char *to) { |
| 39 | // This implementation of bit_cast requires trivially-constructible To, to avoid | 44 | // This implementation of bit_cast requires trivially-constructible To, to avoid |
| 40 | // UB in the implementation. | 45 | // UB in the implementation. |
| 41 | template <typename To, typename From> | 46 | template <typename To, typename From> |
| 42 | LIBC_INLINE constexpr cpp::enable_if_t< | 47 | LIBC_INLINE static constexpr cpp::enable_if_t< |
| 43 | (sizeof(To) == sizeof(From)) && | 48 | (sizeof(To) == sizeof(From)) && |
| 44 | cpp::is_trivially_constructible<To>::value && | 49 | cpp::is_trivially_constructible<To>::value && |
| 45 | cpp::is_trivially_copyable<To>::value && | 50 | cpp::is_trivially_copyable<To>::value && |
| 46 | cpp::is_trivially_copyable<From>::value, | 51 | cpp::is_trivially_copyable<From>::value, |
| 47 | To> | 52 | To> |
| 48 | bit_cast(const From &from) { | 53 | bit_cast(const From &from) { |
| 49 | MSAN_UNPOISON(&from, sizeof(From)); | 54 | #if LIBC_HAS_BUILTIN_BIT_CAST |
| 50 | #if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC) | ||
| 51 | return __builtin_bit_cast(To, from); | 55 | return __builtin_bit_cast(To, from); |
| 52 | #else | 56 | #else |
| 53 | To to{}; | 57 | To to{}; |
| ... | @@ -60,14 +64,12 @@ bit_cast(const From &from) { | ... | @@ -60,14 +64,12 @@ bit_cast(const From &from) { |
| 60 | 64 | ||
| 61 | // The following simple bit copy from a smaller type to maybe-larger type. | 65 | // The following simple bit copy from a smaller type to maybe-larger type. |
| 62 | template <typename To, typename From> | 66 | template <typename To, typename From> |
| 63 | LIBC_INLINE constexpr cpp::enable_if_t< | 67 | LIBC_INLINE cpp::enable_if_t<(sizeof(To) >= sizeof(From)) && |
| 64 | (sizeof(To) >= sizeof(From)) && | 68 | cpp::is_trivially_constructible<To>::value && |
| 65 | cpp::is_trivially_constructible<To>::value && | 69 | cpp::is_trivially_copyable<To>::value && |
| 66 | cpp::is_trivially_copyable<To>::value && | 70 | cpp::is_trivially_copyable<From>::value, |
| 67 | cpp::is_trivially_copyable<From>::value, | 71 | void> |
| 68 | void> | ||
| 69 | bit_copy(const From &from, To &to) { | 72 | bit_copy(const From &from, To &to) { |
| 70 | MSAN_UNPOISON(&from, sizeof(From)); | ||
| 71 | char *dst = reinterpret_cast<char *>(&to); | 73 | char *dst = reinterpret_cast<char *>(&to); |
| 72 | const char *src = reinterpret_cast<const char *>(&from); | 74 | const char *src = reinterpret_cast<const char *>(&from); |
| 73 | inline_copy<sizeof(From)>(src, dst); | 75 | inline_copy<sizeof(From)>(src, dst); |
| ... | @@ -330,6 +332,36 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) | ... | @@ -330,6 +332,36 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) |
| 330 | #endif // __builtin_popcountg | 332 | #endif // __builtin_popcountg |
| 331 | #undef ADD_SPECIALIZATION | 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 | } // namespace cpp | 365 | } // namespace cpp |
| 334 | } // namespace LIBC_NAMESPACE_DECL | 366 | } // namespace LIBC_NAMESPACE_DECL |
| 335 | 367 |
lib/libcxx/libc/src/__support/CPP/iterator.h+29| ... | @@ -9,6 +9,7 @@ | ... | @@ -9,6 +9,7 @@ |
| 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H | 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H |
| 10 | #define LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H | 10 | #define LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H |
| 11 | 11 | ||
| 12 | #include "hdr/types/size_t.h" | ||
| 12 | #include "src/__support/CPP/type_traits/enable_if.h" | 13 | #include "src/__support/CPP/type_traits/enable_if.h" |
| 13 | #include "src/__support/CPP/type_traits/is_convertible.h" | 14 | #include "src/__support/CPP/type_traits/is_convertible.h" |
| 14 | #include "src/__support/CPP/type_traits/is_same.h" | 15 | #include "src/__support/CPP/type_traits/is_same.h" |
| ... | @@ -18,9 +19,13 @@ | ... | @@ -18,9 +19,13 @@ |
| 18 | namespace LIBC_NAMESPACE_DECL { | 19 | namespace LIBC_NAMESPACE_DECL { |
| 19 | namespace cpp { | 20 | namespace cpp { |
| 20 | 21 | ||
| 22 | struct input_iterator_tag {}; | ||
| 23 | struct random_access_iterator_tag : input_iterator_tag {}; | ||
| 24 | |||
| 21 | template <typename T> struct iterator_traits; | 25 | template <typename T> struct iterator_traits; |
| 22 | template <typename T> struct iterator_traits<T *> { | 26 | template <typename T> struct iterator_traits<T *> { |
| 23 | using reference = T &; | 27 | using reference = T &; |
| 28 | using iterator_category = random_access_iterator_tag; | ||
| 24 | using value_type = T; | 29 | using value_type = T; |
| 25 | }; | 30 | }; |
| 26 | 31 | ||
| ... | @@ -93,6 +98,30 @@ public: | ... | @@ -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 | } // namespace cpp | 125 | } // namespace cpp |
| 97 | } // namespace LIBC_NAMESPACE_DECL | 126 | } // namespace LIBC_NAMESPACE_DECL |
| 98 | 127 |
lib/libcxx/libc/src/__support/CPP/limits.h+26-62| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | //===-- A self contained equivalent of std::limits --------------*- C++ -*-===// | 1 | //===-- A self contained equivalent of <limits> ----------------*- C++ -*-===// |
| 2 | // | 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 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. | 4 | // See https://llvm.org/LICENSE.txt for license information. |
| ... | @@ -13,78 +13,42 @@ | ... | @@ -13,78 +13,42 @@ |
| 13 | #include "src/__support/CPP/type_traits/is_integral.h" | 13 | #include "src/__support/CPP/type_traits/is_integral.h" |
| 14 | #include "src/__support/CPP/type_traits/is_signed.h" | 14 | #include "src/__support/CPP/type_traits/is_signed.h" |
| 15 | #include "src/__support/macros/attributes.h" // LIBC_INLINE | 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 | namespace LIBC_NAMESPACE_DECL { | 17 | namespace LIBC_NAMESPACE_DECL { |
| 20 | namespace cpp { | 18 | namespace cpp { |
| 21 | 19 | ||
| 22 | namespace internal { | 20 | namespace internal { |
| 23 | 21 | ||
| 24 | template <typename T, T min_value, T max_value> struct integer_impl { | 22 | template <typename T, bool is_integral> struct numeric_limits_impl {}; |
| 25 | static_assert(cpp::is_integral_v<T>); | 23 | |
| 26 | LIBC_INLINE static constexpr T max() { return max_value; } | 24 | template <typename T> struct numeric_limits_impl<T, true> { |
| 27 | LIBC_INLINE static constexpr T min() { return min_value; } | 25 | LIBC_INLINE_VAR static constexpr bool is_signed = T(-1) < T(0); |
| 26 | |||
| 28 | LIBC_INLINE_VAR static constexpr int digits = | 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 | } // namespace internal | 47 | } // namespace internal |
| 33 | 48 | ||
| 34 | template <class T> struct numeric_limits {}; | 49 | template <typename T> |
| 35 | 50 | struct numeric_limits | |
| 36 | // TODO: Add numeric_limits specializations as needed for new types. | 51 | : public internal::numeric_limits_impl<T, is_integral_v<T>> {}; |
| 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 | ||
| 88 | 52 | ||
| 89 | } // namespace cpp | 53 | } // namespace cpp |
| 90 | } // namespace LIBC_NAMESPACE_DECL | 54 | } // namespace LIBC_NAMESPACE_DECL |
lib/libcxx/libc/src/__support/CPP/string_view.h+79-62| ... | @@ -18,46 +18,52 @@ | ... | @@ -18,46 +18,52 @@ |
| 18 | namespace LIBC_NAMESPACE_DECL { | 18 | namespace LIBC_NAMESPACE_DECL { |
| 19 | namespace cpp { | 19 | namespace cpp { |
| 20 | 20 | ||
| 21 | // This is very simple alternate of the std::string_view class. There is no | 21 | template <typename CharT> class basic_string_view; |
| 22 | // bounds check performed in any of the methods. The callers are expected to | 22 | |
| 23 | // do the checks before invoking the methods. | 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 | // This class will be extended as needed in future. | 30 | // This class will be extended as needed in future. |
| 26 | class string_view { | 31 | template <typename CharT> class basic_string_view { |
| 27 | private: | 32 | private: |
| 28 | const char *Data; | 33 | const CharT *Data; |
| 29 | size_t Len; | 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, | 40 | LIBC_INLINE static constexpr int compareN(const CharT *Lhs, const CharT *Rhs, |
| 34 | size_t Length) { | 41 | size_t Length) { |
| 35 | for (size_t i = 0; i < Length; ++i) | 42 | for (size_t i = 0; i < Length; ++i) |
| 36 | if (int Diff = (int)Lhs[i] - (int)Rhs[i]) | 43 | if (Lhs[i] != Rhs[i]) |
| 37 | return Diff; | 44 | return Lhs[i] < Rhs[i] ? -1 : 1; |
| 38 | return 0; | 45 | return 0; |
| 39 | } | 46 | } |
| 40 | 47 | ||
| 41 | LIBC_INLINE static constexpr size_t length(const char *Str) { | 48 | LIBC_INLINE static constexpr size_t length(const CharT *Str) { |
| 42 | for (const char *End = Str;; ++End) | 49 | for (const CharT *End = Str;; ++End) |
| 43 | if (*End == '\0') | 50 | if (*End == CharT{0}) |
| 44 | return static_cast<size_t>(End - Str); | 51 | return static_cast<size_t>(End - Str); |
| 45 | } | 52 | } |
| 46 | 53 | ||
| 47 | LIBC_INLINE bool equals(string_view Other) const { | 54 | LIBC_INLINE constexpr bool equals(basic_string_view Other) const { |
| 48 | return (Len == Other.Len && | 55 | return (Len == Other.Len && compareN(Data, Other.Data, Other.Len) == 0); |
| 49 | compareMemory(Data, Other.Data, Other.Len) == 0); | ||
| 50 | } | 56 | } |
| 51 | 57 | ||
| 52 | public: | 58 | public: |
| 53 | using value_type = char; | 59 | using value_type = CharT; |
| 54 | using size_type = size_t; | 60 | using size_type = size_t; |
| 55 | using difference_type = ptrdiff_t; | 61 | using difference_type = ptrdiff_t; |
| 56 | using pointer = char *; | 62 | using pointer = CharT *; |
| 57 | using const_pointer = const char *; | 63 | using const_pointer = const CharT *; |
| 58 | using reference = char &; | 64 | using reference = CharT &; |
| 59 | using const_reference = const char &; | 65 | using const_reference = const CharT &; |
| 60 | using const_iterator = char *; | 66 | using const_iterator = CharT *; |
| 61 | using iterator = const_iterator; | 67 | using iterator = const_iterator; |
| 62 | 68 | ||
| 63 | // special value equal to the maximum value representable by the type | 69 | // special value equal to the maximum value representable by the type |
| ... | @@ -65,124 +71,126 @@ public: | ... | @@ -65,124 +71,126 @@ public: |
| 65 | LIBC_INLINE_VAR static constexpr size_t npos = | 71 | LIBC_INLINE_VAR static constexpr size_t npos = |
| 66 | cpp::numeric_limits<size_t>::max(); | 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 | // Assumes Str is a null-terminated string. The length of the string does | 76 | // Assumes Str is a null-terminated string. The length of the string does |
| 71 | // not include the terminating null character. | 77 | // not include the terminating null character. |
| 72 | // Preconditions: [Str, Str + ​length(Str)) is a valid range. | 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 | : Data(Str), Len(length(Str)) {} | 80 | : Data(Str), Len(length(Str)) {} |
| 75 | 81 | ||
| 76 | // Preconditions: [Str, Str + N) is a valid range. | 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 | : Data(Str), Len(N) {} | 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 | LIBC_INLINE constexpr size_t size() const { return Len; } | 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 | LIBC_INLINE constexpr bool empty() const { return Len == 0; } | 92 | LIBC_INLINE constexpr bool empty() const { return Len == 0; } |
| 87 | 93 | ||
| 88 | // Returns an iterator to the first character of the view. | 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 | // Returns an iterator to the character following the last character of the | 97 | // Returns an iterator to the character following the last character of the |
| 92 | // view. | 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 | // Returns a const reference to the character at specified location pos. | 101 | // Returns a const reference to the character at specified location pos. |
| 96 | // No bounds checking is performed: the behavior is undefined if pos >= | 102 | // No bounds checking is performed: the behavior is undefined if pos >= |
| 97 | // size(). | 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 | return Data[Index]; | 105 | return Data[Index]; |
| 100 | } | 106 | } |
| 101 | 107 | ||
| 102 | /// compare - Compare two strings; the result is -1, 0, or 1 if this string | 108 | /// compare - Compare two strings; the result is -1, 0, or 1 if this string |
| 103 | /// is lexicographically less than, equal to, or greater than the \p Other. | 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 | // Check the prefix for a mismatch. | 111 | // Check the prefix for a mismatch. |
| 106 | if (int Res = compareMemory(Data, Other.Data, min(Len, Other.Len))) | 112 | if (int Res = compareN(Data, Other.Data, min(Len, Other.Len))) |
| 107 | return Res < 0 ? -1 : 1; | 113 | return Res; |
| 108 | // Otherwise the prefixes match, so we only need to check the lengths. | 114 | // Otherwise the prefixes match, so we only need to check the lengths. |
| 109 | if (Len == Other.Len) | 115 | if (Len == Other.Len) |
| 110 | return 0; | 116 | return 0; |
| 111 | return Len < Other.Len ? -1 : 1; | 117 | return Len < Other.Len ? -1 : 1; |
| 112 | } | 118 | } |
| 113 | 119 | ||
| 114 | LIBC_INLINE bool operator==(string_view Other) const { return equals(Other); } | 120 | LIBC_INLINE constexpr bool operator==(basic_string_view Other) const { |
| 115 | LIBC_INLINE bool operator!=(string_view Other) const { | 121 | return equals(Other); |
| 122 | } | ||
| 123 | LIBC_INLINE constexpr bool operator!=(basic_string_view Other) const { | ||
| 116 | return !(*this == Other); | 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 | return compare(Other) == -1; | 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 | return compare(Other) != 1; | 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 | return compare(Other) == 1; | 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 | return compare(Other) != -1; | 136 | return compare(Other) != -1; |
| 129 | } | 137 | } |
| 130 | 138 | ||
| 131 | // Moves the start of the view forward by n characters. | 139 | // Moves the start of the view forward by n characters. |
| 132 | // The behavior is undefined if n > size(). | 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 | Len -= N; | 142 | Len -= N; |
| 135 | Data += N; | 143 | Data += N; |
| 136 | } | 144 | } |
| 137 | 145 | ||
| 138 | // Moves the end of the view back by n characters. | 146 | // Moves the end of the view back by n characters. |
| 139 | // The behavior is undefined if n > size(). | 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 | // Check if this string starts with the given Prefix. | 150 | // Check if this string starts with the given Prefix. |
| 143 | LIBC_INLINE bool starts_with(string_view Prefix) const { | 151 | LIBC_INLINE constexpr bool starts_with(basic_string_view Prefix) const { |
| 144 | return Len >= Prefix.Len && | 152 | return Len >= Prefix.Len && compareN(Data, Prefix.Data, Prefix.Len) == 0; |
| 145 | compareMemory(Data, Prefix.Data, Prefix.Len) == 0; | ||
| 146 | } | 153 | } |
| 147 | 154 | ||
| 148 | // Check if this string starts with the given Prefix. | 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 | return !empty() && front() == Prefix; | 157 | return !empty() && front() == Prefix; |
| 151 | } | 158 | } |
| 152 | 159 | ||
| 153 | // Check if this string ends with the given Prefix. | 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 | return !empty() && back() == Suffix; | 162 | return !empty() && back() == Suffix; |
| 156 | } | 163 | } |
| 157 | 164 | ||
| 158 | // Check if this string ends with the given Suffix. | 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 | return Len >= Suffix.Len && | 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 | // Return a reference to the substring from [Start, Start + N). | 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 | 173 | // Start The index of the starting character in the substring; if the index |
| 167 | // npos or greater than the length of the string then the empty substring will | 174 | // is npos or greater than the length of the string then the empty substring |
| 168 | // be returned. | 175 | // will be returned. |
| 169 | // | 176 | // |
| 170 | // N The number of characters to included in the substring. If N exceeds the | 177 | // N The number of characters to included in the substring. If N exceeds the |
| 171 | // number of characters remaining in the string, the string suffix (starting | 178 | // number of characters remaining in the string, the string suffix (starting |
| 172 | // with Start) will be returned. | 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 | Start = min(Start, Len); | 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 | // front - Get the first character in the string. | 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 | // back - Get the last character in the string. | 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 | // Finds the first occurence of c in this view, starting at position From. | 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 | size_t From = 0) const { | 194 | size_t From = 0) const { |
| 187 | for (size_t Pos = From; Pos < size(); ++Pos) | 195 | for (size_t Pos = From; Pos < size(); ++Pos) |
| 188 | if ((*this)[Pos] == c) | 196 | if ((*this)[Pos] == c) |
| ... | @@ -191,7 +199,7 @@ public: | ... | @@ -191,7 +199,7 @@ public: |
| 191 | } | 199 | } |
| 192 | 200 | ||
| 193 | // Finds the last occurence of c in this view, ending at position End. | 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 | size_t End = npos) const { | 203 | size_t End = npos) const { |
| 196 | End = End >= size() ? size() : End + 1; | 204 | End = End >= size() ? size() : End + 1; |
| 197 | for (; End > 0; --End) | 205 | for (; End > 0; --End) |
| ... | @@ -200,9 +208,18 @@ public: | ... | @@ -200,9 +208,18 @@ public: |
| 200 | return npos; | 208 | return npos; |
| 201 | } | 209 | } |
| 202 | 210 | ||
| 203 | // Finds the first character not equal to c in this view, starting at position | 211 | LIBC_INLINE constexpr size_t find_last_not_of(const char c, |
| 204 | // From. | 212 | size_t end = npos) const { |
| 205 | LIBC_INLINE constexpr size_t find_first_not_of(const char c, | 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 | size_t From = 0) const { | 223 | size_t From = 0) const { |
| 207 | for (size_t Pos = From; Pos < size(); ++Pos) | 224 | for (size_t Pos = From; Pos < size(); ++Pos) |
| 208 | if ((*this)[Pos] != c) | 225 | if ((*this)[Pos] != c) |
| ... | @@ -211,7 +228,7 @@ public: | ... | @@ -211,7 +228,7 @@ public: |
| 211 | } | 228 | } |
| 212 | 229 | ||
| 213 | // Check if this view contains the given character. | 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 | return find_first_of(c) != npos; | 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,7 +15,11 @@ namespace LIBC_NAMESPACE_DECL { |
| 15 | namespace cpp { | 15 | namespace cpp { |
| 16 | 16 | ||
| 17 | LIBC_INLINE constexpr bool is_constant_evaluated() { | 17 | LIBC_INLINE constexpr bool is_constant_evaluated() { |
| 18 | #if LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED | ||
| 18 | return __builtin_is_constant_evaluated(); | 19 | return __builtin_is_constant_evaluated(); |
| 20 | #else | ||
| 21 | return false; | ||
| 22 | #endif | ||
| 19 | } | 23 | } |
| 20 | 24 | ||
| 21 | } // namespace cpp | 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,7 +9,7 @@ |
| 9 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_ASSIGNABLE_H | 9 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_ASSIGNABLE_H |
| 10 | 10 | ||
| 11 | #include "src/__support/CPP/type_traits/add_lvalue_reference.h" | 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 | #include "src/__support/macros/config.h" | 13 | #include "src/__support/macros/config.h" |
| 14 | 14 | ||
| 15 | namespace LIBC_NAMESPACE_DECL { | 15 | namespace LIBC_NAMESPACE_DECL { |
| ... | @@ -18,9 +18,8 @@ namespace cpp { | ... | @@ -18,9 +18,8 @@ namespace cpp { |
| 18 | // is copy assignable | 18 | // is copy assignable |
| 19 | template <class T> | 19 | template <class T> |
| 20 | struct is_copy_assignable | 20 | struct is_copy_assignable |
| 21 | : public integral_constant< | 21 | : public cpp::is_assignable<cpp::add_lvalue_reference_t<T>, |
| 22 | bool, __is_assignable(cpp::add_lvalue_reference_t<T>, | 22 | cpp::add_lvalue_reference_t<const T>> {}; |
| 23 | cpp::add_lvalue_reference_t<const T>)> {}; | ||
| 24 | 23 | ||
| 25 | template <class T> | 24 | template <class T> |
| 26 | LIBC_INLINE_VAR constexpr bool is_copy_assignable_v = | 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,7 +9,7 @@ |
| 9 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_CONSTRUCTIBLE_H | 9 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_CONSTRUCTIBLE_H |
| 10 | 10 | ||
| 11 | #include "src/__support/CPP/type_traits/add_lvalue_reference.h" | 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 | #include "src/__support/macros/config.h" | 13 | #include "src/__support/macros/config.h" |
| 14 | 14 | ||
| 15 | namespace LIBC_NAMESPACE_DECL { | 15 | namespace LIBC_NAMESPACE_DECL { |
| ... | @@ -18,8 +18,7 @@ namespace cpp { | ... | @@ -18,8 +18,7 @@ namespace cpp { |
| 18 | // is copy constructible | 18 | // is copy constructible |
| 19 | template <class T> | 19 | template <class T> |
| 20 | struct is_copy_constructible | 20 | struct is_copy_constructible |
| 21 | : public integral_constant< | 21 | : public cpp::is_constructible<T, cpp::add_lvalue_reference_t<const T>> {}; |
| 22 | bool, __is_constructible(T, cpp::add_lvalue_reference_t<const T>)> {}; | ||
| 23 | 22 | ||
| 24 | template <class T> | 23 | template <class T> |
| 25 | LIBC_INLINE_VAR constexpr bool is_copy_constructible_v = | 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,13 +26,18 @@ private: |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | public: | 28 | public: |
| 29 | LIBC_INLINE_VAR static constexpr bool value = __is_unqualified_any_of< | 29 | LIBC_INLINE_VAR static constexpr bool value = |
| 30 | T, | 30 | __is_unqualified_any_of<T, |
| 31 | #ifdef LIBC_TYPES_HAS_INT128 | 31 | #ifdef LIBC_TYPES_HAS_INT128 |
| 32 | __int128_t, __uint128_t, | 32 | __int128_t, __uint128_t, |
| 33 | #endif | 33 | #endif |
| 34 | char, signed char, unsigned char, short, unsigned short, int, | 34 | #ifdef __cpp_char8_t |
| 35 | unsigned int, long, unsigned long, long long, unsigned long long, bool>(); | 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 | template <typename T> | 42 | template <typename T> |
| 38 | LIBC_INLINE_VAR constexpr bool is_integral_v = is_integral<T>::value; | 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,7 +10,7 @@ |
| 10 | 10 | ||
| 11 | #include "src/__support/CPP/type_traits/add_lvalue_reference.h" | 11 | #include "src/__support/CPP/type_traits/add_lvalue_reference.h" |
| 12 | #include "src/__support/CPP/type_traits/add_rvalue_reference.h" | 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 | #include "src/__support/macros/config.h" | 14 | #include "src/__support/macros/config.h" |
| 15 | 15 | ||
| 16 | namespace LIBC_NAMESPACE_DECL { | 16 | namespace LIBC_NAMESPACE_DECL { |
| ... | @@ -19,9 +19,8 @@ namespace cpp { | ... | @@ -19,9 +19,8 @@ namespace cpp { |
| 19 | // is move assignable | 19 | // is move assignable |
| 20 | template <class T> | 20 | template <class T> |
| 21 | struct is_move_assignable | 21 | struct is_move_assignable |
| 22 | : public integral_constant<bool, __is_assignable( | 22 | : public cpp::is_assignable<cpp::add_lvalue_reference_t<T>, |
| 23 | cpp::add_lvalue_reference_t<T>, | 23 | cpp::add_rvalue_reference_t<T>> {}; |
| 24 | cpp::add_rvalue_reference_t<T>)> {}; | ||
| 25 | 24 | ||
| 26 | template <class T> | 25 | template <class T> |
| 27 | LIBC_INLINE_VAR constexpr bool is_move_assignable_v = | 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,7 +9,7 @@ |
| 9 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MOVE_CONSTRUCTIBLE_H | 9 | #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MOVE_CONSTRUCTIBLE_H |
| 10 | 10 | ||
| 11 | #include "src/__support/CPP/type_traits/add_rvalue_reference.h" | 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 | #include "src/__support/macros/config.h" | 13 | #include "src/__support/macros/config.h" |
| 14 | 14 | ||
| 15 | namespace LIBC_NAMESPACE_DECL { | 15 | namespace LIBC_NAMESPACE_DECL { |
| ... | @@ -18,8 +18,7 @@ namespace cpp { | ... | @@ -18,8 +18,7 @@ namespace cpp { |
| 18 | // is move constructible | 18 | // is move constructible |
| 19 | template <class T> | 19 | template <class T> |
| 20 | struct is_move_constructible | 20 | struct is_move_constructible |
| 21 | : public integral_constant<bool, __is_constructible( | 21 | : public cpp::is_constructible<T, cpp::add_rvalue_reference_t<T>> {}; |
| 22 | T, cpp::add_rvalue_reference_t<T>)> {}; | ||
| 23 | 22 | ||
| 24 | template <class T> | 23 | template <class T> |
| 25 | LIBC_INLINE_VAR constexpr bool is_move_constructible_v = | 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,7 +10,7 @@ |
| 10 | 10 | ||
| 11 | #include "include/llvm-libc-macros/stdfix-macros.h" | 11 | #include "include/llvm-libc-macros/stdfix-macros.h" |
| 12 | #include "src/__support/CPP/type_traits/bool_constant.h" | 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 | #include "src/__support/CPP/type_traits/is_same.h" | 14 | #include "src/__support/CPP/type_traits/is_same.h" |
| 15 | #include "src/__support/CPP/type_traits/remove_cv.h" | 15 | #include "src/__support/CPP/type_traits/remove_cv.h" |
| 16 | #include "src/__support/macros/attributes.h" | 16 | #include "src/__support/macros/attributes.h" |
| ... | @@ -23,7 +23,7 @@ namespace cpp { | ... | @@ -23,7 +23,7 @@ namespace cpp { |
| 23 | 23 | ||
| 24 | #ifndef LIBC_COMPILER_HAS_FIXED_POINT | 24 | #ifndef LIBC_COMPILER_HAS_FIXED_POINT |
| 25 | template <typename T> | 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 | LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; } | 27 | LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; } |
| 28 | LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; } | 28 | LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; } |
| 29 | }; | 29 | }; |
| ... | @@ -37,7 +37,7 @@ private: | ... | @@ -37,7 +37,7 @@ private: |
| 37 | 37 | ||
| 38 | public: | 38 | public: |
| 39 | LIBC_INLINE_VAR static constexpr bool value = | 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 | __is_unqualified_any_of<T, unsigned short fract, unsigned fract, | 41 | __is_unqualified_any_of<T, unsigned short fract, unsigned fract, |
| 42 | unsigned long fract, unsigned short accum, | 42 | unsigned long fract, unsigned short accum, |
| 43 | unsigned accum, unsigned long accum, | 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,7 +798,9 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() { |
| 798 | return FPType::IEEE754_Binary64; | 798 | return FPType::IEEE754_Binary64; |
| 799 | else if constexpr (LDBL_MANT_DIG == 64) | 799 | else if constexpr (LDBL_MANT_DIG == 64) |
| 800 | return FPType::X86_Binary80; | 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 | return FPType::IEEE754_Binary128; | 804 | return FPType::IEEE754_Binary128; |
| 803 | } | 805 | } |
| 804 | #if defined(LIBC_TYPES_HAS_FLOAT16) | 806 | #if defined(LIBC_TYPES_HAS_FLOAT16) |
| ... | @@ -833,21 +835,22 @@ struct FPBits final : public internal::FPRepImpl<get_fp_type<T>(), FPBits<T>> { | ... | @@ -833,21 +835,22 @@ struct FPBits final : public internal::FPRepImpl<get_fp_type<T>(), FPBits<T>> { |
| 833 | // Constructors. | 835 | // Constructors. |
| 834 | LIBC_INLINE constexpr FPBits() = default; | 836 | LIBC_INLINE constexpr FPBits() = default; |
| 835 | 837 | ||
| 836 | template <typename XType> LIBC_INLINE constexpr explicit FPBits(XType x) { | 838 | template < |
| 837 | using Unqual = typename cpp::remove_cv_t<XType>; | 839 | typename XType, |
| 838 | if constexpr (cpp::is_same_v<Unqual, T>) { | 840 | cpp::enable_if_t<cpp::is_same_v<cpp::remove_cv_t<XType>, T>, int> = 0> |
| 839 | UP::bits = cpp::bit_cast<StorageType>(x); | 841 | LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR explicit FPBits(XType x) { |
| 840 | } else if constexpr (cpp::is_same_v<Unqual, StorageType>) { | 842 | UP::bits = cpp::bit_cast<StorageType>(x); |
| 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 | } | ||
| 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 | // Floating-point conversions. | 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 | } // namespace fputil | 856 | } // namespace fputil |
lib/libcxx/libc/src/__support/FPUtil/rounding_mode.h+25-5| ... | @@ -24,8 +24,12 @@ namespace generic { | ... | @@ -24,8 +24,12 @@ namespace generic { |
| 24 | // 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO | 24 | // 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO |
| 25 | // = 0x1.000002f for FE_UPWARD. | 25 | // = 0x1.000002f for FE_UPWARD. |
| 26 | LIBC_INLINE bool fenv_is_round_up() { | 26 | LIBC_INLINE bool fenv_is_round_up() { |
| 27 | #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 28 | return false; | ||
| 29 | #else | ||
| 27 | static volatile float x = 0x1.0p-25f; | 30 | static volatile float x = 0x1.0p-25f; |
| 28 | return (1.0f + x != 1.0f); | 31 | return (1.0f + x != 1.0f); |
| 32 | #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 29 | } | 33 | } |
| 30 | 34 | ||
| 31 | // Quick free-standing test whether fegetround() == FE_DOWNWARD. | 35 | // Quick free-standing test whether fegetround() == FE_DOWNWARD. |
| ... | @@ -33,8 +37,12 @@ LIBC_INLINE bool fenv_is_round_up() { | ... | @@ -33,8 +37,12 @@ LIBC_INLINE bool fenv_is_round_up() { |
| 33 | // -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO | 37 | // -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO |
| 34 | // = -0x1.000002f for FE_DOWNWARD. | 38 | // = -0x1.000002f for FE_DOWNWARD. |
| 35 | LIBC_INLINE bool fenv_is_round_down() { | 39 | LIBC_INLINE bool fenv_is_round_down() { |
| 40 | #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 41 | return false; | ||
| 42 | #else | ||
| 36 | static volatile float x = 0x1.0p-25f; | 43 | static volatile float x = 0x1.0p-25f; |
| 37 | return (-1.0f - x != -1.0f); | 44 | return (-1.0f - x != -1.0f); |
| 45 | #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 38 | } | 46 | } |
| 39 | 47 | ||
| 40 | // Quick free-standing test whether fegetround() == FE_TONEAREST. | 48 | // Quick free-standing test whether fegetround() == FE_TONEAREST. |
| ... | @@ -44,9 +52,13 @@ LIBC_INLINE bool fenv_is_round_down() { | ... | @@ -44,9 +52,13 @@ LIBC_INLINE bool fenv_is_round_down() { |
| 44 | // 1.5f - 2^-24 = 1.5f for FE_TONEAREST, FE_UPWARD | 52 | // 1.5f - 2^-24 = 1.5f for FE_TONEAREST, FE_UPWARD |
| 45 | // = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO | 53 | // = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO |
| 46 | LIBC_INLINE bool fenv_is_round_to_nearest() { | 54 | LIBC_INLINE bool fenv_is_round_to_nearest() { |
| 55 | #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 56 | return true; | ||
| 57 | #else | ||
| 47 | static volatile float x = 0x1.0p-24f; | 58 | static volatile float x = 0x1.0p-24f; |
| 48 | float y = 1.5f + x; | 59 | float y = 1.5f + x; |
| 49 | return (y == 1.5f - x); | 60 | return (y == 1.5f - x); |
| 61 | #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 50 | } | 62 | } |
| 51 | 63 | ||
| 52 | // Quick free-standing test whether fegetround() == FE_TOWARDZERO. | 64 | // Quick free-standing test whether fegetround() == FE_TOWARDZERO. |
| ... | @@ -60,13 +72,20 @@ LIBC_INLINE bool fenv_is_round_to_nearest() { | ... | @@ -60,13 +72,20 @@ LIBC_INLINE bool fenv_is_round_to_nearest() { |
| 60 | // = 2^-22 for FE_TONEAREST, FE_UPWARD | 72 | // = 2^-22 for FE_TONEAREST, FE_UPWARD |
| 61 | // = 0 for FE_DOWNWARD | 73 | // = 0 for FE_DOWNWARD |
| 62 | LIBC_INLINE bool fenv_is_round_to_zero() { | 74 | LIBC_INLINE bool fenv_is_round_to_zero() { |
| 75 | #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 76 | return false; | ||
| 77 | #else | ||
| 63 | static volatile float x = 0x1.0p-24f; | 78 | static volatile float x = 0x1.0p-24f; |
| 64 | float y = x; | 79 | float y = x; |
| 65 | return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f); | 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 | // Quick free standing get rounding mode based on the above observations. | 84 | // Quick free standing get rounding mode based on the above observations. |
| 69 | LIBC_INLINE int quick_get_round() { | 85 | LIBC_INLINE int quick_get_round() { |
| 86 | #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 87 | return FE_TONEAREST; | ||
| 88 | #else | ||
| 70 | static volatile float x = 0x1.0p-24f; | 89 | static volatile float x = 0x1.0p-24f; |
| 71 | float y = x; | 90 | float y = x; |
| 72 | float z = (0x1.000002p0f + y) + (-1.0f - y); | 91 | float z = (0x1.000002p0f + y) + (-1.0f - y); |
| ... | @@ -76,11 +95,12 @@ LIBC_INLINE int quick_get_round() { | ... | @@ -76,11 +95,12 @@ LIBC_INLINE int quick_get_round() { |
| 76 | if (z == 0x1.0p-23f) | 95 | if (z == 0x1.0p-23f) |
| 77 | return FE_TOWARDZERO; | 96 | return FE_TOWARDZERO; |
| 78 | return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD; | 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 | } // namespace generic | 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 | if (cpp::is_constant_evaluated()) { | 104 | if (cpp::is_constant_evaluated()) { |
| 85 | return false; | 105 | return false; |
| 86 | } else { | 106 | } else { |
| ... | @@ -88,7 +108,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_up() { | ... | @@ -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 | if (cpp::is_constant_evaluated()) { | 112 | if (cpp::is_constant_evaluated()) { |
| 93 | return false; | 113 | return false; |
| 94 | } else { | 114 | } else { |
| ... | @@ -96,7 +116,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_down() { | ... | @@ -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 | if (cpp::is_constant_evaluated()) { | 120 | if (cpp::is_constant_evaluated()) { |
| 101 | return true; | 121 | return true; |
| 102 | } else { | 122 | } else { |
| ... | @@ -104,7 +124,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() { | ... | @@ -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 | if (cpp::is_constant_evaluated()) { | 128 | if (cpp::is_constant_evaluated()) { |
| 109 | return false; | 129 | return false; |
| 110 | } else { | 130 | } else { |
| ... | @@ -113,7 +133,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_zero() { | ... | @@ -113,7 +133,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_zero() { |
| 113 | } | 133 | } |
| 114 | 134 | ||
| 115 | // Quick free standing get rounding mode based on the above observations. | 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 | if (cpp::is_constant_evaluated()) { | 137 | if (cpp::is_constant_evaluated()) { |
| 118 | return FE_TONEAREST; | 138 | return FE_TONEAREST; |
| 119 | } else { | 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,10 +242,9 @@ LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst, |
| 242 | 242 | ||
| 243 | template <typename word, size_t N> | 243 | template <typename word, size_t N> |
| 244 | LIBC_INLINE constexpr bool is_negative(const cpp::array<word, N> &array) { | 244 | LIBC_INLINE constexpr bool is_negative(const cpp::array<word, N> &array) { |
| 245 | using signed_word = cpp::make_signed_t<word>; | 245 | constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits; |
| 246 | return cpp::bit_cast<signed_word>(array.back()) < 0; | 246 | return (array.back() >> (WORD_BITS - 1)) != 0; |
| 247 | } | 247 | } |
| 248 | |||
| 249 | // An enum for the shift function below. | 248 | // An enum for the shift function below. |
| 250 | enum Direction { LEFT, RIGHT }; | 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,9 +256,11 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array, |
| 257 | size_t offset) { | 256 | size_t offset) { |
| 258 | static_assert(direction == LEFT || direction == RIGHT); | 257 | static_assert(direction == LEFT || direction == RIGHT); |
| 259 | constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits; | 258 | constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits; |
| 259 | #if LIBC_HAS_BUILTIN_BIT_CAST | ||
| 260 | #ifdef LIBC_TYPES_HAS_INT128 | 260 | #ifdef LIBC_TYPES_HAS_INT128 |
| 261 | constexpr size_t TOTAL_BITS = N * WORD_BITS; | 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 | using type = cpp::conditional_t<is_signed, __int128_t, __uint128_t>; | 264 | using type = cpp::conditional_t<is_signed, __int128_t, __uint128_t>; |
| 264 | auto tmp = cpp::bit_cast<type>(array); | 265 | auto tmp = cpp::bit_cast<type>(array); |
| 265 | if constexpr (direction == LEFT) | 266 | if constexpr (direction == LEFT) |
| ... | @@ -269,6 +270,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array, | ... | @@ -269,6 +270,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array, |
| 269 | return cpp::bit_cast<cpp::array<word, N>>(tmp); | 270 | return cpp::bit_cast<cpp::array<word, N>>(tmp); |
| 270 | } | 271 | } |
| 271 | #endif | 272 | #endif |
| 273 | #endif // LIBC_HAS_BUILTIN_BIT_CAST | ||
| 274 | |||
| 272 | if (LIBC_UNLIKELY(offset == 0)) | 275 | if (LIBC_UNLIKELY(offset == 0)) |
| 273 | return array; | 276 | return array; |
| 274 | const bool is_neg = is_signed && is_negative(array); | 277 | const bool is_neg = is_signed && is_negative(array); |
| ... | @@ -336,8 +339,8 @@ private: | ... | @@ -336,8 +339,8 @@ private: |
| 336 | "WordType must be unsigned integer."); | 339 | "WordType must be unsigned integer."); |
| 337 | 340 | ||
| 338 | struct Division { | 341 | struct Division { |
| 339 | BigInt quotient; | 342 | BigInt quotient{}; |
| 340 | BigInt remainder; | 343 | BigInt remainder{}; |
| 341 | }; | 344 | }; |
| 342 | 345 | ||
| 343 | public: | 346 | public: |
| ... | @@ -355,7 +358,7 @@ public: | ... | @@ -355,7 +358,7 @@ public: |
| 355 | 358 | ||
| 356 | LIBC_INLINE_VAR static constexpr size_t WORD_COUNT = Bits / WORD_SIZE; | 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 | LIBC_INLINE constexpr BigInt() = default; | 363 | LIBC_INLINE constexpr BigInt() = default; |
| 361 | 364 | ||
| ... | @@ -363,9 +366,10 @@ public: | ... | @@ -363,9 +366,10 @@ public: |
| 363 | 366 | ||
| 364 | template <size_t OtherBits, bool OtherSigned, typename OtherWordType> | 367 | template <size_t OtherBits, bool OtherSigned, typename OtherWordType> |
| 365 | LIBC_INLINE constexpr BigInt( | 368 | LIBC_INLINE constexpr BigInt( |
| 366 | const BigInt<OtherBits, OtherSigned, OtherWordType> &other) { | 369 | const BigInt<OtherBits, OtherSigned, OtherWordType> &other) |
| 370 | : val{} { | ||
| 367 | using BigIntOther = BigInt<OtherBits, OtherSigned, OtherWordType>; | 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 | static_assert(!(Bits == OtherBits && WORD_SIZE != BigIntOther::WORD_SIZE) && | 374 | static_assert(!(Bits == OtherBits && WORD_SIZE != BigIntOther::WORD_SIZE) && |
| 371 | "This is currently untested for casting between bigints with " | 375 | "This is currently untested for casting between bigints with " |
| ... | @@ -453,20 +457,22 @@ public: | ... | @@ -453,20 +457,22 @@ public: |
| 453 | } | 457 | } |
| 454 | 458 | ||
| 455 | // Construct a BigInt from a C array. | 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 | static_assert(N == WORD_COUNT); | 462 | static_assert(N == WORD_COUNT); |
| 458 | for (size_t i = 0; i < WORD_COUNT; ++i) | 463 | for (size_t i = 0; i < WORD_COUNT; ++i) |
| 459 | val[i] = nums[i]; | 464 | val[i] = nums[i]; |
| 460 | } | 465 | } |
| 461 | 466 | ||
| 462 | LIBC_INLINE constexpr explicit BigInt( | 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 | val = words; | 470 | val = words; |
| 465 | } | 471 | } |
| 466 | 472 | ||
| 467 | // Initialize the first word to |v| and the rest to 0. | 473 | // Initialize the first word to |v| and the rest to 0. |
| 468 | template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T>>> | 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 | constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT; | 476 | constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT; |
| 471 | const bool is_neg = v < 0; | 477 | const bool is_neg = v < 0; |
| 472 | for (size_t i = 0; i < WORD_COUNT; ++i) { | 478 | for (size_t i = 0; i < WORD_COUNT; ++i) { |
| ... | @@ -488,7 +494,7 @@ public: | ... | @@ -488,7 +494,7 @@ public: |
| 488 | LIBC_INLINE static constexpr BigInt one() { return BigInt(1); } | 494 | LIBC_INLINE static constexpr BigInt one() { return BigInt(1); } |
| 489 | LIBC_INLINE static constexpr BigInt all_ones() { return ~zero(); } | 495 | LIBC_INLINE static constexpr BigInt all_ones() { return ~zero(); } |
| 490 | LIBC_INLINE static constexpr BigInt min() { | 496 | LIBC_INLINE static constexpr BigInt min() { |
| 491 | BigInt out; | 497 | BigInt out{}; |
| 492 | if constexpr (SIGNED) | 498 | if constexpr (SIGNED) |
| 493 | out.set_msb(); | 499 | out.set_msb(); |
| 494 | return out; | 500 | return out; |
| ... | @@ -601,7 +607,7 @@ public: | ... | @@ -601,7 +607,7 @@ public: |
| 601 | template <size_t OtherBits> | 607 | template <size_t OtherBits> |
| 602 | LIBC_INLINE constexpr auto | 608 | LIBC_INLINE constexpr auto |
| 603 | ful_mul(const BigInt<OtherBits, Signed, WordType> &other) const { | 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 | multiword::multiply_with_carry(result.val, val, other.val); | 611 | multiword::multiply_with_carry(result.val, val, other.val); |
| 606 | return result; | 612 | return result; |
| 607 | } | 613 | } |
| ... | @@ -633,7 +639,7 @@ public: | ... | @@ -633,7 +639,7 @@ public: |
| 633 | // 256 4 16 10 3 | 639 | // 256 4 16 10 3 |
| 634 | // 512 8 64 36 7 | 640 | // 512 8 64 36 7 |
| 635 | LIBC_INLINE constexpr BigInt quick_mul_hi(const BigInt &other) const { | 641 | LIBC_INLINE constexpr BigInt quick_mul_hi(const BigInt &other) const { |
| 636 | BigInt result; | 642 | BigInt result{}; |
| 637 | multiword::quick_mul_hi(result.val, val, other.val); | 643 | multiword::quick_mul_hi(result.val, val, other.val); |
| 638 | return result; | 644 | return result; |
| 639 | } | 645 | } |
| ... | @@ -686,7 +692,7 @@ public: | ... | @@ -686,7 +692,7 @@ public: |
| 686 | // And finally we perform some extra alignment steps for the remaining bits. | 692 | // And finally we perform some extra alignment steps for the remaining bits. |
| 687 | LIBC_INLINE constexpr cpp::optional<BigInt> | 693 | LIBC_INLINE constexpr cpp::optional<BigInt> |
| 688 | div_uint_half_times_pow_2(multiword::half_width_t<WordType> x, size_t e) { | 694 | div_uint_half_times_pow_2(multiword::half_width_t<WordType> x, size_t e) { |
| 689 | BigInt remainder; | 695 | BigInt remainder{}; |
| 690 | if (x == 0) | 696 | if (x == 0) |
| 691 | return cpp::nullopt; | 697 | return cpp::nullopt; |
| 692 | if (e >= Bits) { | 698 | if (e >= Bits) { |
| ... | @@ -694,7 +700,7 @@ public: | ... | @@ -694,7 +700,7 @@ public: |
| 694 | *this = BigInt<Bits, false, WordType>(); | 700 | *this = BigInt<Bits, false, WordType>(); |
| 695 | return remainder; | 701 | return remainder; |
| 696 | } | 702 | } |
| 697 | BigInt quotient; | 703 | BigInt quotient{}; |
| 698 | WordType x_word = static_cast<WordType>(x); | 704 | WordType x_word = static_cast<WordType>(x); |
| 699 | constexpr size_t LOG2_WORD_SIZE = | 705 | constexpr size_t LOG2_WORD_SIZE = |
| 700 | static_cast<size_t>(cpp::bit_width(WORD_SIZE) - 1); | 706 | static_cast<size_t>(cpp::bit_width(WORD_SIZE) - 1); |
| ... | @@ -846,13 +852,13 @@ public: | ... | @@ -846,13 +852,13 @@ public: |
| 846 | #define DEFINE_BINOP(OP) \ | 852 | #define DEFINE_BINOP(OP) \ |
| 847 | LIBC_INLINE friend constexpr BigInt operator OP(const BigInt &lhs, \ | 853 | LIBC_INLINE friend constexpr BigInt operator OP(const BigInt &lhs, \ |
| 848 | const BigInt &rhs) { \ | 854 | const BigInt &rhs) { \ |
| 849 | BigInt result; \ | 855 | BigInt result{}; \ |
| 850 | for (size_t i = 0; i < WORD_COUNT; ++i) \ | 856 | for (size_t i = 0; i < WORD_COUNT; ++i) \ |
| 851 | result[i] = lhs[i] OP rhs[i]; \ | 857 | result[i] = lhs[i] OP rhs[i]; \ |
| 852 | return result; \ | 858 | return result; \ |
| 853 | } \ | 859 | } \ |
| 854 | LIBC_INLINE friend constexpr BigInt operator OP##=(BigInt &lhs, \ | 860 | LIBC_INLINE friend constexpr BigInt operator OP## = \ |
| 855 | const BigInt &rhs) { \ | 861 | (BigInt & lhs, const BigInt &rhs) { \ |
| 856 | for (size_t i = 0; i < WORD_COUNT; ++i) \ | 862 | for (size_t i = 0; i < WORD_COUNT; ++i) \ |
| 857 | lhs[i] OP## = rhs[i]; \ | 863 | lhs[i] OP## = rhs[i]; \ |
| 858 | return lhs; \ | 864 | return lhs; \ |
| ... | @@ -864,7 +870,7 @@ public: | ... | @@ -864,7 +870,7 @@ public: |
| 864 | #undef DEFINE_BINOP | 870 | #undef DEFINE_BINOP |
| 865 | 871 | ||
| 866 | LIBC_INLINE constexpr BigInt operator~() const { | 872 | LIBC_INLINE constexpr BigInt operator~() const { |
| 867 | BigInt result; | 873 | BigInt result{}; |
| 868 | for (size_t i = 0; i < WORD_COUNT; ++i) | 874 | for (size_t i = 0; i < WORD_COUNT; ++i) |
| 869 | result[i] = static_cast<WordType>(~val[i]); | 875 | result[i] = static_cast<WordType>(~val[i]); |
| 870 | return result; | 876 | return result; |
| ... | @@ -1004,7 +1010,7 @@ private: | ... | @@ -1004,7 +1010,7 @@ private: |
| 1004 | LIBC_INLINE constexpr static Division divide_unsigned(const BigInt &dividend, | 1010 | LIBC_INLINE constexpr static Division divide_unsigned(const BigInt &dividend, |
| 1005 | const BigInt &divider) { | 1011 | const BigInt &divider) { |
| 1006 | BigInt remainder = dividend; | 1012 | BigInt remainder = dividend; |
| 1007 | BigInt quotient; | 1013 | BigInt quotient{}; |
| 1008 | if (remainder >= divider) { | 1014 | if (remainder >= divider) { |
| 1009 | BigInt subtractor = divider; | 1015 | BigInt subtractor = divider; |
| 1010 | int cur_bit = multiword::countl_zero(subtractor.val) - | 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,31 +1187,6 @@ LIBC_INLINE_VAR constexpr bool is_unsigned_integral_or_big_int_v = |
| 1181 | 1187 | ||
| 1182 | namespace cpp { | 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 | // Specialization of cpp::popcount ('bit.h') for BigInt. | 1190 | // Specialization of cpp::popcount ('bit.h') for BigInt. |
| 1210 | template <typename T> | 1191 | template <typename T> |
| 1211 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int> | 1192 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int> |
| ... | @@ -1311,7 +1292,7 @@ mask_trailing_ones() { | ... | @@ -1311,7 +1292,7 @@ mask_trailing_ones() { |
| 1311 | return T::all_ones(); | 1292 | return T::all_ones(); |
| 1312 | constexpr size_t QUOTIENT = count / T::WORD_SIZE; | 1293 | constexpr size_t QUOTIENT = count / T::WORD_SIZE; |
| 1313 | constexpr size_t REMAINDER = count % T::WORD_SIZE; | 1294 | constexpr size_t REMAINDER = count % T::WORD_SIZE; |
| 1314 | T out; // zero initialized | 1295 | T out{}; |
| 1315 | for (size_t i = 0; i <= QUOTIENT; ++i) | 1296 | for (size_t i = 0; i <= QUOTIENT; ++i) |
| 1316 | out[i] = i < QUOTIENT | 1297 | out[i] = i < QUOTIENT |
| 1317 | ? cpp::numeric_limits<typename T::word_type>::max() | 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,7 +1308,7 @@ LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() { |
| 1327 | return T::all_ones(); | 1308 | return T::all_ones(); |
| 1328 | constexpr size_t QUOTIENT = (T::BITS - count - 1U) / T::WORD_SIZE; | 1309 | constexpr size_t QUOTIENT = (T::BITS - count - 1U) / T::WORD_SIZE; |
| 1329 | constexpr size_t REMAINDER = count % T::WORD_SIZE; | 1310 | constexpr size_t REMAINDER = count % T::WORD_SIZE; |
| 1330 | T out; // zero initialized | 1311 | T out{}; |
| 1331 | for (size_t i = QUOTIENT; i < T::WORD_COUNT; ++i) | 1312 | for (size_t i = QUOTIENT; i < T::WORD_COUNT; ++i) |
| 1332 | out[i] = i > QUOTIENT | 1313 | out[i] = i > QUOTIENT |
| 1333 | ? cpp::numeric_limits<typename T::word_type>::max() | 1314 | ? cpp::numeric_limits<typename T::word_type>::max() |
| ... | @@ -1386,6 +1367,11 @@ first_trailing_one(T value) { | ... | @@ -1386,6 +1367,11 @@ first_trailing_one(T value) { |
| 1386 | return value == 0 ? 0 : cpp::countr_zero(value) + 1; | 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 | } // namespace LIBC_NAMESPACE_DECL | 1375 | } // namespace LIBC_NAMESPACE_DECL |
| 1390 | 1376 | ||
| 1391 | #endif // LLVM_LIBC_SRC___SUPPORT_BIG_INT_H | 1377 | #endif // LLVM_LIBC_SRC___SUPPORT_BIG_INT_H |
lib/libcxx/libc/src/__support/common.h+45-32| ... | @@ -22,6 +22,10 @@ | ... | @@ -22,6 +22,10 @@ |
| 22 | #define LLVM_LIBC_FUNCTION_ATTR | 22 | #define LLVM_LIBC_FUNCTION_ATTR |
| 23 | #endif | 23 | #endif |
| 24 | 24 | ||
| 25 | #ifndef LLVM_LIBC_VARIABLE_ATTR | ||
| 26 | #define LLVM_LIBC_VARIABLE_ATTR | ||
| 27 | #endif | ||
| 28 | |||
| 25 | // clang-format off | 29 | // clang-format off |
| 26 | // Allow each function `func` to have extra attributes specified by defining: | 30 | // Allow each function `func` to have extra attributes specified by defining: |
| 27 | // `LLVM_LIBC_FUNCTION_ATTR_func` macro, which should always start with | 31 | // `LLVM_LIBC_FUNCTION_ATTR_func` macro, which should always start with |
| ... | @@ -33,7 +37,9 @@ | ... | @@ -33,7 +37,9 @@ |
| 33 | // clang-format on | 37 | // clang-format on |
| 34 | #define LLVM_LIBC_EMPTY | 38 | #define LLVM_LIBC_EMPTY |
| 35 | 39 | ||
| 40 | #define GET_NOTHING(...) 0 | ||
| 36 | #define GET_SECOND(first, second, ...) second | 41 | #define GET_SECOND(first, second, ...) second |
| 42 | #define GET_FIFTH(first, second, third, fourth, fifth, ...) fifth | ||
| 37 | #define EXPAND_THEN_SECOND(name) GET_SECOND(name, LLVM_LIBC_EMPTY) | 43 | #define EXPAND_THEN_SECOND(name) GET_SECOND(name, LLVM_LIBC_EMPTY) |
| 38 | 44 | ||
| 39 | #define LLVM_LIBC_ATTR(name) EXPAND_THEN_SECOND(LLVM_LIBC_FUNCTION_ATTR_##name) | 45 | #define LLVM_LIBC_ATTR(name) EXPAND_THEN_SECOND(LLVM_LIBC_FUNCTION_ATTR_##name) |
| ... | @@ -44,50 +50,57 @@ | ... | @@ -44,50 +50,57 @@ |
| 44 | // symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`. | 50 | // symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`. |
| 45 | #if defined(LIBC_COPT_PUBLIC_PACKAGING) && !defined(LIBC_COMPILER_IS_MSVC) | 51 | #if defined(LIBC_COPT_PUBLIC_PACKAGING) && !defined(LIBC_COMPILER_IS_MSVC) |
| 46 | #ifndef __APPLE__ | 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 | LLVM_LIBC_ATTR(name) \ | 54 | LLVM_LIBC_ATTR(name) \ |
| 49 | LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \ | 55 | LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \ |
| 50 | __##name##_impl__ asm(#name); \ | 56 | __##name##_impl__ asm(c_alias); \ |
| 51 | decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \ | 57 | decltype(LIBC_NAMESPACE::name) name [[gnu::alias(c_alias)]]; \ |
| 52 | type __##name##_impl__ arglist | 58 | type __##name##_impl__ arglist |
| 53 | #else // __APPLE__ | 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 | LLVM_LIBC_ATTR(name) \ | 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 | type name arglist | 64 | type name arglist |
| 58 | #endif // __APPLE__ | 65 | #endif // __APPLE__ |
| 66 | |||
| 59 | #else // LIBC_COPT_PUBLIC_PACKAGING | 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 | #endif // LIBC_COPT_PUBLIC_PACKAGING | 70 | #endif // LIBC_COPT_PUBLIC_PACKAGING |
| 62 | 71 | ||
| 63 | // This extra layer of macro allows `name` to be a macro to rename a function. | 72 | #define LLVM_LIBC_FUNCTION_IMPL_3(type, name, arglist) \ |
| 64 | #define LLVM_LIBC_FUNCTION(type, name, arglist) \ | 73 | LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, #name) |
| 65 | LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) | ||
| 66 | 74 | ||
| 67 | namespace LIBC_NAMESPACE_DECL { | 75 | // LLVM_LIBC_FUNCTION(type, name, arglist) is equivalent to |
| 68 | namespace internal { | 76 | // LLVM_LIBC_FUNCTION(type, name, arglist, #name) |
| 69 | LIBC_INLINE constexpr bool same_string(char const *lhs, char const *rhs) { | 77 | #define LLVM_LIBC_FUNCTION(...) \ |
| 70 | for (; *lhs || *rhs; ++lhs, ++rhs) | 78 | GET_FIFTH(__VA_ARGS__, LLVM_LIBC_FUNCTION_IMPL_4, LLVM_LIBC_FUNCTION_IMPL_3, \ |
| 71 | if (*lhs != *rhs) | 79 | GET_NOTHING)(__VA_ARGS__) |
| 72 | return false; | ||
| 73 | return true; | ||
| 74 | } | ||
| 75 | } // namespace internal | ||
| 76 | } // namespace LIBC_NAMESPACE_DECL | ||
| 77 | 80 | ||
| 78 | #define __LIBC_MACRO_TO_STRING(str) #str | 81 | // At the moment, [[gnu::alias()]] is not supported on MacOS, and it is needed |
| 79 | #define LIBC_MACRO_TO_STRING(str) __LIBC_MACRO_TO_STRING(str) | 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. | 104 | #define LLVM_LIBC_VARIABLE(type, name) LLVM_LIBC_VARIABLE_IMPL(type, name) |
| 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 | ||
| 92 | 105 | ||
| 93 | #endif // LLVM_LIBC_SRC___SUPPORT_COMMON_H | 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,7 +37,7 @@ namespace internal { |
| 37 | // EBCDIC. Technically we could use some smaller ranges, but that's even harder | 37 | // EBCDIC. Technically we could use some smaller ranges, but that's even harder |
| 38 | // to read. | 38 | // to read. |
| 39 | 39 | ||
| 40 | LIBC_INLINE static constexpr bool islower(char ch) { | 40 | LIBC_INLINE constexpr bool islower(char ch) { |
| 41 | switch (ch) { | 41 | switch (ch) { |
| 42 | case 'a': | 42 | case 'a': |
| 43 | case 'b': | 43 | case 'b': |
| ... | @@ -71,7 +71,7 @@ LIBC_INLINE static constexpr bool islower(char ch) { | ... | @@ -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 | switch (ch) { | 75 | switch (ch) { |
| 76 | case 'A': | 76 | case 'A': |
| 77 | case 'B': | 77 | case 'B': |
| ... | @@ -105,7 +105,7 @@ LIBC_INLINE static constexpr bool isupper(char ch) { | ... | @@ -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 | switch (ch) { | 109 | switch (ch) { |
| 110 | case '0': | 110 | case '0': |
| 111 | case '1': | 111 | case '1': |
| ... | @@ -123,7 +123,7 @@ LIBC_INLINE static constexpr bool isdigit(char ch) { | ... | @@ -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 | switch (ch) { | 127 | switch (ch) { |
| 128 | case 'A': | 128 | case 'A': |
| 129 | return 'a'; | 129 | return 'a'; |
| ... | @@ -182,7 +182,7 @@ LIBC_INLINE static constexpr char tolower(char ch) { | ... | @@ -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 | switch (ch) { | 186 | switch (ch) { |
| 187 | case 'a': | 187 | case 'a': |
| 188 | return 'A'; | 188 | return 'A'; |
| ... | @@ -241,7 +241,7 @@ LIBC_INLINE static constexpr char toupper(char ch) { | ... | @@ -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 | switch (ch) { | 245 | switch (ch) { |
| 246 | case 'a': | 246 | case 'a': |
| 247 | case 'b': | 247 | case 'b': |
| ... | @@ -301,7 +301,7 @@ LIBC_INLINE static constexpr bool isalpha(char ch) { | ... | @@ -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 | switch (ch) { | 305 | switch (ch) { |
| 306 | case 'a': | 306 | case 'a': |
| 307 | case 'b': | 307 | case 'b': |
| ... | @@ -371,7 +371,8 @@ LIBC_INLINE static constexpr bool isalnum(char ch) { | ... | @@ -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 | switch (ch) { | 376 | switch (ch) { |
| 376 | case '0': | 377 | case '0': |
| 377 | return 0; | 378 | return 0; |
| ... | @@ -475,8 +476,21 @@ LIBC_INLINE static constexpr int b36_char_to_int(char ch) { | ... | @@ -475,8 +476,21 @@ LIBC_INLINE static constexpr int b36_char_to_int(char ch) { |
| 475 | return 0; | 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 | // Can't actually use LIBC_ASSERT here because it depends on integer_to_string | 494 | // Can't actually use LIBC_ASSERT here because it depends on integer_to_string |
| 481 | // which depends on this. | 495 | // which depends on this. |
| 482 | 496 | ||
| ... | @@ -559,7 +573,7 @@ LIBC_INLINE static constexpr char int_to_b36_char(int num) { | ... | @@ -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 | switch (ch) { | 577 | switch (ch) { |
| 564 | case ' ': | 578 | case ' ': |
| 565 | case '\t': | 579 | case '\t': |
| ... | @@ -574,14 +588,12 @@ LIBC_INLINE static constexpr bool isspace(char ch) { | ... | @@ -574,14 +588,12 @@ LIBC_INLINE static constexpr bool isspace(char ch) { |
| 574 | } | 588 | } |
| 575 | 589 | ||
| 576 | // not yet encoding independent. | 590 | // not yet encoding independent. |
| 577 | LIBC_INLINE static constexpr bool isgraph(char ch) { | 591 | LIBC_INLINE constexpr bool isgraph(char ch) { return 0x20 < ch && ch < 0x7f; } |
| 578 | return 0x20 < ch && ch < 0x7f; | ||
| 579 | } | ||
| 580 | 592 | ||
| 581 | // An overload which provides a way to compare input with specific character | 593 | // An overload which provides a way to compare input with specific character |
| 582 | // values, when input can be of a regular or a wide character type. | 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, | 595 | LIBC_INLINE constexpr bool is_char_or_wchar(char ch, char c_value, |
| 584 | [[maybe_unused]] wchar_t) { | 596 | [[maybe_unused]] wchar_t) { |
| 585 | return (ch == c_value); | 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,7 +1,7 @@ |
| 1 | //===-- High Precision Decimal ----------------------------------*- C++ -*-===// | 1 | //===-- High Precision Decimal ----------------------------------*- C++ -*-===// |
| 2 | // | 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 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 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 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,8 +25,9 @@ |
| 25 | #include "src/__support/OSUtil/exit.h" | 25 | #include "src/__support/OSUtil/exit.h" |
| 26 | #include "src/__support/OSUtil/io.h" | 26 | #include "src/__support/OSUtil/io.h" |
| 27 | #include "src/__support/integer_to_string.h" | 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 | #include "src/__support/macros/config.h" | 29 | #include "src/__support/macros/config.h" |
| 30 | #include "src/__support/macros/macro-utils.h" | ||
| 30 | #include "src/__support/macros/optimization.h" // For LIBC_UNLIKELY | 31 | #include "src/__support/macros/optimization.h" // For LIBC_UNLIKELY |
| 31 | 32 | ||
| 32 | namespace LIBC_NAMESPACE_DECL { | 33 | namespace LIBC_NAMESPACE_DECL { |
| ... | @@ -65,19 +66,11 @@ LIBC_INLINE void report_assertion_failure(const char *assertion, | ... | @@ -65,19 +66,11 @@ LIBC_INLINE void report_assertion_failure(const char *assertion, |
| 65 | } while (false) | 66 | } while (false) |
| 66 | #else | 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 | #define LIBC_ASSERT(COND) \ | 69 | #define LIBC_ASSERT(COND) \ |
| 76 | do { \ | 70 | do { \ |
| 77 | if (LIBC_UNLIKELY(!(COND))) { \ | 71 | if (LIBC_UNLIKELY(!(COND))) { \ |
| 78 | LIBC_NAMESPACE::write_to_stderr(__FILE__ ":" __LIBC_LINE_STR__ \ | 72 | LIBC_NAMESPACE::write_to_stderr(__FILE__ ":" LLVM_LIBC_STRINGIFY( \ |
| 79 | ": Assertion failed: '" #COND \ | 73 | __LINE__) ": Assertion failed: '" #COND "' in function: '"); \ |
| 80 | "' in function: '"); \ | ||
| 81 | LIBC_NAMESPACE::write_to_stderr(__PRETTY_FUNCTION__); \ | 74 | LIBC_NAMESPACE::write_to_stderr(__PRETTY_FUNCTION__); \ |
| 82 | LIBC_NAMESPACE::write_to_stderr("'\n"); \ | 75 | LIBC_NAMESPACE::write_to_stderr("'\n"); \ |
| 83 | LIBC_NAMESPACE::internal::exit(0xFF); \ | 76 | LIBC_NAMESPACE::internal::exit(0xFF); \ |
lib/libcxx/libc/src/__support/macros/attributes.h+74| ... | @@ -29,6 +29,80 @@ | ... | @@ -29,6 +29,80 @@ |
| 29 | #define LIBC_INLINE_ASM __asm__ __volatile__ | 29 | #define LIBC_INLINE_ASM __asm__ __volatile__ |
| 30 | #define LIBC_UNUSED __attribute__((unused)) | 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 | // Uses the platform specific specialization | 106 | // Uses the platform specific specialization |
| 33 | #define LIBC_THREAD_MODE_PLATFORM 0 | 107 | #define LIBC_THREAD_MODE_PLATFORM 0 |
| 34 | 108 |
lib/libcxx/libc/src/__support/macros/config.h+14| ... | @@ -48,6 +48,10 @@ | ... | @@ -48,6 +48,10 @@ |
| 48 | 48 | ||
| 49 | #define __builtin_prefetch(X, Y, Z) | 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 | #endif // LIBC_COMPILER_IS_MSVC | 55 | #endif // LIBC_COMPILER_IS_MSVC |
| 52 | 56 | ||
| 53 | #ifdef __clang__ | 57 | #ifdef __clang__ |
| ... | @@ -66,4 +70,14 @@ | ... | @@ -66,4 +70,14 @@ |
| 66 | #define LIBC_NAMESPACE_DECL LIBC_NAMESPACE | 70 | #define LIBC_NAMESPACE_DECL LIBC_NAMESPACE |
| 67 | #endif | 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 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H | 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,8 +32,13 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) { |
| 32 | #define LIBC_LOOP_NOUNROLL _Pragma("nounroll") | 32 | #define LIBC_LOOP_NOUNROLL _Pragma("nounroll") |
| 33 | #define LIBC_LOOP_UNROLL _Pragma("unroll") | 33 | #define LIBC_LOOP_UNROLL _Pragma("unroll") |
| 34 | #elif defined(LIBC_COMPILER_IS_GCC) | 34 | #elif defined(LIBC_COMPILER_IS_GCC) |
| 35 | #if LIBC_COMPILER_GCC_VER >= 800 | ||
| 35 | #define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0") | 36 | #define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0") |
| 36 | #define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048") | 37 | #define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048") |
| 38 | #else | ||
| 39 | #define LIBC_LOOP_NOUNROLL | ||
| 40 | #define LIBC_LOOP_UNROLL | ||
| 41 | #endif | ||
| 37 | #elif defined(LIBC_COMPILER_IS_MSVC) | 42 | #elif defined(LIBC_COMPILER_IS_MSVC) |
| 38 | #define LIBC_LOOP_NOUNROLL | 43 | #define LIBC_LOOP_NOUNROLL |
| 39 | #define LIBC_LOOP_UNROLL | 44 | #define LIBC_LOOP_UNROLL |
| ... | @@ -47,33 +52,39 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) { | ... | @@ -47,33 +52,39 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) { |
| 47 | #define LIBC_MATH_SMALL_TABLES 0x02 | 52 | #define LIBC_MATH_SMALL_TABLES 0x02 |
| 48 | #define LIBC_MATH_NO_ERRNO 0x04 | 53 | #define LIBC_MATH_NO_ERRNO 0x04 |
| 49 | #define LIBC_MATH_NO_EXCEPT 0x08 | 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 | #define LIBC_MATH_FAST \ | 57 | #define LIBC_MATH_FAST \ |
| 51 | (LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | \ | 58 | (LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | \ |
| 52 | LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT) | 59 | LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT | \ |
| 53 | #define LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT 0x10 | 60 | LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY) |
| 54 | 61 | ||
| 55 | #ifndef LIBC_MATH | 62 | #ifndef LIBC_MATH |
| 56 | #define LIBC_MATH 0 | 63 | #define LIBC_MATH 0 |
| 57 | #endif // LIBC_MATH | 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 | #define LIBC_MATH_HAS_SKIP_ACCURATE_PASS | 67 | #define LIBC_MATH_HAS_SKIP_ACCURATE_PASS |
| 61 | #endif | 68 | #endif |
| 62 | 69 | ||
| 63 | #if (LIBC_MATH & LIBC_MATH_SMALL_TABLES) | 70 | #if ((LIBC_MATH) & LIBC_MATH_SMALL_TABLES) |
| 64 | #define LIBC_MATH_HAS_SMALL_TABLES | 71 | #define LIBC_MATH_HAS_SMALL_TABLES |
| 65 | #endif | 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 | #define LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT | 75 | #define LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT |
| 69 | #endif | 76 | #endif |
| 70 | 77 | ||
| 71 | #if (LIBC_MATH & LIBC_MATH_NO_ERRNO) | 78 | #if ((LIBC_MATH) & LIBC_MATH_NO_ERRNO) |
| 72 | #define LIBC_MATH_HAS_NO_ERRNO | 79 | #define LIBC_MATH_HAS_NO_ERRNO |
| 73 | #endif | 80 | #endif |
| 74 | 81 | ||
| 75 | #if (LIBC_MATH & LIBC_MATH_NO_EXCEPT) | 82 | #if ((LIBC_MATH) & LIBC_MATH_NO_EXCEPT) |
| 76 | #define LIBC_MATH_HAS_NO_EXCEPT | 83 | #define LIBC_MATH_HAS_NO_EXCEPT |
| 77 | #endif | 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 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H | 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,11 +13,16 @@ |
| 13 | #define LIBC_TARGET_ARCH_IS_AMDGPU | 13 | #define LIBC_TARGET_ARCH_IS_AMDGPU |
| 14 | #endif | 14 | #endif |
| 15 | 15 | ||
| 16 | #if defined(__SPIRV__) | ||
| 17 | #define LIBC_TARGET_ARCH_IS_SPIRV | ||
| 18 | #endif | ||
| 19 | |||
| 16 | #if defined(__NVPTX__) | 20 | #if defined(__NVPTX__) |
| 17 | #define LIBC_TARGET_ARCH_IS_NVPTX | 21 | #define LIBC_TARGET_ARCH_IS_NVPTX |
| 18 | #endif | 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 | #define LIBC_TARGET_ARCH_IS_GPU | 26 | #define LIBC_TARGET_ARCH_IS_GPU |
| 22 | #endif | 27 | #endif |
| 23 | 28 |
lib/libcxx/libc/src/__support/macros/properties/cpu_features.h+7-2| ... | @@ -56,6 +56,10 @@ | ... | @@ -56,6 +56,10 @@ |
| 56 | #define LIBC_TARGET_CPU_HAS_AVX512BW | 56 | #define LIBC_TARGET_CPU_HAS_AVX512BW |
| 57 | #endif | 57 | #endif |
| 58 | 58 | ||
| 59 | #if defined(__AVX512F__) || defined(__AVX2__) | ||
| 60 | #define LIBC_TARGET_CPU_HAS_GATHER | ||
| 61 | #endif | ||
| 62 | |||
| 59 | #if defined(__ARM_FP) | 63 | #if defined(__ARM_FP) |
| 60 | #if (__ARM_FP & 0x2) | 64 | #if (__ARM_FP & 0x2) |
| 61 | #define LIBC_TARGET_CPU_HAS_ARM_FPU_HALF | 65 | #define LIBC_TARGET_CPU_HAS_ARM_FPU_HALF |
| ... | @@ -91,13 +95,14 @@ | ... | @@ -91,13 +95,14 @@ |
| 91 | #endif // LIBC_TARGET_CPU_HAS_RISCV_FPU_DOUBLE | 95 | #endif // LIBC_TARGET_CPU_HAS_RISCV_FPU_DOUBLE |
| 92 | #endif // __riscv_flen | 96 | #endif // __riscv_flen |
| 93 | 97 | ||
| 94 | #if defined(__NVPTX__) || defined(__AMDGPU__) | 98 | #if defined(__NVPTX__) || defined(__AMDGPU__) || defined(__SPIRV__) |
| 95 | #define LIBC_TARGET_CPU_HAS_FPU_FLOAT | 99 | #define LIBC_TARGET_CPU_HAS_FPU_FLOAT |
| 96 | #define LIBC_TARGET_CPU_HAS_FPU_DOUBLE | 100 | #define LIBC_TARGET_CPU_HAS_FPU_DOUBLE |
| 97 | #endif | 101 | #endif |
| 98 | 102 | ||
| 99 | #if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \ | 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 | #define LIBC_TARGET_CPU_HAS_FMA | 106 | #define LIBC_TARGET_CPU_HAS_FMA |
| 102 | // Provide a more fine-grained control of FMA instruction for ARM targets. | 107 | // Provide a more fine-grained control of FMA instruction for ARM targets. |
| 103 | #if defined(LIBC_TARGET_CPU_HAS_FPU_HALF) | 108 | #if defined(LIBC_TARGET_CPU_HAS_FPU_HALF) |
lib/libcxx/libc/src/__support/macros/sanitizer.h+7-6| ... | @@ -26,24 +26,25 @@ | ... | @@ -26,24 +26,25 @@ |
| 26 | #ifdef LIBC_HAS_MEMORY_SANITIZER | 26 | #ifdef LIBC_HAS_MEMORY_SANITIZER |
| 27 | // Only perform MSAN unpoison in non-constexpr context. | 27 | // Only perform MSAN unpoison in non-constexpr context. |
| 28 | #include <sanitizer/msan_interface.h> | 28 | #include <sanitizer/msan_interface.h> |
| 29 | #define MSAN_UNPOISON(addr, size) \ | 29 | #define LIBC_MSAN_UNPOISON(addr, size) \ |
| 30 | do { \ | 30 | do { \ |
| 31 | if (!__builtin_is_constant_evaluated()) \ | 31 | if (!__builtin_is_constant_evaluated()) \ |
| 32 | __msan_unpoison(addr, size); \ | 32 | __msan_unpoison(addr, size); \ |
| 33 | } while (0) | 33 | } while (0) |
| 34 | #else | 34 | #else |
| 35 | #define MSAN_UNPOISON(ptr, size) | 35 | #define LIBC_MSAN_UNPOISON(ptr, size) |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | #ifdef LIBC_HAS_ADDRESS_SANITIZER | 38 | #ifdef LIBC_HAS_ADDRESS_SANITIZER |
| 39 | #include <sanitizer/asan_interface.h> | 39 | #include <sanitizer/asan_interface.h> |
| 40 | #define ASAN_POISON_MEMORY_REGION(addr, size) \ | 40 | #define LIBC_ASAN_POISON_MEMORY_REGION(addr, size) \ |
| 41 | __asan_poison_memory_region((addr), (size)) | 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 | __asan_unpoison_memory_region((addr), (size)) | 43 | __asan_unpoison_memory_region((addr), (size)) |
| 44 | #else | 44 | #else |
| 45 | #define ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size)) | 45 | #define LIBC_ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size)) |
| 46 | #define ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size)) | 46 | #define LIBC_ASAN_UNPOISON_MEMORY_REGION(addr, size) \ |
| 47 | ((void)(addr), (void)(size)) | ||
| 47 | #endif | 48 | #endif |
| 48 | 49 | ||
| 49 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_SANITIZER_H | 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,6 +80,21 @@ template <typename T> |
| 80 | #endif // __builtin_sub_overflow | 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 | #define RETURN_IF(TYPE, BUILTIN) \ | 98 | #define RETURN_IF(TYPE, BUILTIN) \ |
| 84 | if constexpr (cpp::is_same_v<T, TYPE>) \ | 99 | if constexpr (cpp::is_same_v<T, TYPE>) \ |
| 85 | return BUILTIN(a, b, carry_in, &carry_out); | 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,7 +124,7 @@ eisel_lemire(ExpandedFloat<T> init_num, |
| 124 | // Wider Approximation | 124 | // Wider Approximation |
| 125 | UInt128 final_approx; | 125 | UInt128 final_approx; |
| 126 | // The halfway constant is used to check if the bits that will be shifted away | 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 | // mantissa size) - 3 (we shift away the last two bits separately for | 128 | // mantissa size) - 3 (we shift away the last two bits separately for |
| 129 | // accuracy, and the most significant bit is ignored.) = 9 bits. Similarly, | 129 | // accuracy, and the most significant bit is ignored.) = 9 bits. Similarly, |
| 130 | // it's 6 bits for floats in this case. | 130 | // it's 6 bits for floats in this case. |
| ... | @@ -262,7 +262,7 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num, | ... | @@ -262,7 +262,7 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num, |
| 262 | (final_approx_lower < approx_lower ? 1 : 0); | 262 | (final_approx_lower < approx_lower ? 1 : 0); |
| 263 | 263 | ||
| 264 | // The halfway constant is used to check if the bits that will be shifted away | 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 | // (final mantissa size) - 3 (we shift away the last two bits separately for | 266 | // (final mantissa size) - 3 (we shift away the last two bits separately for |
| 267 | // accuracy, and the most significant bit is ignored.) = 61 bits. Similarly, | 267 | // accuracy, and the most significant bit is ignored.) = 61 bits. Similarly, |
| 268 | // it's 12 bits for 128 bit floats in this case. | 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,17 +680,15 @@ template <> LIBC_INLINE constexpr int32_t get_lower_bound<double>() { |
| 680 | // accuracy. | 680 | // accuracy. |
| 681 | template <typename T, typename CharType> | 681 | template <typename T, typename CharType> |
| 682 | LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float( | 682 | LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float( |
| 683 | ExpandedFloat<T> init_num, bool truncated, RoundDirection round, | 683 | ExpandedFloat<T> init_num, [[maybe_unused]] bool truncated, |
| 684 | const CharType *__restrict numStart, | 684 | RoundDirection round, const CharType *__restrict numStart, |
| 685 | const size_t num_len = cpp::numeric_limits<size_t>::max()) { | 685 | const size_t num_len = cpp::numeric_limits<size_t>::max()) { |
| 686 | using FPBits = typename fputil::FPBits<T>; | 686 | using FPBits = typename fputil::FPBits<T>; |
| 687 | using StorageType = typename FPBits::StorageType; | ||
| 688 | 687 | ||
| 689 | StorageType mantissa = init_num.mantissa; | ||
| 690 | int32_t exp10 = init_num.exponent; | 688 | int32_t exp10 = init_num.exponent; |
| 691 | 689 | ||
| 692 | FloatConvertReturn<T> output; | 690 | FloatConvertReturn<T> output; |
| 693 | cpp::optional<ExpandedFloat<T>> opt_output; | 691 | [[maybe_unused]] cpp::optional<ExpandedFloat<T>> opt_output; |
| 694 | 692 | ||
| 695 | // If the exponent is too large and can't be represented in this size of | 693 | // If the exponent is too large and can't be represented in this size of |
| 696 | // float, return inf. These bounds are relatively loose, but are mostly | 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,6 +723,8 @@ LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float( |
| 725 | 723 | ||
| 726 | #ifndef LIBC_COPT_STRTOFLOAT_DISABLE_EISEL_LEMIRE | 724 | #ifndef LIBC_COPT_STRTOFLOAT_DISABLE_EISEL_LEMIRE |
| 727 | // Try Eisel-Lemire | 725 | // Try Eisel-Lemire |
| 726 | using StorageType = typename FPBits::StorageType; | ||
| 727 | StorageType mantissa = init_num.mantissa; | ||
| 728 | opt_output = eisel_lemire<T>(init_num, round); | 728 | opt_output = eisel_lemire<T>(init_num, round); |
| 729 | if (opt_output.has_value()) { | 729 | if (opt_output.has_value()) { |
| 730 | if (!truncated) { | 730 | if (!truncated) { |
| ... | @@ -1093,7 +1093,7 @@ hexadecimal_string_to_float(const CharType *__restrict src, | ... | @@ -1093,7 +1093,7 @@ hexadecimal_string_to_float(const CharType *__restrict src, |
| 1093 | } | 1093 | } |
| 1094 | 1094 | ||
| 1095 | template <typename T, typename CharType> | 1095 | template <typename T, typename CharType> |
| 1096 | LIBC_INLINE typename fputil::FPBits<T>::StorageType | 1096 | LIBC_INLINE constexpr typename fputil::FPBits<T>::StorageType |
| 1097 | nan_mantissa_from_ncharseq(const CharType *str, size_t len) { | 1097 | nan_mantissa_from_ncharseq(const CharType *str, size_t len) { |
| 1098 | using FPBits = typename fputil::FPBits<T>; | 1098 | using FPBits = typename fputil::FPBits<T>; |
| 1099 | using StorageType = typename FPBits::StorageType; | 1099 | using StorageType = typename FPBits::StorageType; |
| ... | @@ -1129,7 +1129,9 @@ strtofloatingpoint(const CharType *__restrict src) { | ... | @@ -1129,7 +1129,9 @@ strtofloatingpoint(const CharType *__restrict src) { |
| 1129 | 1129 | ||
| 1130 | size_t index = first_non_whitespace(src); | 1130 | size_t index = first_non_whitespace(src); |
| 1131 | int sign = get_sign(src + index); | 1131 | int sign = get_sign(src + index); |
| 1132 | #ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 1132 | bool is_positive = (sign >= 0); | 1133 | bool is_positive = (sign >= 0); |
| 1134 | #endif | ||
| 1133 | index += (sign != 0); | 1135 | index += (sign != 0); |
| 1134 | 1136 | ||
| 1135 | if (sign < 0) { | 1137 | if (sign < 0) { |
| ... | @@ -1146,6 +1148,7 @@ strtofloatingpoint(const CharType *__restrict src) { | ... | @@ -1146,6 +1148,7 @@ strtofloatingpoint(const CharType *__restrict src) { |
| 1146 | } | 1148 | } |
| 1147 | 1149 | ||
| 1148 | RoundDirection round_direction = RoundDirection::Nearest; | 1150 | RoundDirection round_direction = RoundDirection::Nearest; |
| 1151 | #ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 1149 | switch (fputil::quick_get_round()) { | 1152 | switch (fputil::quick_get_round()) { |
| 1150 | case FE_TONEAREST: | 1153 | case FE_TONEAREST: |
| 1151 | round_direction = RoundDirection::Nearest; | 1154 | round_direction = RoundDirection::Nearest; |
| ... | @@ -1160,6 +1163,7 @@ strtofloatingpoint(const CharType *__restrict src) { | ... | @@ -1160,6 +1163,7 @@ strtofloatingpoint(const CharType *__restrict src) { |
| 1160 | round_direction = RoundDirection::Down; | 1163 | round_direction = RoundDirection::Down; |
| 1161 | break; | 1164 | break; |
| 1162 | } | 1165 | } |
| 1166 | #endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY | ||
| 1163 | 1167 | ||
| 1164 | StrToNumResult<ExpandedFloat<T>> parse_result({0, 0}); | 1168 | StrToNumResult<ExpandedFloat<T>> parse_result({0, 0}); |
| 1165 | if (base == 16) { | 1169 | if (base == 16) { |
| ... | @@ -1221,7 +1225,8 @@ strtofloatingpoint(const CharType *__restrict src) { | ... | @@ -1221,7 +1225,8 @@ strtofloatingpoint(const CharType *__restrict src) { |
| 1221 | return {result.get_val(), static_cast<ptrdiff_t>(index), error}; | 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 | using FPBits = typename fputil::FPBits<T>; | 1230 | using FPBits = typename fputil::FPBits<T>; |
| 1226 | using StorageType = typename FPBits::StorageType; | 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,7 +33,7 @@ namespace internal { |
| 33 | // Returns the idx to the first character in src that is not a whitespace | 33 | // Returns the idx to the first character in src that is not a whitespace |
| 34 | // character (as determined by isspace()) | 34 | // character (as determined by isspace()) |
| 35 | template <typename CharType> | 35 | template <typename CharType> |
| 36 | LIBC_INLINE size_t | 36 | LIBC_INLINE constexpr size_t |
| 37 | first_non_whitespace(const CharType *__restrict src, | 37 | first_non_whitespace(const CharType *__restrict src, |
| 38 | size_t src_len = cpp::numeric_limits<size_t>::max()) { | 38 | size_t src_len = cpp::numeric_limits<size_t>::max()) { |
| 39 | size_t src_cur = 0; | 39 | size_t src_cur = 0; |
| ... | @@ -65,6 +65,18 @@ LIBC_INLINE static bool is_hex_start(const CharType *__restrict src, | ... | @@ -65,6 +65,18 @@ LIBC_INLINE static bool is_hex_start(const CharType *__restrict src, |
| 65 | b36_char_to_int(src[2]) < 16; | 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 | // Takes the address of the string pointer and parses the base from the start of | 80 | // Takes the address of the string pointer and parses the base from the start of |
| 69 | // it. | 81 | // it. |
| 70 | template <typename CharType> | 82 | template <typename CharType> |
| ... | @@ -75,6 +87,10 @@ LIBC_INLINE static int infer_base(const CharType *__restrict src, | ... | @@ -75,6 +87,10 @@ LIBC_INLINE static int infer_base(const CharType *__restrict src, |
| 75 | // with values 10 through 15 respectively." (C standard 6.4.4.1) | 87 | // with values 10 through 15 respectively." (C standard 6.4.4.1) |
| 76 | if (is_hex_start(src, src_len)) | 88 | if (is_hex_start(src, src_len)) |
| 77 | return 16; | 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 | // An octal number is defined as "the prefix 0 optionally followed by a | 94 | // An octal number is defined as "the prefix 0 optionally followed by a |
| 79 | // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any | 95 | // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any |
| 80 | // number that starts with 0, including just 0, is an octal number. | 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,7 +110,7 @@ LIBC_INLINE static int infer_base(const CharType *__restrict src, |
| 94 | // Takes a pointer to a string and the base to convert to. This function is used | 110 | // Takes a pointer to a string and the base to convert to. This function is used |
| 95 | // as the backend for all of the string to int functions. | 111 | // as the backend for all of the string to int functions. |
| 96 | template <typename T, typename CharType> | 112 | template <typename T, typename CharType> |
| 97 | LIBC_INLINE StrToNumResult<T> | 113 | LIBC_INLINE constexpr StrToNumResult<T> |
| 98 | strtointeger(const CharType *__restrict src, int base, | 114 | strtointeger(const CharType *__restrict src, int base, |
| 99 | const size_t src_len = cpp::numeric_limits<size_t>::max()) { | 115 | const size_t src_len = cpp::numeric_limits<size_t>::max()) { |
| 100 | using ResultType = make_integral_or_big_int_unsigned_t<T>; | 116 | using ResultType = make_integral_or_big_int_unsigned_t<T>; |
| ... | @@ -120,6 +136,9 @@ strtointeger(const CharType *__restrict src, int base, | ... | @@ -120,6 +136,9 @@ strtointeger(const CharType *__restrict src, int base, |
| 120 | if (base == 16 && is_hex_start(src + src_cur, src_len - src_cur)) | 136 | if (base == 16 && is_hex_start(src + src_cur, src_len - src_cur)) |
| 121 | src_cur = src_cur + 2; | 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 | constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>; | 142 | constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>; |
| 124 | ResultType constexpr NEGATIVE_MAX = | 143 | ResultType constexpr NEGATIVE_MAX = |
| 125 | !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1 | 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,6 +13,18 @@ |
| 13 | #include "src/__support/macros/attributes.h" // LIBC_INLINE | 13 | #include "src/__support/macros/attributes.h" // LIBC_INLINE |
| 14 | #include "src/__support/macros/config.h" | 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 | namespace LIBC_NAMESPACE_DECL { | 28 | namespace LIBC_NAMESPACE_DECL { |
| 17 | namespace internal { | 29 | namespace internal { |
| 18 | 30 | ||
| ... | @@ -38,8 +50,8 @@ namespace internal { | ... | @@ -38,8 +50,8 @@ namespace internal { |
| 38 | // This assumes the character ranges are contiguous, which they aren't in | 50 | // This assumes the character ranges are contiguous, which they aren't in |
| 39 | // EBCDIC. Technically we could use some smaller ranges, but that's even harder | 51 | // EBCDIC. Technically we could use some smaller ranges, but that's even harder |
| 40 | // to read. | 52 | // to read. |
| 41 | 53 | namespace ascii { | |
| 42 | LIBC_INLINE static constexpr bool islower(wchar_t wch) { | 54 | LIBC_INLINE constexpr bool islower(wchar_t wch) { |
| 43 | switch (wch) { | 55 | switch (wch) { |
| 44 | case L'a': | 56 | case L'a': |
| 45 | case L'b': | 57 | case L'b': |
| ... | @@ -73,7 +85,7 @@ LIBC_INLINE static constexpr bool islower(wchar_t wch) { | ... | @@ -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 | switch (wch) { | 89 | switch (wch) { |
| 78 | case L'A': | 90 | case L'A': |
| 79 | case L'B': | 91 | case L'B': |
| ... | @@ -107,7 +119,7 @@ LIBC_INLINE static constexpr bool isupper(wchar_t wch) { | ... | @@ -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 | switch (wch) { | 123 | switch (wch) { |
| 112 | case L'0': | 124 | case L'0': |
| 113 | case L'1': | 125 | case L'1': |
| ... | @@ -125,125 +137,169 @@ LIBC_INLINE static constexpr bool isdigit(wchar_t wch) { | ... | @@ -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 | switch (wch) { | 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 | case L'A': | 168 | case L'A': |
| 131 | return L'a'; | ||
| 132 | case L'B': | 169 | case L'B': |
| 133 | return L'b'; | ||
| 134 | case L'C': | 170 | case L'C': |
| 135 | return L'c'; | ||
| 136 | case L'D': | 171 | case L'D': |
| 137 | return L'd'; | ||
| 138 | case L'E': | 172 | case L'E': |
| 139 | return L'e'; | ||
| 140 | case L'F': | 173 | case L'F': |
| 141 | return L'f'; | ||
| 142 | case L'G': | 174 | case L'G': |
| 143 | return L'g'; | ||
| 144 | case L'H': | 175 | case L'H': |
| 145 | return L'h'; | ||
| 146 | case L'I': | 176 | case L'I': |
| 147 | return L'i'; | ||
| 148 | case L'J': | 177 | case L'J': |
| 149 | return L'j'; | ||
| 150 | case L'K': | 178 | case L'K': |
| 151 | return L'k'; | ||
| 152 | case L'L': | 179 | case L'L': |
| 153 | return L'l'; | ||
| 154 | case L'M': | 180 | case L'M': |
| 155 | return L'm'; | ||
| 156 | case L'N': | 181 | case L'N': |
| 157 | return L'n'; | ||
| 158 | case L'O': | 182 | case L'O': |
| 159 | return L'o'; | ||
| 160 | case L'P': | 183 | case L'P': |
| 161 | return L'p'; | ||
| 162 | case L'Q': | 184 | case L'Q': |
| 163 | return L'q'; | ||
| 164 | case L'R': | 185 | case L'R': |
| 165 | return L'r'; | ||
| 166 | case L'S': | 186 | case L'S': |
| 167 | return L's'; | ||
| 168 | case L'T': | 187 | case L'T': |
| 169 | return L't'; | ||
| 170 | case L'U': | 188 | case L'U': |
| 171 | return L'u'; | ||
| 172 | case L'V': | 189 | case L'V': |
| 173 | return L'v'; | ||
| 174 | case L'W': | 190 | case L'W': |
| 175 | return L'w'; | ||
| 176 | case L'X': | 191 | case L'X': |
| 177 | return L'x'; | ||
| 178 | case L'Y': | 192 | case L'Y': |
| 179 | return L'y'; | ||
| 180 | case L'Z': | 193 | case L'Z': |
| 181 | return L'z'; | 194 | return true; |
| 182 | default: | 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 | switch (wch) { | 201 | switch (wch) { |
| 189 | case L'a': | 202 | case L'a': |
| 190 | return L'A'; | ||
| 191 | case L'b': | 203 | case L'b': |
| 192 | return L'B'; | ||
| 193 | case L'c': | 204 | case L'c': |
| 194 | return L'C'; | ||
| 195 | case L'd': | 205 | case L'd': |
| 196 | return L'D'; | ||
| 197 | case L'e': | 206 | case L'e': |
| 198 | return L'E'; | ||
| 199 | case L'f': | 207 | case L'f': |
| 200 | return L'F'; | ||
| 201 | case L'g': | 208 | case L'g': |
| 202 | return L'G'; | ||
| 203 | case L'h': | 209 | case L'h': |
| 204 | return L'H'; | ||
| 205 | case L'i': | 210 | case L'i': |
| 206 | return L'I'; | ||
| 207 | case L'j': | 211 | case L'j': |
| 208 | return L'J'; | ||
| 209 | case L'k': | 212 | case L'k': |
| 210 | return L'K'; | ||
| 211 | case L'l': | 213 | case L'l': |
| 212 | return L'L'; | ||
| 213 | case L'm': | 214 | case L'm': |
| 214 | return L'M'; | ||
| 215 | case L'n': | 215 | case L'n': |
| 216 | return L'N'; | ||
| 217 | case L'o': | 216 | case L'o': |
| 218 | return L'O'; | ||
| 219 | case L'p': | 217 | case L'p': |
| 220 | return L'P'; | ||
| 221 | case L'q': | 218 | case L'q': |
| 222 | return L'Q'; | ||
| 223 | case L'r': | 219 | case L'r': |
| 224 | return L'R'; | ||
| 225 | case L's': | 220 | case L's': |
| 226 | return L'S'; | ||
| 227 | case L't': | 221 | case L't': |
| 228 | return L'T'; | ||
| 229 | case L'u': | 222 | case L'u': |
| 230 | return L'U'; | ||
| 231 | case L'v': | 223 | case L'v': |
| 232 | return L'V'; | ||
| 233 | case L'w': | 224 | case L'w': |
| 234 | return L'W'; | ||
| 235 | case L'x': | 225 | case L'x': |
| 236 | return L'X'; | ||
| 237 | case L'y': | 226 | case L'y': |
| 238 | return L'Y'; | ||
| 239 | case L'z': | 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 | default: | 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 | switch (wch) { | 303 | switch (wch) { |
| 248 | case L'a': | 304 | case L'a': |
| 249 | case L'b': | 305 | case L'b': |
| ... | @@ -251,129 +307,301 @@ LIBC_INLINE static constexpr bool isalpha(wchar_t wch) { | ... | @@ -251,129 +307,301 @@ LIBC_INLINE static constexpr bool isalpha(wchar_t wch) { |
| 251 | case L'd': | 307 | case L'd': |
| 252 | case L'e': | 308 | case L'e': |
| 253 | case L'f': | 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 | case L'A': | 310 | case L'A': |
| 275 | case L'B': | 311 | case L'B': |
| 276 | case L'C': | 312 | case L'C': |
| 277 | case L'D': | 313 | case L'D': |
| 278 | case L'E': | 314 | case L'E': |
| 279 | case L'F': | 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 | case L'G': | 354 | case L'G': |
| 355 | return L'g'; | ||
| 281 | case L'H': | 356 | case L'H': |
| 357 | return L'h'; | ||
| 282 | case L'I': | 358 | case L'I': |
| 359 | return L'i'; | ||
| 283 | case L'J': | 360 | case L'J': |
| 361 | return L'j'; | ||
| 284 | case L'K': | 362 | case L'K': |
| 363 | return L'k'; | ||
| 285 | case L'L': | 364 | case L'L': |
| 365 | return L'l'; | ||
| 286 | case L'M': | 366 | case L'M': |
| 367 | return L'm'; | ||
| 287 | case L'N': | 368 | case L'N': |
| 369 | return L'n'; | ||
| 288 | case L'O': | 370 | case L'O': |
| 371 | return L'o'; | ||
| 289 | case L'P': | 372 | case L'P': |
| 373 | return L'p'; | ||
| 290 | case L'Q': | 374 | case L'Q': |
| 375 | return L'q'; | ||
| 291 | case L'R': | 376 | case L'R': |
| 377 | return L'r'; | ||
| 292 | case L'S': | 378 | case L'S': |
| 379 | return L's'; | ||
| 293 | case L'T': | 380 | case L'T': |
| 381 | return L't'; | ||
| 294 | case L'U': | 382 | case L'U': |
| 383 | return L'u'; | ||
| 295 | case L'V': | 384 | case L'V': |
| 385 | return L'v'; | ||
| 296 | case L'W': | 386 | case L'W': |
| 387 | return L'w'; | ||
| 297 | case L'X': | 388 | case L'X': |
| 389 | return L'x'; | ||
| 298 | case L'Y': | 390 | case L'Y': |
| 391 | return L'y'; | ||
| 299 | case L'Z': | 392 | case L'Z': |
| 300 | return true; | 393 | return L'z'; |
| 301 | default: | 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 | switch (wch) { | 400 | switch (wch) { |
| 308 | case L'a': | 401 | case L'a': |
| 402 | return L'A'; | ||
| 309 | case L'b': | 403 | case L'b': |
| 404 | return L'B'; | ||
| 310 | case L'c': | 405 | case L'c': |
| 406 | return L'C'; | ||
| 311 | case L'd': | 407 | case L'd': |
| 408 | return L'D'; | ||
| 312 | case L'e': | 409 | case L'e': |
| 410 | return L'E'; | ||
| 313 | case L'f': | 411 | case L'f': |
| 412 | return L'F'; | ||
| 314 | case L'g': | 413 | case L'g': |
| 414 | return L'G'; | ||
| 315 | case L'h': | 415 | case L'h': |
| 416 | return L'H'; | ||
| 316 | case L'i': | 417 | case L'i': |
| 418 | return L'I'; | ||
| 317 | case L'j': | 419 | case L'j': |
| 420 | return L'J'; | ||
| 318 | case L'k': | 421 | case L'k': |
| 422 | return L'K'; | ||
| 319 | case L'l': | 423 | case L'l': |
| 424 | return L'L'; | ||
| 320 | case L'm': | 425 | case L'm': |
| 426 | return L'M'; | ||
| 321 | case L'n': | 427 | case L'n': |
| 428 | return L'N'; | ||
| 322 | case L'o': | 429 | case L'o': |
| 430 | return L'O'; | ||
| 323 | case L'p': | 431 | case L'p': |
| 432 | return L'P'; | ||
| 324 | case L'q': | 433 | case L'q': |
| 434 | return L'Q'; | ||
| 325 | case L'r': | 435 | case L'r': |
| 436 | return L'R'; | ||
| 326 | case L's': | 437 | case L's': |
| 438 | return L'S'; | ||
| 327 | case L't': | 439 | case L't': |
| 440 | return L'T'; | ||
| 328 | case L'u': | 441 | case L'u': |
| 442 | return L'U'; | ||
| 329 | case L'v': | 443 | case L'v': |
| 444 | return L'V'; | ||
| 330 | case L'w': | 445 | case L'w': |
| 446 | return L'W'; | ||
| 331 | case L'x': | 447 | case L'x': |
| 448 | return L'X'; | ||
| 332 | case L'y': | 449 | case L'y': |
| 450 | return L'Y'; | ||
| 333 | case L'z': | 451 | case L'z': |
| 334 | case L'A': | 452 | return L'Z'; |
| 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; | ||
| 371 | default: | 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 | switch (wch) { | 605 | switch (wch) { |
| 378 | case L'0': | 606 | case L'0': |
| 379 | return 0; | 607 | return 0; |
| ... | @@ -561,20 +789,6 @@ LIBC_INLINE static constexpr wchar_t int_to_b36_wchar(int num) { | ... | @@ -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 | // An overload which provides a way to compare input with specific character | 792 | // An overload which provides a way to compare input with specific character |
| 579 | // values, when input can be of a regular or a wide character type. | 793 | // values, when input can be of a regular or a wide character type. |
| 580 | LIBC_INLINE static constexpr bool | 794 | LIBC_INLINE static constexpr bool |