| author | |
| committer | |
| log | c47c05386eab5982b0fb20aa58ab80e202e97393 |
| tree | d53510783643e7ed7291fdc8652384e74ce6a303 |
| parent | 9f2f6aaef519fe37a6936653bbd01b69b1f65a2f |
37 files changed, 1277 insertions(+), 281 deletions(-)
lib/libcxx/libc/hdr/errno_macros.h+3-1| ... | ... | @@ -15,7 +15,9 @@ |
| 15 | 15 | #include <linux/errno.h> |
| 16 | 16 | |
| 17 | 17 | #include "include/llvm-libc-macros/error-number-macros.h" |
| 18 | #else // __linux__ | |
| 18 | #elif defined(__APPLE__) | |
| 19 | #include <sys/errno.h> | |
| 20 | #else // __APPLE__ | |
| 19 | 21 | #include "include/llvm-libc-macros/generic-error-number-macros.h" |
| 20 | 22 | #endif |
| 21 | 23 |
lib/libcxx/libc/hdr/stdint_proxy.h created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | //===-- stdint.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 | #ifndef LLVM_LIBC_HDR_STDINT_PROXY_H | |
| 10 | #define LLVM_LIBC_HDR_STDINT_PROXY_H | |
| 11 | ||
| 12 | // This target is to make sure we have correct build order in full build mode, | |
| 13 | // that is `libc.include.stdint` is added to the dependency of all targets | |
| 14 | // that use <stdint.h> header. | |
| 15 | ||
| 16 | #include <stdint.h> | |
| 17 | ||
| 18 | #endif // LLVM_LIBC_HDR_STDINT_PROXY_H |
lib/libcxx/libc/hdr/types/wchar_t.h created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | //===-- Definition of wchar_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_WCHAR_T_H | |
| 11 | #define LLVM_LIBC_HDR_TYPES_WCHAR_T_H | |
| 12 | ||
| 13 | #ifdef LIBC_FULL_BUILD | |
| 14 | ||
| 15 | #include "include/llvm-libc-types/wchar_t.h" | |
| 16 | ||
| 17 | #else // overlay mode | |
| 18 | ||
| 19 | #include "hdr/wchar_overlay.h" | |
| 20 | ||
| 21 | #endif // LLVM_LIBC_FULL_BUILD | |
| 22 | ||
| 23 | #endif // LLVM_LIBC_HDR_TYPES_WCHAR_T_H |
lib/libcxx/libc/hdr/wchar_overlay.h created+69| ... | ... | @@ -0,0 +1,69 @@ |
| 1 | //===-- Including wchar.h in overlay mode ---------------------------------===// | |
| 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_HDR_WCHAR_OVERLAY_H | |
| 10 | #define LLVM_LIBC_HDR_WCHAR_OVERLAY_H | |
| 11 | ||
| 12 | #ifdef LIBC_FULL_BUILD | |
| 13 | #error "This header should only be included in overlay mode" | |
| 14 | #endif | |
| 15 | ||
| 16 | // Overlay mode | |
| 17 | ||
| 18 | // glibc <wchar.h> header might provide extern inline definitions for few | |
| 19 | // functions, causing external alias errors. They are guarded by | |
| 20 | // `__USE_EXTERN_INLINES` macro. We temporarily disable `__USE_EXTERN_INLINES` | |
| 21 | // macro by defining `__NO_INLINE__` before including <wchar.h>. | |
| 22 | // And the same with `__USE_FORTIFY_LEVEL`, which will be temporarily disabled | |
| 23 | // with `_FORTIFY_SOURCE`. | |
| 24 | ||
| 25 | #ifdef _FORTIFY_SOURCE | |
| 26 | #define LIBC_OLD_FORTIFY_SOURCE _FORTIFY_SOURCE | |
| 27 | #undef _FORTIFY_SOURCE | |
| 28 | #endif | |
| 29 | ||
| 30 | #ifndef __NO_INLINE__ | |
| 31 | #define __NO_INLINE__ 1 | |
| 32 | #define LIBC_SET_NO_INLINE | |
| 33 | #endif | |
| 34 | ||
| 35 | #ifdef __USE_EXTERN_INLINES | |
| 36 | #define LIBC_OLD_USE_EXTERN_INLINES | |
| 37 | #undef __USE_EXTERN_INLINES | |
| 38 | #endif | |
| 39 | ||
| 40 | #ifdef __USE_FORTIFY_LEVEL | |
| 41 | #define LIBC_OLD_USE_FORTIFY_LEVEL __USE_FORTIFY_LEVEL | |
| 42 | #undef __USE_FORTIFY_LEVEL | |
| 43 | #define __USE_FORTIFY_LEVEL 0 | |
| 44 | #endif | |
| 45 | ||
| 46 | #include <wchar.h> | |
| 47 | ||
| 48 | #ifdef LIBC_OLD_FORTIFY_SOURCE | |
| 49 | #define _FORTIFY_SOURCE LIBC_OLD_FORTIFY_SOURCE | |
| 50 | #undef LIBC_OLD_FORTIFY_SOURCE | |
| 51 | #endif | |
| 52 | ||
| 53 | #ifdef LIBC_SET_NO_INLINE | |
| 54 | #undef __NO_INLINE__ | |
| 55 | #undef LIBC_SET_NO_INLINE | |
| 56 | #endif | |
| 57 | ||
| 58 | #ifdef LIBC_OLD_USE_FORTIFY_LEVEL | |
| 59 | #undef __USE_FORTIFY_LEVEL | |
| 60 | #define __USE_FORTIFY_LEVEL LIBC_OLD_USE_FORTIFY_LEVEL | |
| 61 | #undef LIBC_OLD_USE_FORTIFY_LEVEL | |
| 62 | #endif | |
| 63 | ||
| 64 | #ifdef LIBC_OLD_USE_EXTERN_INLINES | |
| 65 | #define __USE_EXTERN_INLINES | |
| 66 | #undef LIBC_OLD_USE_EXTERN_INLINES | |
| 67 | #endif | |
| 68 | ||
| 69 | #endif // LLVM_LIBC_HDR_WCHAR_OVERLAY_H |
lib/libcxx/libc/include/llvm-libc-macros/cfloat128-macros.h created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | //===-- Detection of _Complex _Float128 compiler builtin type -------------===// | |
| 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_MACROS_CFLOAT128_MACROS_H | |
| 10 | #define LLVM_LIBC_MACROS_CFLOAT128_MACROS_H | |
| 11 | ||
| 12 | #include "float-macros.h" // LDBL_MANT_DIG | |
| 13 | ||
| 14 | // Currently, the complex variant of C23 `_Float128` type is only defined as a | |
| 15 | // built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For | |
| 16 | // clang, the complex variant of `__float128` is defined instead, and only on | |
| 17 | // x86-64 targets for clang 11 or later. | |
| 18 | // | |
| 19 | // TODO: Update the complex variant of C23 `_Float128` type detection again when | |
| 20 | // clang supports it. | |
| 21 | #ifdef __clang__ | |
| 22 | #if (__clang_major__ >= 11) && \ | |
| 23 | (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) | |
| 24 | // Use _Complex __float128 type. clang uses __SIZEOF_FLOAT128__ or __FLOAT128__ | |
| 25 | // macro to notify the availability of __float128 type: | |
| 26 | // https://reviews.llvm.org/D15120 | |
| 27 | #define LIBC_TYPES_HAS_CFLOAT128 | |
| 28 | #endif | |
| 29 | #elif defined(__GNUC__) | |
| 30 | #if (defined(__STDC_IEC_60559_COMPLEX__) || defined(__SIZEOF_FLOAT128__)) && \ | |
| 31 | (__GNUC__ >= 13 || (!defined(__cplusplus))) | |
| 32 | #define LIBC_TYPES_HAS_CFLOAT128 | |
| 33 | #endif | |
| 34 | #endif | |
| 35 | ||
| 36 | #if !defined(LIBC_TYPES_HAS_CFLOAT128) && (LDBL_MANT_DIG == 113) | |
| 37 | #define LIBC_TYPES_HAS_CFLOAT128 | |
| 38 | #define LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE | |
| 39 | #endif | |
| 40 | ||
| 41 | #endif // LLVM_LIBC_MACROS_CFLOAT128_MACROS_H |
lib/libcxx/libc/include/llvm-libc-macros/cfloat16-macros.h created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | //===-- Detection of _Complex _Float16 compiler builtin type --------------===// | |
| 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_MACROS_CFLOAT16_MACROS_H | |
| 10 | #define LLVM_LIBC_MACROS_CFLOAT16_MACROS_H | |
| 11 | ||
| 12 | #if defined(__FLT16_MANT_DIG__) && \ | |
| 13 | (!defined(__GNUC__) || __GNUC__ >= 13 || \ | |
| 14 | (defined(__clang__) && __clang_major__ >= 14)) && \ | |
| 15 | !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \ | |
| 16 | !defined(_WIN32) | |
| 17 | #define LIBC_TYPES_HAS_CFLOAT16 | |
| 18 | #endif | |
| 19 | ||
| 20 | #endif // LLVM_LIBC_MACROS_CFLOAT16_MACROS_H |
lib/libcxx/libc/include/llvm-libc-macros/wchar-macros.h created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | //===-- Macros defined in wchar.h header file -----------------------------===// | |
| 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_MACROS_WCHAR_MACROS_H | |
| 10 | #define LLVM_LIBC_MACROS_WCHAR_MACROS_H | |
| 11 | ||
| 12 | #include "../llvm-libc-types/wint_t.h" | |
| 13 | ||
| 14 | #ifndef WEOF | |
| 15 | #define WEOF ((wint_t)(0xffffffffu)) | |
| 16 | #endif | |
| 17 | ||
| 18 | #endif // LLVM_LIBC_MACROS_WCHAR_MACROS_H |
lib/libcxx/libc/include/llvm-libc-types/cfloat128.h+11-28| ... | ... | @@ -9,36 +9,19 @@ |
| 9 | 9 | #ifndef LLVM_LIBC_TYPES_CFLOAT128_H |
| 10 | 10 | #define LLVM_LIBC_TYPES_CFLOAT128_H |
| 11 | 11 | |
| 12 | #include "../llvm-libc-macros/float-macros.h" // LDBL_MANT_DIG | |
| 12 | #include "../llvm-libc-macros/cfloat128-macros.h" | |
| 13 | 13 | |
| 14 | // Currently, the complex variant of C23 `_Float128` type is only defined as a | |
| 15 | // built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For | |
| 16 | // clang, the complex variant of `__float128` is defined instead, and only on | |
| 17 | // x86-64 targets for clang 11 or later. | |
| 18 | // | |
| 19 | // TODO: Update the complex variant of C23 `_Float128` type detection again when | |
| 20 | // clang supports it. | |
| 21 | #ifdef __clang__ | |
| 22 | #if (__clang_major__ >= 11) && \ | |
| 23 | (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) | |
| 24 | // Use _Complex __float128 type. clang uses __SIZEOF_FLOAT128__ or __FLOAT128__ | |
| 25 | // macro to notify the availability of __float128 type: | |
| 26 | // https://reviews.llvm.org/D15120 | |
| 27 | #define LIBC_TYPES_HAS_CFLOAT128 | |
| 14 | #ifdef LIBC_TYPES_HAS_CFLOAT128 | |
| 15 | #ifndef LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE | |
| 16 | #if defined(__GNUC__) && !defined(__clang__) | |
| 17 | // Remove the workaround when https://gcc.gnu.org/PR32187 gets fixed. | |
| 18 | typedef __typeof__(_Complex __float128) cfloat128; | |
| 19 | #else // ^^^ workaround / no workaround vvv | |
| 28 | 20 | typedef _Complex __float128 cfloat128; |
| 29 | #endif | |
| 30 | #elif defined(__GNUC__) | |
| 31 | #if (defined(__STDC_IEC_60559_COMPLEX__) || defined(__SIZEOF_FLOAT128__)) && \ | |
| 32 | (__GNUC__ >= 13 || (!defined(__cplusplus))) | |
| 33 | #define LIBC_TYPES_HAS_CFLOAT128 | |
| 34 | typedef _Complex _Float128 cfloat128; | |
| 35 | #endif | |
| 36 | #endif | |
| 37 | ||
| 38 | #if !defined(LIBC_TYPES_HAS_CFLOAT128) && (LDBL_MANT_DIG == 113) | |
| 39 | #define LIBC_TYPES_HAS_CFLOAT128 | |
| 40 | #define LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE | |
| 21 | #endif // ^^^ no workaround ^^^ | |
| 22 | #else | |
| 41 | 23 | typedef _Complex long double cfloat128; |
| 42 | #endif | |
| 24 | #endif // LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE | |
| 25 | #endif // LIBC_TYPES_HAS_CFLOAT128 | |
| 43 | 26 | |
| 44 | 27 | #endif // LLVM_LIBC_TYPES_CFLOAT128_H |
lib/libcxx/libc/include/llvm-libc-types/cfloat16.h+4-7| ... | ... | @@ -9,13 +9,10 @@ |
| 9 | 9 | #ifndef LLVM_LIBC_TYPES_CFLOAT16_H |
| 10 | 10 | #define LLVM_LIBC_TYPES_CFLOAT16_H |
| 11 | 11 | |
| 12 | #if defined(__FLT16_MANT_DIG__) && \ | |
| 13 | (!defined(__GNUC__) || __GNUC__ >= 13 || \ | |
| 14 | (defined(__clang__) && __clang_major__ >= 14)) && \ | |
| 15 | !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \ | |
| 16 | !defined(_WIN32) | |
| 17 | #define LIBC_TYPES_HAS_CFLOAT16 | |
| 12 | #include "../llvm-libc-macros/cfloat16-macros.h" | |
| 13 | ||
| 14 | #ifdef LIBC_TYPES_HAS_CFLOAT16 | |
| 18 | 15 | typedef _Complex _Float16 cfloat16; |
| 19 | #endif | |
| 16 | #endif // LIBC_TYPES_HAS_CFLOAT16 | |
| 20 | 17 | |
| 21 | 18 | #endif // LLVM_LIBC_TYPES_CFLOAT16_H |
lib/libcxx/libc/include/llvm-libc-types/wint_t.h created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | //===-- Definition of wint_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_WINT_T_H | |
| 10 | #define LLVM_LIBC_TYPES_WINT_T_H | |
| 11 | ||
| 12 | typedef __WINT_TYPE__ wint_t; | |
| 13 | ||
| 14 | #endif // LLVM_LIBC_TYPES_WINT_T_H |
lib/libcxx/libc/shared/libc_common.h+5| ... | ... | @@ -19,6 +19,11 @@ |
| 19 | 19 | #define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM_INLINE |
| 20 | 20 | #endif // LIBC_ERRNO_MODE |
| 21 | 21 | |
| 22 | // Use system fenv functions in math implementations. | |
| 23 | #ifndef LIBC_MATH_USE_SYSTEM_FENV | |
| 24 | #define LIBC_MATH_USE_SYSTEM_FENV | |
| 25 | #endif // LIBC_MATH_USE_SYSTEM_FENV | |
| 26 | ||
| 22 | 27 | #ifndef LIBC_NAMESPACE |
| 23 | 28 | #define LIBC_NAMESPACE __llvm_libc |
| 24 | 29 | #endif // LIBC_NAMESPACE |
lib/libcxx/libc/src/__support/CPP/bit.h+50-12| ... | ... | @@ -11,14 +11,14 @@ |
| 11 | 11 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H |
| 12 | 12 | #define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H |
| 13 | 13 | |
| 14 | #include "hdr/stdint_proxy.h" | |
| 14 | 15 | #include "src/__support/CPP/limits.h" // numeric_limits |
| 15 | 16 | #include "src/__support/CPP/type_traits.h" |
| 16 | 17 | #include "src/__support/macros/attributes.h" |
| 17 | 18 | #include "src/__support/macros/config.h" |
| 19 | #include "src/__support/macros/properties/compiler.h" | |
| 18 | 20 | #include "src/__support/macros/sanitizer.h" |
| 19 | 21 | |
| 20 | #include <stdint.h> | |
| 21 | ||
| 22 | 22 | namespace LIBC_NAMESPACE_DECL { |
| 23 | 23 | namespace cpp { |
| 24 | 24 | |
| ... | ... | @@ -26,6 +26,16 @@ namespace cpp { |
| 26 | 26 | #define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE |
| 27 | 27 | #endif |
| 28 | 28 | |
| 29 | template <unsigned N> | |
| 30 | LIBC_INLINE static void inline_copy(const char *from, char *to) { | |
| 31 | #if __has_builtin(__builtin_memcpy_inline) | |
| 32 | __builtin_memcpy_inline(to, from, N); | |
| 33 | #else | |
| 34 | for (unsigned i = 0; i < N; ++i) | |
| 35 | to[i] = from[i]; | |
| 36 | #endif // __has_builtin(__builtin_memcpy_inline) | |
| 37 | } | |
| 38 | ||
| 29 | 39 | // This implementation of bit_cast requires trivially-constructible To, to avoid |
| 30 | 40 | // UB in the implementation. |
| 31 | 41 | template <typename To, typename From> |
| ... | ... | @@ -37,22 +47,32 @@ LIBC_INLINE constexpr cpp::enable_if_t< |
| 37 | 47 | To> |
| 38 | 48 | bit_cast(const From &from) { |
| 39 | 49 | MSAN_UNPOISON(&from, sizeof(From)); |
| 40 | #if __has_builtin(__builtin_bit_cast) | |
| 50 | #if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC) | |
| 41 | 51 | return __builtin_bit_cast(To, from); |
| 42 | 52 | #else |
| 43 | To to; | |
| 53 | To to{}; | |
| 44 | 54 | char *dst = reinterpret_cast<char *>(&to); |
| 45 | 55 | const char *src = reinterpret_cast<const char *>(&from); |
| 46 | #if __has_builtin(__builtin_memcpy_inline) | |
| 47 | __builtin_memcpy_inline(dst, src, sizeof(To)); | |
| 48 | #else | |
| 49 | for (unsigned i = 0; i < sizeof(To); ++i) | |
| 50 | dst[i] = src[i]; | |
| 51 | #endif // __has_builtin(__builtin_memcpy_inline) | |
| 56 | inline_copy<sizeof(From)>(src, dst); | |
| 52 | 57 | return to; |
| 53 | 58 | #endif // __has_builtin(__builtin_bit_cast) |
| 54 | 59 | } |
| 55 | 60 | |
| 61 | // The following simple bit copy from a smaller type to maybe-larger type. | |
| 62 | template <typename To, typename From> | |
| 63 | LIBC_INLINE constexpr cpp::enable_if_t< | |
| 64 | (sizeof(To) >= sizeof(From)) && | |
| 65 | cpp::is_trivially_constructible<To>::value && | |
| 66 | cpp::is_trivially_copyable<To>::value && | |
| 67 | cpp::is_trivially_copyable<From>::value, | |
| 68 | void> | |
| 69 | bit_copy(const From &from, To &to) { | |
| 70 | MSAN_UNPOISON(&from, sizeof(From)); | |
| 71 | char *dst = reinterpret_cast<char *>(&to); | |
| 72 | const char *src = reinterpret_cast<const char *>(&from); | |
| 73 | inline_copy<sizeof(From)>(src, dst); | |
| 74 | } | |
| 75 | ||
| 56 | 76 | template <typename T> |
| 57 | 77 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, |
| 58 | 78 | bool> |
| ... | ... | @@ -105,10 +125,16 @@ countr_zero(T value) { |
| 105 | 125 | } |
| 106 | 126 | #if __has_builtin(__builtin_ctzs) |
| 107 | 127 | ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs) |
| 108 | #endif | |
| 128 | #endif // __has_builtin(__builtin_ctzs) | |
| 129 | #if __has_builtin(__builtin_ctz) | |
| 109 | 130 | ADD_SPECIALIZATION(countr_zero, unsigned int, __builtin_ctz) |
| 131 | #endif // __has_builtin(__builtin_ctz) | |
| 132 | #if __has_builtin(__builtin_ctzl) | |
| 110 | 133 | ADD_SPECIALIZATION(countr_zero, unsigned long, __builtin_ctzl) |
| 134 | #endif // __has_builtin(__builtin_ctzl) | |
| 135 | #if __has_builtin(__builtin_ctzll) | |
| 111 | 136 | ADD_SPECIALIZATION(countr_zero, unsigned long long, __builtin_ctzll) |
| 137 | #endif // __has_builtin(__builtin_ctzll) | |
| 112 | 138 | #endif // __has_builtin(__builtin_ctzg) |
| 113 | 139 | |
| 114 | 140 | /// Count number of 0's from the most significant bit to the least |
| ... | ... | @@ -144,10 +170,16 @@ countl_zero(T value) { |
| 144 | 170 | } |
| 145 | 171 | #if __has_builtin(__builtin_clzs) |
| 146 | 172 | ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs) |
| 147 | #endif | |
| 173 | #endif // __has_builtin(__builtin_clzs) | |
| 174 | #if __has_builtin(__builtin_clz) | |
| 148 | 175 | ADD_SPECIALIZATION(countl_zero, unsigned int, __builtin_clz) |
| 176 | #endif // __has_builtin(__builtin_clz) | |
| 177 | #if __has_builtin(__builtin_clzl) | |
| 149 | 178 | ADD_SPECIALIZATION(countl_zero, unsigned long, __builtin_clzl) |
| 179 | #endif // __has_builtin(__builtin_clzl) | |
| 180 | #if __has_builtin(__builtin_clzll) | |
| 150 | 181 | ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll) |
| 182 | #endif // __has_builtin(__builtin_clzll) | |
| 151 | 183 | #endif // __has_builtin(__builtin_clzg) |
| 152 | 184 | |
| 153 | 185 | #undef ADD_SPECIALIZATION |
| ... | ... | @@ -284,11 +316,17 @@ popcount(T value) { |
| 284 | 316 | [[nodiscard]] LIBC_INLINE constexpr int popcount<TYPE>(TYPE value) { \ |
| 285 | 317 | return BUILTIN(value); \ |
| 286 | 318 | } |
| 319 | #if __has_builtin(__builtin_popcount) | |
| 287 | 320 | ADD_SPECIALIZATION(unsigned char, __builtin_popcount) |
| 288 | 321 | ADD_SPECIALIZATION(unsigned short, __builtin_popcount) |
| 289 | 322 | ADD_SPECIALIZATION(unsigned, __builtin_popcount) |
| 323 | #endif // __builtin_popcount | |
| 324 | #if __has_builtin(__builtin_popcountl) | |
| 290 | 325 | ADD_SPECIALIZATION(unsigned long, __builtin_popcountl) |
| 326 | #endif // __builtin_popcountl | |
| 327 | #if __has_builtin(__builtin_popcountll) | |
| 291 | 328 | ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) |
| 329 | #endif // __builtin_popcountll | |
| 292 | 330 | #endif // __builtin_popcountg |
| 293 | 331 | #undef ADD_SPECIALIZATION |
| 294 | 332 |
lib/libcxx/libc/src/__support/CPP/type_traits/is_complex.h+7| ... | ... | @@ -13,12 +13,17 @@ |
| 13 | 13 | #include "src/__support/macros/attributes.h" |
| 14 | 14 | #include "src/__support/macros/config.h" |
| 15 | 15 | // LIBC_TYPES_HAS_CFLOAT16 && LIBC_TYPES_HAS_CFLOAT128 |
| 16 | #include "src/__support/macros/properties/compiler.h" | |
| 16 | 17 | #include "src/__support/macros/properties/complex_types.h" |
| 17 | 18 | |
| 18 | 19 | namespace LIBC_NAMESPACE_DECL { |
| 19 | 20 | namespace cpp { |
| 20 | 21 | |
| 21 | 22 | // is_complex |
| 23 | #ifdef LIBC_COMPILER_IS_MSVC | |
| 24 | // TODO: Add support for complex types with MSVC. | |
| 25 | template <typename T> struct is_complex : false_type {}; | |
| 26 | #else | |
| 22 | 27 | template <typename T> struct is_complex { |
| 23 | 28 | private: |
| 24 | 29 | template <typename Head, typename... Args> |
| ... | ... | @@ -40,6 +45,8 @@ public: |
| 40 | 45 | #endif |
| 41 | 46 | >(); |
| 42 | 47 | }; |
| 48 | #endif // LIBC_COMPILER_IS_MSVC | |
| 49 | ||
| 43 | 50 | template <typename T> |
| 44 | 51 | LIBC_INLINE_VAR constexpr bool is_complex_v = is_complex<T>::value; |
| 45 | 52 | template <typename T1, typename T2> |
lib/libcxx/libc/src/__support/CPP/type_traits/is_destructible.h+2-1| ... | ... | @@ -15,6 +15,7 @@ |
| 15 | 15 | #include "src/__support/CPP/type_traits/remove_all_extents.h" |
| 16 | 16 | #include "src/__support/CPP/type_traits/true_type.h" |
| 17 | 17 | #include "src/__support/CPP/type_traits/type_identity.h" |
| 18 | #include "src/__support/CPP/utility/declval.h" | |
| 18 | 19 | #include "src/__support/macros/attributes.h" |
| 19 | 20 | #include "src/__support/macros/config.h" |
| 20 | 21 | |
| ... | ... | @@ -22,7 +23,7 @@ namespace LIBC_NAMESPACE_DECL { |
| 22 | 23 | namespace cpp { |
| 23 | 24 | |
| 24 | 25 | // is_destructible |
| 25 | #if __has_builtin(__is_destructible) | |
| 26 | #if __has_builtin(__is_destructible) || defined(LIBC_COMPILER_IS_MSVC) | |
| 26 | 27 | template <typename T> |
| 27 | 28 | struct is_destructible : bool_constant<__is_destructible(T)> {}; |
| 28 | 29 | #else |
lib/libcxx/libc/src/__support/CPP/type_traits/is_unsigned.h+6| ... | ... | @@ -16,6 +16,8 @@ |
| 16 | 16 | #include "src/__support/macros/attributes.h" |
| 17 | 17 | #include "src/__support/macros/config.h" |
| 18 | 18 | |
| 19 | #include <stddef.h> | |
| 20 | ||
| 19 | 21 | namespace LIBC_NAMESPACE_DECL { |
| 20 | 22 | namespace cpp { |
| 21 | 23 | |
| ... | ... | @@ -46,6 +48,10 @@ public: |
| 46 | 48 | LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; } |
| 47 | 49 | }; |
| 48 | 50 | #endif // LIBC_COMPILER_HAS_FIXED_POINT |
| 51 | #if LIBC_HAS_VECTOR_TYPE | |
| 52 | template <typename T, size_t N> | |
| 53 | struct is_unsigned<T [[clang::ext_vector_type(N)]]> : bool_constant<false> {}; | |
| 54 | #endif | |
| 49 | 55 | |
| 50 | 56 | template <typename T> |
| 51 | 57 | LIBC_INLINE_VAR constexpr bool is_unsigned_v = is_unsigned<T>::value; |
lib/libcxx/libc/src/__support/CPP/utility/integer_sequence.h+10| ... | ... | @@ -5,12 +5,15 @@ |
| 5 | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | 6 | // |
| 7 | 7 | //===----------------------------------------------------------------------===// |
| 8 | ||
| 8 | 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H |
| 9 | 10 | #define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H |
| 10 | 11 | |
| 11 | 12 | #include "src/__support/CPP/type_traits/is_integral.h" |
| 12 | 13 | #include "src/__support/macros/config.h" |
| 13 | 14 | |
| 15 | #include <stddef.h> | |
| 16 | ||
| 14 | 17 | namespace LIBC_NAMESPACE_DECL { |
| 15 | 18 | namespace cpp { |
| 16 | 19 | |
| ... | ... | @@ -34,6 +37,13 @@ template <typename T, int N> |
| 34 | 37 | using make_integer_sequence = |
| 35 | 38 | typename detail::make_integer_sequence<T, N - 1>::type; |
| 36 | 39 | |
| 40 | // index sequence | |
| 41 | template <size_t... Ints> | |
| 42 | using index_sequence = integer_sequence<size_t, Ints...>; | |
| 43 | template <int N> | |
| 44 | using make_index_sequence = | |
| 45 | typename detail::make_integer_sequence<size_t, N - 1>::type; | |
| 46 | ||
| 37 | 47 | } // namespace cpp |
| 38 | 48 | } // namespace LIBC_NAMESPACE_DECL |
| 39 | 49 |
lib/libcxx/libc/src/__support/FPUtil/FPBits.h+6-7| ... | ... | @@ -15,6 +15,7 @@ |
| 15 | 15 | #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H |
| 16 | 16 | #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H |
| 17 | 17 | |
| 18 | #include "hdr/stdint_proxy.h" | |
| 18 | 19 | #include "src/__support/CPP/bit.h" |
| 19 | 20 | #include "src/__support/CPP/type_traits.h" |
| 20 | 21 | #include "src/__support/common.h" |
| ... | ... | @@ -26,8 +27,6 @@ |
| 26 | 27 | #include "src/__support/sign.h" // Sign |
| 27 | 28 | #include "src/__support/uint128.h" |
| 28 | 29 | |
| 29 | #include <stdint.h> | |
| 30 | ||
| 31 | 30 | namespace LIBC_NAMESPACE_DECL { |
| 32 | 31 | namespace fputil { |
| 33 | 32 | |
| ... | ... | @@ -790,16 +789,16 @@ struct FPRep : public FPRepImpl<fp_type, FPRep<fp_type>> { |
| 790 | 789 | // Returns the FPType corresponding to C++ type T on the host. |
| 791 | 790 | template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() { |
| 792 | 791 | using UnqualT = cpp::remove_cv_t<T>; |
| 793 | if constexpr (cpp::is_same_v<UnqualT, float> && __FLT_MANT_DIG__ == 24) | |
| 792 | if constexpr (cpp::is_same_v<UnqualT, float> && FLT_MANT_DIG == 24) | |
| 794 | 793 | return FPType::IEEE754_Binary32; |
| 795 | else if constexpr (cpp::is_same_v<UnqualT, double> && __DBL_MANT_DIG__ == 53) | |
| 794 | else if constexpr (cpp::is_same_v<UnqualT, double> && DBL_MANT_DIG == 53) | |
| 796 | 795 | return FPType::IEEE754_Binary64; |
| 797 | 796 | else if constexpr (cpp::is_same_v<UnqualT, long double>) { |
| 798 | if constexpr (__LDBL_MANT_DIG__ == 53) | |
| 797 | if constexpr (LDBL_MANT_DIG == 53) | |
| 799 | 798 | return FPType::IEEE754_Binary64; |
| 800 | else if constexpr (__LDBL_MANT_DIG__ == 64) | |
| 799 | else if constexpr (LDBL_MANT_DIG == 64) | |
| 801 | 800 | return FPType::X86_Binary80; |
| 802 | else if constexpr (__LDBL_MANT_DIG__ == 113) | |
| 801 | else if constexpr (LDBL_MANT_DIG == 113) | |
| 803 | 802 | return FPType::IEEE754_Binary128; |
| 804 | 803 | } |
| 805 | 804 | #if defined(LIBC_TYPES_HAS_FLOAT16) |
lib/libcxx/libc/src/__support/FPUtil/rounding_mode.h+50-4| ... | ... | @@ -10,18 +10,21 @@ |
| 10 | 10 | #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_ROUNDING_MODE_H |
| 11 | 11 | |
| 12 | 12 | #include "hdr/fenv_macros.h" |
| 13 | #include "src/__support/CPP/type_traits.h" // is_constant_evaluated | |
| 13 | 14 | #include "src/__support/macros/attributes.h" // LIBC_INLINE |
| 14 | 15 | #include "src/__support/macros/config.h" |
| 15 | 16 | |
| 16 | 17 | namespace LIBC_NAMESPACE_DECL { |
| 17 | 18 | namespace fputil { |
| 18 | 19 | |
| 20 | namespace generic { | |
| 21 | ||
| 19 | 22 | // Quick free-standing test whether fegetround() == FE_UPWARD. |
| 20 | 23 | // Using the following observation: |
| 21 | 24 | // 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO |
| 22 | 25 | // = 0x1.000002f for FE_UPWARD. |
| 23 | 26 | LIBC_INLINE bool fenv_is_round_up() { |
| 24 | volatile float x = 0x1.0p-25f; | |
| 27 | static volatile float x = 0x1.0p-25f; | |
| 25 | 28 | return (1.0f + x != 1.0f); |
| 26 | 29 | } |
| 27 | 30 | |
| ... | ... | @@ -30,7 +33,7 @@ LIBC_INLINE bool fenv_is_round_up() { |
| 30 | 33 | // -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO |
| 31 | 34 | // = -0x1.000002f for FE_DOWNWARD. |
| 32 | 35 | LIBC_INLINE bool fenv_is_round_down() { |
| 33 | volatile float x = 0x1.0p-25f; | |
| 36 | static volatile float x = 0x1.0p-25f; | |
| 34 | 37 | return (-1.0f - x != -1.0f); |
| 35 | 38 | } |
| 36 | 39 | |
| ... | ... | @@ -42,8 +45,8 @@ LIBC_INLINE bool fenv_is_round_down() { |
| 42 | 45 | // = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO |
| 43 | 46 | LIBC_INLINE bool fenv_is_round_to_nearest() { |
| 44 | 47 | static volatile float x = 0x1.0p-24f; |
| 45 | float y = x; | |
| 46 | return (1.5f + y == 1.5f - y); | |
| 48 | float y = 1.5f + x; | |
| 49 | return (y == 1.5f - x); | |
| 47 | 50 | } |
| 48 | 51 | |
| 49 | 52 | // Quick free-standing test whether fegetround() == FE_TOWARDZERO. |
| ... | ... | @@ -75,6 +78,49 @@ LIBC_INLINE int quick_get_round() { |
| 75 | 78 | return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD; |
| 76 | 79 | } |
| 77 | 80 | |
| 81 | } // namespace generic | |
| 82 | ||
| 83 | LIBC_INLINE static constexpr bool fenv_is_round_up() { | |
| 84 | if (cpp::is_constant_evaluated()) { | |
| 85 | return false; | |
| 86 | } else { | |
| 87 | return generic::fenv_is_round_up(); | |
| 88 | } | |
| 89 | } | |
| 90 | ||
| 91 | LIBC_INLINE static constexpr bool fenv_is_round_down() { | |
| 92 | if (cpp::is_constant_evaluated()) { | |
| 93 | return false; | |
| 94 | } else { | |
| 95 | return generic::fenv_is_round_down(); | |
| 96 | } | |
| 97 | } | |
| 98 | ||
| 99 | LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() { | |
| 100 | if (cpp::is_constant_evaluated()) { | |
| 101 | return true; | |
| 102 | } else { | |
| 103 | return generic::fenv_is_round_to_nearest(); | |
| 104 | } | |
| 105 | } | |
| 106 | ||
| 107 | LIBC_INLINE static constexpr bool fenv_is_round_to_zero() { | |
| 108 | if (cpp::is_constant_evaluated()) { | |
| 109 | return false; | |
| 110 | } else { | |
| 111 | return generic::fenv_is_round_to_zero(); | |
| 112 | } | |
| 113 | } | |
| 114 | ||
| 115 | // Quick free standing get rounding mode based on the above observations. | |
| 116 | LIBC_INLINE static constexpr int quick_get_round() { | |
| 117 | if (cpp::is_constant_evaluated()) { | |
| 118 | return FE_TONEAREST; | |
| 119 | } else { | |
| 120 | return generic::quick_get_round(); | |
| 121 | } | |
| 122 | } | |
| 123 | ||
| 78 | 124 | } // namespace fputil |
| 79 | 125 | } // namespace LIBC_NAMESPACE_DECL |
| 80 | 126 |
lib/libcxx/libc/src/__support/big_int.h+14-14| ... | ... | @@ -9,6 +9,7 @@ |
| 9 | 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_BIG_INT_H |
| 10 | 10 | #define LLVM_LIBC_SRC___SUPPORT_BIG_INT_H |
| 11 | 11 | |
| 12 | #include "hdr/stdint_proxy.h" | |
| 12 | 13 | #include "src/__support/CPP/array.h" |
| 13 | 14 | #include "src/__support/CPP/bit.h" // countl_zero |
| 14 | 15 | #include "src/__support/CPP/limits.h" |
| ... | ... | @@ -23,7 +24,6 @@ |
| 23 | 24 | #include "src/__support/number_pair.h" |
| 24 | 25 | |
| 25 | 26 | #include <stddef.h> // For size_t |
| 26 | #include <stdint.h> | |
| 27 | 27 | |
| 28 | 28 | namespace LIBC_NAMESPACE_DECL { |
| 29 | 29 | |
| ... | ... | @@ -95,10 +95,10 @@ LIBC_INLINE constexpr DoubleWide<word> mul2(word a, word b) { |
| 95 | 95 | #endif |
| 96 | 96 | else { |
| 97 | 97 | using half_word = half_width_t<word>; |
| 98 | const auto shiftl = [](word value) -> word { | |
| 98 | constexpr auto shiftl = [](word value) -> word { | |
| 99 | 99 | return value << cpp::numeric_limits<half_word>::digits; |
| 100 | 100 | }; |
| 101 | const auto shiftr = [](word value) -> word { | |
| 101 | constexpr auto shiftr = [](word value) -> word { | |
| 102 | 102 | return value >> cpp::numeric_limits<half_word>::digits; |
| 103 | 103 | }; |
| 104 | 104 | // Here we do a one digit multiplication where 'a' and 'b' are of type |
| ... | ... | @@ -111,19 +111,19 @@ LIBC_INLINE constexpr DoubleWide<word> mul2(word a, word b) { |
| 111 | 111 | // c result |
| 112 | 112 | // We convert 'lo' and 'hi' from 'half_word' to 'word' so multiplication |
| 113 | 113 | // doesn't overflow. |
| 114 | const word a_lo = lo(a); | |
| 115 | const word b_lo = lo(b); | |
| 116 | const word a_hi = hi(a); | |
| 117 | const word b_hi = hi(b); | |
| 118 | const word step1 = b_lo * a_lo; // no overflow; | |
| 119 | const word step2 = b_lo * a_hi; // no overflow; | |
| 120 | const word step3 = b_hi * a_lo; // no overflow; | |
| 121 | const word step4 = b_hi * a_hi; // no overflow; | |
| 114 | word a_lo = lo(a); | |
| 115 | word b_lo = lo(b); | |
| 116 | word a_hi = hi(a); | |
| 117 | word b_hi = hi(b); | |
| 118 | word step1 = b_lo * a_lo; // no overflow; | |
| 119 | word step2 = b_lo * a_hi; // no overflow; | |
| 120 | word step3 = b_hi * a_lo; // no overflow; | |
| 121 | word step4 = b_hi * a_hi; // no overflow; | |
| 122 | 122 | word lo_digit = step1; |
| 123 | 123 | word hi_digit = step4; |
| 124 | const word no_carry = 0; | |
| 125 | word carry; | |
| 126 | word _; // unused carry variable. | |
| 124 | word no_carry = 0; | |
| 125 | word carry = 0; | |
| 126 | [[maybe_unused]] word _ = 0; // unused carry variable. | |
| 127 | 127 | lo_digit = add_with_carry<word>(lo_digit, shiftl(step2), no_carry, carry); |
| 128 | 128 | hi_digit = add_with_carry<word>(hi_digit, shiftr(step2), carry, _); |
| 129 | 129 | lo_digit = add_with_carry<word>(lo_digit, shiftl(step3), no_carry, carry); |
lib/libcxx/libc/src/__support/common.h+3-2| ... | ... | @@ -16,6 +16,7 @@ |
| 16 | 16 | #include "src/__support/macros/attributes.h" |
| 17 | 17 | #include "src/__support/macros/config.h" |
| 18 | 18 | #include "src/__support/macros/properties/architectures.h" |
| 19 | #include "src/__support/macros/properties/compiler.h" | |
| 19 | 20 | |
| 20 | 21 | #ifndef LLVM_LIBC_FUNCTION_ATTR |
| 21 | 22 | #define LLVM_LIBC_FUNCTION_ATTR |
| ... | ... | @@ -41,12 +42,12 @@ |
| 41 | 42 | // to cleanly export and alias the C++ symbol `LIBC_NAMESPACE::func` with the C |
| 42 | 43 | // symbol `func`. So for public packaging on MacOS, we will only export the C |
| 43 | 44 | // symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`. |
| 44 | #if defined(LIBC_COPT_PUBLIC_PACKAGING) | |
| 45 | #if defined(LIBC_COPT_PUBLIC_PACKAGING) && !defined(LIBC_COMPILER_IS_MSVC) | |
| 45 | 46 | #ifndef __APPLE__ |
| 46 | 47 | #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \ |
| 47 | 48 | LLVM_LIBC_ATTR(name) \ |
| 48 | 49 | LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \ |
| 49 | __##name##_impl__ __asm__(#name); \ | |
| 50 | __##name##_impl__ asm(#name); \ | |
| 50 | 51 | decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \ |
| 51 | 52 | type __##name##_impl__ arglist |
| 52 | 53 | #else // __APPLE__ |
lib/libcxx/libc/src/__support/ctype_utils.h+19-12| ... | ... | @@ -27,7 +27,7 @@ namespace internal { |
| 27 | 27 | // as well as a way to support non-ASCII character encodings. |
| 28 | 28 | |
| 29 | 29 | // Similarly, do not change these functions to use case ranges. e.g. |
| 30 | // bool islower(int ch) { | |
| 30 | // bool islower(char ch) { | |
| 31 | 31 | // switch(ch) { |
| 32 | 32 | // case 'a'...'z': |
| 33 | 33 | // return true; |
| ... | ... | @@ -37,7 +37,7 @@ namespace internal { |
| 37 | 37 | // EBCDIC. Technically we could use some smaller ranges, but that's even harder |
| 38 | 38 | // to read. |
| 39 | 39 | |
| 40 | LIBC_INLINE static constexpr bool islower(int ch) { | |
| 40 | LIBC_INLINE static constexpr bool islower(char ch) { | |
| 41 | 41 | switch (ch) { |
| 42 | 42 | case 'a': |
| 43 | 43 | case 'b': |
| ... | ... | @@ -71,7 +71,7 @@ LIBC_INLINE static constexpr bool islower(int ch) { |
| 71 | 71 | } |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | LIBC_INLINE static constexpr bool isupper(int ch) { | |
| 74 | LIBC_INLINE static constexpr bool isupper(char ch) { | |
| 75 | 75 | switch (ch) { |
| 76 | 76 | case 'A': |
| 77 | 77 | case 'B': |
| ... | ... | @@ -105,7 +105,7 @@ LIBC_INLINE static constexpr bool isupper(int ch) { |
| 105 | 105 | } |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | LIBC_INLINE static constexpr bool isdigit(int ch) { | |
| 108 | LIBC_INLINE static constexpr bool isdigit(char ch) { | |
| 109 | 109 | switch (ch) { |
| 110 | 110 | case '0': |
| 111 | 111 | case '1': |
| ... | ... | @@ -123,7 +123,7 @@ LIBC_INLINE static constexpr bool isdigit(int ch) { |
| 123 | 123 | } |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | LIBC_INLINE static constexpr int tolower(int ch) { | |
| 126 | LIBC_INLINE static constexpr char tolower(char ch) { | |
| 127 | 127 | switch (ch) { |
| 128 | 128 | case 'A': |
| 129 | 129 | return 'a'; |
| ... | ... | @@ -182,7 +182,7 @@ LIBC_INLINE static constexpr int tolower(int ch) { |
| 182 | 182 | } |
| 183 | 183 | } |
| 184 | 184 | |
| 185 | LIBC_INLINE static constexpr int toupper(int ch) { | |
| 185 | LIBC_INLINE static constexpr char toupper(char ch) { | |
| 186 | 186 | switch (ch) { |
| 187 | 187 | case 'a': |
| 188 | 188 | return 'A'; |
| ... | ... | @@ -241,7 +241,7 @@ LIBC_INLINE static constexpr int toupper(int ch) { |
| 241 | 241 | } |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | LIBC_INLINE static constexpr bool isalpha(int ch) { | |
| 244 | LIBC_INLINE static constexpr bool isalpha(char ch) { | |
| 245 | 245 | switch (ch) { |
| 246 | 246 | case 'a': |
| 247 | 247 | case 'b': |
| ... | ... | @@ -301,7 +301,7 @@ LIBC_INLINE static constexpr bool isalpha(int ch) { |
| 301 | 301 | } |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | LIBC_INLINE static constexpr bool isalnum(int ch) { | |
| 304 | LIBC_INLINE static constexpr bool isalnum(char ch) { | |
| 305 | 305 | switch (ch) { |
| 306 | 306 | case 'a': |
| 307 | 307 | case 'b': |
| ... | ... | @@ -371,7 +371,7 @@ LIBC_INLINE static constexpr bool isalnum(int ch) { |
| 371 | 371 | } |
| 372 | 372 | } |
| 373 | 373 | |
| 374 | LIBC_INLINE static constexpr int b36_char_to_int(int ch) { | |
| 374 | LIBC_INLINE static constexpr int b36_char_to_int(char ch) { | |
| 375 | 375 | switch (ch) { |
| 376 | 376 | case '0': |
| 377 | 377 | return 0; |
| ... | ... | @@ -476,7 +476,7 @@ LIBC_INLINE static constexpr int b36_char_to_int(int ch) { |
| 476 | 476 | } |
| 477 | 477 | } |
| 478 | 478 | |
| 479 | LIBC_INLINE static constexpr int int_to_b36_char(int num) { | |
| 479 | LIBC_INLINE static constexpr char int_to_b36_char(int num) { | |
| 480 | 480 | // Can't actually use LIBC_ASSERT here because it depends on integer_to_string |
| 481 | 481 | // which depends on this. |
| 482 | 482 | |
| ... | ... | @@ -559,7 +559,7 @@ LIBC_INLINE static constexpr int int_to_b36_char(int num) { |
| 559 | 559 | } |
| 560 | 560 | } |
| 561 | 561 | |
| 562 | LIBC_INLINE static constexpr bool isspace(int ch) { | |
| 562 | LIBC_INLINE static constexpr bool isspace(char ch) { | |
| 563 | 563 | switch (ch) { |
| 564 | 564 | case ' ': |
| 565 | 565 | case '\t': |
| ... | ... | @@ -574,10 +574,17 @@ LIBC_INLINE static constexpr bool isspace(int ch) { |
| 574 | 574 | } |
| 575 | 575 | |
| 576 | 576 | // not yet encoding independent. |
| 577 | LIBC_INLINE static constexpr bool isgraph(int ch) { | |
| 577 | LIBC_INLINE static constexpr bool isgraph(char ch) { | |
| 578 | 578 | return 0x20 < ch && ch < 0x7f; |
| 579 | 579 | } |
| 580 | 580 | |
| 581 | // 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. | |
| 583 | LIBC_INLINE static constexpr bool is_char_or_wchar(char ch, char c_value, | |
| 584 | [[maybe_unused]] wchar_t) { | |
| 585 | return (ch == c_value); | |
| 586 | } | |
| 587 | ||
| 581 | 588 | } // namespace internal |
| 582 | 589 | } // namespace LIBC_NAMESPACE_DECL |
| 583 | 590 |
lib/libcxx/libc/src/__support/detailed_powers_of_ten.h+1-2| ... | ... | @@ -9,11 +9,10 @@ |
| 9 | 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H |
| 10 | 10 | #define LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H |
| 11 | 11 | |
| 12 | #include "hdr/stdint_proxy.h" | |
| 12 | 13 | #include "src/__support/common.h" |
| 13 | 14 | #include "src/__support/macros/config.h" |
| 14 | 15 | |
| 15 | #include <stdint.h> | |
| 16 | ||
| 17 | 16 | namespace LIBC_NAMESPACE_DECL { |
| 18 | 17 | namespace internal { |
| 19 | 18 |
lib/libcxx/libc/src/__support/high_precision_decimal.h+33-14| ... | ... | @@ -15,11 +15,12 @@ |
| 15 | 15 | #ifndef LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H |
| 16 | 16 | #define LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H |
| 17 | 17 | |
| 18 | #include "hdr/stdint_proxy.h" | |
| 18 | 19 | #include "src/__support/CPP/limits.h" |
| 19 | 20 | #include "src/__support/ctype_utils.h" |
| 20 | 21 | #include "src/__support/macros/config.h" |
| 21 | 22 | #include "src/__support/str_to_integer.h" |
| 22 | #include <stdint.h> | |
| 23 | #include "src/__support/wctype_utils.h" | |
| 23 | 24 | |
| 24 | 25 | namespace LIBC_NAMESPACE_DECL { |
| 25 | 26 | namespace internal { |
| ... | ... | @@ -38,6 +39,24 @@ struct LShiftTableEntry { |
| 38 | 39 | // TODO: Figure out where to put this. |
| 39 | 40 | enum class RoundDirection { Up, Down, Nearest }; |
| 40 | 41 | |
| 42 | // These constants are used in both this file and in the main str_to_float.h. | |
| 43 | // TODO: Figure out where to put this. | |
| 44 | template <typename CharType> struct constants; | |
| 45 | template <> struct constants<char> { | |
| 46 | static constexpr char DECIMAL_POINT = '.'; | |
| 47 | static constexpr char DECIMAL_EXPONENT_MARKER = 'e'; | |
| 48 | static constexpr char HEX_EXPONENT_MARKER = 'p'; | |
| 49 | static constexpr char INF_STRING[] = "infinity"; | |
| 50 | static constexpr char NAN_STRING[] = "nan"; | |
| 51 | }; | |
| 52 | template <> struct constants<wchar_t> { | |
| 53 | static constexpr wchar_t DECIMAL_POINT = L'.'; | |
| 54 | static constexpr wchar_t DECIMAL_EXPONENT_MARKER = L'e'; | |
| 55 | static constexpr wchar_t HEX_EXPONENT_MARKER = L'p'; | |
| 56 | static constexpr wchar_t INF_STRING[] = L"infinity"; | |
| 57 | static constexpr wchar_t NAN_STRING[] = L"nan"; | |
| 58 | }; | |
| 59 | ||
| 41 | 60 | // This is based on the HPD data structure described as part of the Simple |
| 42 | 61 | // Decimal Conversion algorithm by Nigel Tao, described at this link: |
| 43 | 62 | // https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html |
| ... | ... | @@ -314,9 +333,9 @@ private: |
| 314 | 333 | public: |
| 315 | 334 | // num_string is assumed to be a string of numeric characters. It doesn't |
| 316 | 335 | // handle leading spaces. |
| 317 | LIBC_INLINE | |
| 318 | HighPrecisionDecimal( | |
| 319 | const char *__restrict num_string, | |
| 336 | template <typename CharType> | |
| 337 | LIBC_INLINE HighPrecisionDecimal( | |
| 338 | const CharType *__restrict num_string, | |
| 320 | 339 | const size_t num_len = cpp::numeric_limits<size_t>::max()) { |
| 321 | 340 | bool saw_dot = false; |
| 322 | 341 | size_t num_cur = 0; |
| ... | ... | @@ -324,25 +343,26 @@ public: |
| 324 | 343 | // them all. |
| 325 | 344 | uint32_t total_digits = 0; |
| 326 | 345 | while (num_cur < num_len && |
| 327 | (isdigit(num_string[num_cur]) || num_string[num_cur] == '.')) { | |
| 328 | if (num_string[num_cur] == '.') { | |
| 346 | (isdigit(num_string[num_cur]) || | |
| 347 | num_string[num_cur] == constants<CharType>::DECIMAL_POINT)) { | |
| 348 | if (num_string[num_cur] == constants<CharType>::DECIMAL_POINT) { | |
| 329 | 349 | if (saw_dot) { |
| 330 | 350 | break; |
| 331 | 351 | } |
| 332 | 352 | this->decimal_point = static_cast<int32_t>(total_digits); |
| 333 | 353 | saw_dot = true; |
| 334 | 354 | } else { |
| 335 | if (num_string[num_cur] == '0' && this->num_digits == 0) { | |
| 355 | int digit = b36_char_to_int(num_string[num_cur]); | |
| 356 | if (digit == 0 && this->num_digits == 0) { | |
| 336 | 357 | --this->decimal_point; |
| 337 | 358 | ++num_cur; |
| 338 | 359 | continue; |
| 339 | 360 | } |
| 340 | 361 | ++total_digits; |
| 341 | 362 | if (this->num_digits < MAX_NUM_DIGITS) { |
| 342 | this->digits[this->num_digits] = static_cast<uint8_t>( | |
| 343 | internal::b36_char_to_int(num_string[num_cur])); | |
| 363 | this->digits[this->num_digits] = static_cast<uint8_t>(digit); | |
| 344 | 364 | ++this->num_digits; |
| 345 | } else if (num_string[num_cur] != '0') { | |
| 365 | } else if (digit != 0) { | |
| 346 | 366 | this->truncated = true; |
| 347 | 367 | } |
| 348 | 368 | } |
| ... | ... | @@ -352,11 +372,10 @@ public: |
| 352 | 372 | if (!saw_dot) |
| 353 | 373 | this->decimal_point = static_cast<int32_t>(total_digits); |
| 354 | 374 | |
| 355 | if (num_cur < num_len && | |
| 356 | (num_string[num_cur] == 'e' || num_string[num_cur] == 'E')) { | |
| 375 | if (num_cur < num_len && tolower(num_string[num_cur]) == | |
| 376 | constants<CharType>::DECIMAL_EXPONENT_MARKER) { | |
| 357 | 377 | ++num_cur; |
| 358 | if (isdigit(num_string[num_cur]) || num_string[num_cur] == '+' || | |
| 359 | num_string[num_cur] == '-') { | |
| 378 | if (isdigit(num_string[num_cur]) || get_sign(num_string + num_cur) != 0) { | |
| 360 | 379 | auto result = |
| 361 | 380 | strtointeger<int32_t>(num_string + num_cur, 10, num_len - num_cur); |
| 362 | 381 | if (result.has_error()) { |
lib/libcxx/libc/src/__support/libc_assert.h+2| ... | ... | @@ -14,9 +14,11 @@ |
| 14 | 14 | // The build is configured to just use the public <assert.h> API |
| 15 | 15 | // for libc's internal assertions. |
| 16 | 16 | |
| 17 | #ifndef LIBC_ASSERT | |
| 17 | 18 | #include <assert.h> |
| 18 | 19 | |
| 19 | 20 | #define LIBC_ASSERT(COND) assert(COND) |
| 21 | #endif // LIBC_ASSERT | |
| 20 | 22 | |
| 21 | 23 | #else // Not LIBC_COPT_USE_C_ASSERT |
| 22 | 24 |
lib/libcxx/libc/src/__support/macros/attributes.h+44-1| ... | ... | @@ -17,6 +17,7 @@ |
| 17 | 17 | #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H |
| 18 | 18 | #define LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H |
| 19 | 19 | |
| 20 | #include "config.h" | |
| 20 | 21 | #include "properties/architectures.h" |
| 21 | 22 | |
| 22 | 23 | #ifndef __has_attribute |
| ... | ... | @@ -28,7 +29,32 @@ |
| 28 | 29 | #define LIBC_INLINE_ASM __asm__ __volatile__ |
| 29 | 30 | #define LIBC_UNUSED __attribute__((unused)) |
| 30 | 31 | |
| 31 | #ifdef LIBC_TARGET_ARCH_IS_GPU | |
| 32 | // Uses the platform specific specialization | |
| 33 | #define LIBC_THREAD_MODE_PLATFORM 0 | |
| 34 | ||
| 35 | // Mutex guards nothing, used in single-threaded implementations | |
| 36 | #define LIBC_THREAD_MODE_SINGLE 1 | |
| 37 | ||
| 38 | // Vendor provides implementation | |
| 39 | #define LIBC_THREAD_MODE_EXTERNAL 2 | |
| 40 | ||
| 41 | // libcxx doesn't define LIBC_THREAD_MODE, unless that is passed in the command | |
| 42 | // line in the CMake invocation. This defaults to the original implementation | |
| 43 | // (before changes in https://github.com/llvm/llvm-project/pull/145358) | |
| 44 | #ifndef LIBC_THREAD_MODE | |
| 45 | #define LIBC_THREAD_MODE LIBC_THREAD_MODE_PLATFORM | |
| 46 | #endif // LIBC_THREAD_MODE | |
| 47 | ||
| 48 | #if LIBC_THREAD_MODE != LIBC_THREAD_MODE_PLATFORM && \ | |
| 49 | LIBC_THREAD_MODE != LIBC_THREAD_MODE_SINGLE && \ | |
| 50 | LIBC_THREAD_MODE != LIBC_THREAD_MODE_EXTERNAL | |
| 51 | #error LIBC_THREAD_MODE must be one of the following values: \ | |
| 52 | LIBC_THREAD_MODE_PLATFORM, \ | |
| 53 | LIBC_THREAD_MODE_SINGLE, \ | |
| 54 | LIBC_THREAD_MODE_EXTERNAL. | |
| 55 | #endif | |
| 56 | ||
| 57 | #if LIBC_THREAD_MODE == LIBC_THREAD_MODE_SINGLE | |
| 32 | 58 | #define LIBC_THREAD_LOCAL |
| 33 | 59 | #else |
| 34 | 60 | #define LIBC_THREAD_LOCAL thread_local |
| ... | ... | @@ -48,4 +74,21 @@ |
| 48 | 74 | #define LIBC_PREFERED_TYPE(TYPE) |
| 49 | 75 | #endif |
| 50 | 76 | |
| 77 | #if __has_attribute(ext_vector_type) && \ | |
| 78 | LIBC_HAS_FEATURE(ext_vector_type_boolean) | |
| 79 | #define LIBC_HAS_VECTOR_TYPE 1 | |
| 80 | #else | |
| 81 | #define LIBC_HAS_VECTOR_TYPE 0 | |
| 82 | #endif | |
| 83 | ||
| 84 | #if __has_attribute(no_sanitize) | |
| 85 | // Disable regular and hardware-supported ASan for functions that may | |
| 86 | // intentionally make out-of-bounds access. Disable TSan as well, as it detects | |
| 87 | // out-of-bounds accesses to heap memory. | |
| 88 | #define LIBC_NO_SANITIZE_OOB_ACCESS \ | |
| 89 | __attribute__((no_sanitize("address", "hwaddress", "thread"))) | |
| 90 | #else | |
| 91 | #define LIBC_NO_SANITIZE_OOB_ACCESS | |
| 92 | #endif | |
| 93 | ||
| 51 | 94 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H |
lib/libcxx/libc/src/__support/macros/config.h+23| ... | ... | @@ -13,6 +13,13 @@ |
| 13 | 13 | #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H |
| 14 | 14 | #define LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H |
| 15 | 15 | |
| 16 | #include "src/__support/macros/properties/architectures.h" | |
| 17 | #include "src/__support/macros/properties/compiler.h" | |
| 18 | ||
| 19 | #ifdef LIBC_COMPILER_IS_MSVC | |
| 20 | #include <intrin.h> | |
| 21 | #endif // LIBC_COMPILER_IS_MSVC | |
| 22 | ||
| 16 | 23 | // Workaround for compilers that do not support builtin detection. |
| 17 | 24 | // FIXME: This is only required for the GPU portion which should be moved. |
| 18 | 25 | #ifndef __has_builtin |
| ... | ... | @@ -27,6 +34,22 @@ |
| 27 | 34 | #define LIBC_HAS_FEATURE(f) 0 |
| 28 | 35 | #endif |
| 29 | 36 | |
| 37 | #ifdef LIBC_COMPILER_IS_MSVC | |
| 38 | ||
| 39 | // __builtin_trap replacement | |
| 40 | #ifdef LIBC_TARGET_ARCH_IS_X86 | |
| 41 | #define __builtin_trap __ud2 | |
| 42 | #else // arm64 | |
| 43 | #define __builtin_trap() __break(1) | |
| 44 | #endif | |
| 45 | ||
| 46 | #define __builtin_expect(value, expectation) (value) | |
| 47 | #define __builtin_unreachable() __assume(0) | |
| 48 | ||
| 49 | #define __builtin_prefetch(X, Y, Z) | |
| 50 | ||
| 51 | #endif // LIBC_COMPILER_IS_MSVC | |
| 52 | ||
| 30 | 53 | #ifdef __clang__ |
| 31 | 54 | // Declare a LIBC_NAMESPACE with hidden visibility. `namespace |
| 32 | 55 | // LIBC_NAMESPACE_DECL {` should be used around all declarations and definitions |
lib/libcxx/libc/src/__support/macros/null_check.h+1-2| ... | ... | @@ -11,9 +11,8 @@ |
| 11 | 11 | |
| 12 | 12 | #include "src/__support/macros/config.h" |
| 13 | 13 | #include "src/__support/macros/optimization.h" |
| 14 | #include "src/__support/macros/sanitizer.h" | |
| 15 | 14 | |
| 16 | #if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER) | |
| 15 | #if defined(LIBC_ADD_NULL_CHECKS) | |
| 17 | 16 | #define LIBC_CRASH_ON_NULLPTR(ptr) \ |
| 18 | 17 | do { \ |
| 19 | 18 | if (LIBC_UNLIKELY((ptr) == nullptr)) \ |
lib/libcxx/libc/src/__support/macros/optimization.h+3| ... | ... | @@ -34,6 +34,9 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) { |
| 34 | 34 | #elif defined(LIBC_COMPILER_IS_GCC) |
| 35 | 35 | #define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0") |
| 36 | 36 | #define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048") |
| 37 | #elif defined(LIBC_COMPILER_IS_MSVC) | |
| 38 | #define LIBC_LOOP_NOUNROLL | |
| 39 | #define LIBC_LOOP_UNROLL | |
| 37 | 40 | #else |
| 38 | 41 | #error "Unhandled compiler" |
| 39 | 42 | #endif |
lib/libcxx/libc/src/__support/macros/properties/architectures.h+5-1| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | #define LIBC_TARGET_ARCH_IS_GPU |
| 22 | 22 | #endif |
| 23 | 23 | |
| 24 | #if defined(__pnacl__) || defined(__CLR_VER) || defined(LIBC_TARGET_ARCH_IS_GPU) | |
| 24 | #if defined(__CLR_VER) || defined(LIBC_TARGET_ARCH_IS_GPU) | |
| 25 | 25 | #define LIBC_TARGET_ARCH_IS_VM |
| 26 | 26 | #endif |
| 27 | 27 | |
| ... | ... | @@ -41,6 +41,10 @@ |
| 41 | 41 | #define LIBC_TARGET_ARCH_IS_ARM |
| 42 | 42 | #endif |
| 43 | 43 | |
| 44 | #if defined(__wasm__) | |
| 45 | #define LIBC_TARGET_ARCH_IS_WASM | |
| 46 | #endif | |
| 47 | ||
| 44 | 48 | #if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) |
| 45 | 49 | #define LIBC_TARGET_ARCH_IS_AARCH64 |
| 46 | 50 | #endif |
lib/libcxx/libc/src/__support/macros/properties/compiler.h+8-3| ... | ... | @@ -34,10 +34,15 @@ |
| 34 | 34 | #define LIBC_COMPILER_GCC_VER (__GNUC__ * 100 + __GNUC_MINOR__) |
| 35 | 35 | #endif |
| 36 | 36 | |
| 37 | #if defined(_MSC_VER) | |
| 38 | #define LIBC_COMPILER_IS_MSC | |
| 37 | #if defined(_MSC_VER) && !defined(__clang__) | |
| 38 | #define LIBC_COMPILER_IS_MSVC | |
| 39 | 39 | // https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros |
| 40 | #define LIBC_COMPILER_MSC_VER (_MSC_VER) | |
| 40 | #define LIBC_COMPILER_MSVC_VER (_MSC_VER) | |
| 41 | #ifdef _M_X64 | |
| 42 | #define LIBC_COMPILER_IS_MSVC_X64 | |
| 43 | #else | |
| 44 | #define LIBC_COMPILER_IS_MSVC_X86 | |
| 45 | #endif | |
| 41 | 46 | #endif |
| 42 | 47 | |
| 43 | 48 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_COMPILER_H |
lib/libcxx/libc/src/__support/macros/properties/cpu_features.h+17-1| ... | ... | @@ -18,6 +18,18 @@ |
| 18 | 18 | #define LIBC_TARGET_CPU_HAS_FULLFP16 |
| 19 | 19 | #endif |
| 20 | 20 | |
| 21 | #if defined(__ARM_FEATURE_SVE) | |
| 22 | #define LIBC_TARGET_CPU_HAS_SVE | |
| 23 | #endif | |
| 24 | ||
| 25 | #if defined(__ARM_FEATURE_SVE2) | |
| 26 | #define LIBC_TARGET_CPU_HAS_SVE2 | |
| 27 | #endif | |
| 28 | ||
| 29 | #if defined(__ARM_FEATURE_MOPS) | |
| 30 | #define LIBC_TARGET_CPU_HAS_MOPS | |
| 31 | #endif | |
| 32 | ||
| 21 | 33 | #if defined(__SSE2__) |
| 22 | 34 | #define LIBC_TARGET_CPU_HAS_SSE2 |
| 23 | 35 | #define LIBC_TARGET_CPU_HAS_FPU_FLOAT |
| ... | ... | @@ -59,6 +71,10 @@ |
| 59 | 71 | #endif // LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE |
| 60 | 72 | #endif // __ARM_FP |
| 61 | 73 | |
| 74 | #if defined(__ARM_NEON) | |
| 75 | #define LIBC_TARGET_CPU_HAS_ARM_NEON | |
| 76 | #endif | |
| 77 | ||
| 62 | 78 | #if defined(__riscv_flen) |
| 63 | 79 | // https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc |
| 64 | 80 | #if defined(__riscv_zfhmin) |
| ... | ... | @@ -81,7 +97,7 @@ |
| 81 | 97 | #endif |
| 82 | 98 | |
| 83 | 99 | #if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \ |
| 84 | defined(__NVPTX__) || defined(__AMDGPU__) || defined(__LIBC_RISCV_USE_FMA) | |
| 100 | defined(__NVPTX__) || defined(__AMDGPU__) || defined(__riscv_flen) | |
| 85 | 101 | #define LIBC_TARGET_CPU_HAS_FMA |
| 86 | 102 | // Provide a more fine-grained control of FMA instruction for ARM targets. |
| 87 | 103 | #if defined(LIBC_TARGET_CPU_HAS_FPU_HALF) |
lib/libcxx/libc/src/__support/macros/properties/types.h+2-3| ... | ... | @@ -10,7 +10,8 @@ |
| 10 | 10 | #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H |
| 11 | 11 | #define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H |
| 12 | 12 | |
| 13 | #include "hdr/float_macros.h" // LDBL_MANT_DIG | |
| 13 | #include "hdr/float_macros.h" // LDBL_MANT_DIG | |
| 14 | #include "hdr/stdint_proxy.h" // UINT64_MAX, __SIZEOF_INT128__ | |
| 14 | 15 | #include "include/llvm-libc-macros/float16-macros.h" // LIBC_TYPES_HAS_FLOAT16 |
| 15 | 16 | #include "include/llvm-libc-types/float128.h" // float128 |
| 16 | 17 | #include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL |
| ... | ... | @@ -19,8 +20,6 @@ |
| 19 | 20 | #include "src/__support/macros/properties/cpu_features.h" |
| 20 | 21 | #include "src/__support/macros/properties/os.h" |
| 21 | 22 | |
| 22 | #include <stdint.h> // UINT64_MAX, __SIZEOF_INT128__ | |
| 23 | ||
| 24 | 23 | // 'long double' properties. |
| 25 | 24 | #if (LDBL_MANT_DIG == 53) |
| 26 | 25 | #define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64 |
lib/libcxx/libc/src/__support/macros/sanitizer.h-10| ... | ... | @@ -23,16 +23,6 @@ |
| 23 | 23 | #define LIBC_HAS_MEMORY_SANITIZER |
| 24 | 24 | #endif |
| 25 | 25 | |
| 26 | #if LIBC_HAS_FEATURE(undefined_behavior_sanitizer) | |
| 27 | #define LIBC_HAS_UNDEFINED_BEHAVIOR_SANITIZER | |
| 28 | #endif | |
| 29 | ||
| 30 | #if defined(LIBC_HAS_ADDRESS_SANITIZER) || \ | |
| 31 | defined(LIBC_HAS_MEMORY_SANITIZER) || \ | |
| 32 | defined(LIBC_HAS_UNDEFINED_BEHAVIOR_SANITIZER) | |
| 33 | #define LIBC_HAS_SANITIZER | |
| 34 | #endif | |
| 35 | ||
| 36 | 26 | #ifdef LIBC_HAS_MEMORY_SANITIZER |
| 37 | 27 | // Only perform MSAN unpoison in non-constexpr context. |
| 38 | 28 | #include <sanitizer/msan_interface.h> |
lib/libcxx/libc/src/__support/math_extras.h+20-4| ... | ... | @@ -25,7 +25,13 @@ LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> |
| 25 | 25 | mask_trailing_ones() { |
| 26 | 26 | constexpr unsigned T_BITS = CHAR_BIT * sizeof(T); |
| 27 | 27 | static_assert(count <= T_BITS && "Invalid bit index"); |
| 28 | return count == 0 ? 0 : (T(-1) >> (T_BITS - count)); | |
| 28 | // MSVC complains about out of range shifts. | |
| 29 | if constexpr (count == 0) | |
| 30 | return 0; | |
| 31 | else if constexpr (count >= T_BITS) | |
| 32 | return T(-1); | |
| 33 | else | |
| 34 | return T(-1) >> (T_BITS - count); | |
| 29 | 35 | } |
| 30 | 36 | |
| 31 | 37 | // Create a bitmask with the count left-most bits set to 1, and all other bits |
| ... | ... | @@ -55,18 +61,28 @@ mask_leading_zeros() { |
| 55 | 61 | // Returns whether 'a + b' overflows, the result is stored in 'res'. |
| 56 | 62 | template <typename T> |
| 57 | 63 | [[nodiscard]] LIBC_INLINE constexpr bool add_overflow(T a, T b, T &res) { |
| 64 | #if __has_builtin(__builtin_add_overflow) | |
| 58 | 65 | return __builtin_add_overflow(a, b, &res); |
| 66 | #else | |
| 67 | res = a + b; | |
| 68 | return (res < a) || (res < b); | |
| 69 | #endif // __builtin_add_overflow | |
| 59 | 70 | } |
| 60 | 71 | |
| 61 | 72 | // Returns whether 'a - b' overflows, the result is stored in 'res'. |
| 62 | 73 | template <typename T> |
| 63 | 74 | [[nodiscard]] LIBC_INLINE constexpr bool sub_overflow(T a, T b, T &res) { |
| 75 | #if __has_builtin(__builtin_sub_overflow) | |
| 64 | 76 | return __builtin_sub_overflow(a, b, &res); |
| 77 | #else | |
| 78 | res = a - b; | |
| 79 | return (res > a); | |
| 80 | #endif // __builtin_sub_overflow | |
| 65 | 81 | } |
| 66 | 82 | |
| 67 | 83 | #define RETURN_IF(TYPE, BUILTIN) \ |
| 68 | 84 | if constexpr (cpp::is_same_v<T, TYPE>) \ |
| 69 | return BUILTIN(a, b, carry_in, carry_out); | |
| 85 | return BUILTIN(a, b, carry_in, &carry_out); | |
| 70 | 86 | |
| 71 | 87 | // Returns the result of 'a + b' taking into account 'carry_in'. |
| 72 | 88 | // The carry out is stored in 'carry_out' it not 'nullptr', dropped otherwise. |
| ... | ... | @@ -74,7 +90,7 @@ template <typename T> |
| 74 | 90 | template <typename T> |
| 75 | 91 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> |
| 76 | 92 | add_with_carry(T a, T b, T carry_in, T &carry_out) { |
| 77 | if constexpr (!cpp::is_constant_evaluated()) { | |
| 93 | if (!cpp::is_constant_evaluated()) { | |
| 78 | 94 | #if __has_builtin(__builtin_addcb) |
| 79 | 95 | RETURN_IF(unsigned char, __builtin_addcb) |
| 80 | 96 | #elif __has_builtin(__builtin_addcs) |
| ... | ... | @@ -100,7 +116,7 @@ add_with_carry(T a, T b, T carry_in, T &carry_out) { |
| 100 | 116 | template <typename T> |
| 101 | 117 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> |
| 102 | 118 | sub_with_borrow(T a, T b, T carry_in, T &carry_out) { |
| 103 | if constexpr (!cpp::is_constant_evaluated()) { | |
| 119 | if (!cpp::is_constant_evaluated()) { | |
| 104 | 120 | #if __has_builtin(__builtin_subcb) |
| 105 | 121 | RETURN_IF(unsigned char, __builtin_subcb) |
| 106 | 122 | #elif __has_builtin(__builtin_subcs) |
lib/libcxx/libc/src/__support/str_to_float.h+98-125| ... | ... | @@ -16,6 +16,7 @@ |
| 16 | 16 | #define LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H |
| 17 | 17 | |
| 18 | 18 | #include "hdr/errno_macros.h" // For ERANGE |
| 19 | #include "hdr/stdint_proxy.h" | |
| 19 | 20 | #include "src/__support/CPP/bit.h" |
| 20 | 21 | #include "src/__support/CPP/limits.h" |
| 21 | 22 | #include "src/__support/CPP/optional.h" |
| ... | ... | @@ -32,8 +33,7 @@ |
| 32 | 33 | #include "src/__support/str_to_integer.h" |
| 33 | 34 | #include "src/__support/str_to_num_result.h" |
| 34 | 35 | #include "src/__support/uint128.h" |
| 35 | ||
| 36 | #include <stdint.h> | |
| 36 | #include "src/__support/wctype_utils.h" | |
| 37 | 37 | |
| 38 | 38 | namespace LIBC_NAMESPACE_DECL { |
| 39 | 39 | namespace internal { |
| ... | ... | @@ -335,9 +335,9 @@ constexpr int32_t NUM_POWERS_OF_TWO = |
| 335 | 335 | // the Eisel-Lemire algorithm fails, it's slower but more accurate. It's based |
| 336 | 336 | // on the Simple Decimal Conversion algorithm by Nigel Tao, described at this |
| 337 | 337 | // link: https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html |
| 338 | template <class T> | |
| 338 | template <typename T, typename CharType> | |
| 339 | 339 | LIBC_INLINE FloatConvertReturn<T> simple_decimal_conversion( |
| 340 | const char *__restrict numStart, | |
| 340 | const CharType *__restrict numStart, | |
| 341 | 341 | const size_t num_len = cpp::numeric_limits<size_t>::max(), |
| 342 | 342 | RoundDirection round = RoundDirection::Nearest) { |
| 343 | 343 | using FPBits = typename fputil::FPBits<T>; |
| ... | ... | @@ -677,12 +677,11 @@ template <> LIBC_INLINE constexpr int32_t get_lower_bound<double>() { |
| 677 | 677 | // Takes a mantissa and base 10 exponent and converts it into its closest |
| 678 | 678 | // floating point type T equivalient. First we try the Eisel-Lemire algorithm, |
| 679 | 679 | // then if that fails then we fall back to a more accurate algorithm for |
| 680 | // accuracy. The resulting mantissa and exponent are placed in outputMantissa | |
| 681 | // and outputExp2. | |
| 682 | template <class T> | |
| 680 | // accuracy. | |
| 681 | template <typename T, typename CharType> | |
| 683 | 682 | LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float( |
| 684 | 683 | ExpandedFloat<T> init_num, bool truncated, RoundDirection round, |
| 685 | const char *__restrict numStart, | |
| 684 | const CharType *__restrict numStart, | |
| 686 | 685 | const size_t num_len = cpp::numeric_limits<size_t>::max()) { |
| 687 | 686 | using FPBits = typename fputil::FPBits<T>; |
| 688 | 687 | using StorageType = typename FPBits::StorageType; |
| ... | ... | @@ -861,36 +860,42 @@ LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num, |
| 861 | 860 | return output; |
| 862 | 861 | } |
| 863 | 862 | |
| 864 | // checks if the next 4 characters of the string pointer are the start of a | |
| 863 | // Checks if the first characters of the string pointer are the start of a | |
| 865 | 864 | // hexadecimal floating point number. Does not advance the string pointer. |
| 866 | LIBC_INLINE bool is_float_hex_start(const char *__restrict src, | |
| 867 | const char decimalPoint) { | |
| 868 | if (!(src[0] == '0' && tolower(src[1]) == 'x')) { | |
| 865 | template <typename CharType> | |
| 866 | LIBC_INLINE static bool is_float_hex_start(const CharType *__restrict src) { | |
| 867 | if (!is_char_or_wchar(src[0], '0', L'0') || | |
| 868 | !is_char_or_wchar(tolower(src[1]), 'x', L'x')) { | |
| 869 | 869 | return false; |
| 870 | 870 | } |
| 871 | 871 | size_t first_digit = 2; |
| 872 | if (src[2] == decimalPoint) { | |
| 872 | if (src[2] == constants<CharType>::DECIMAL_POINT) { | |
| 873 | 873 | ++first_digit; |
| 874 | 874 | } |
| 875 | 875 | return isalnum(src[first_digit]) && b36_char_to_int(src[first_digit]) < 16; |
| 876 | 876 | } |
| 877 | 877 | |
| 878 | // Takes the start of a string representing a decimal float, as well as the | |
| 879 | // local decimalPoint. It returns if it suceeded in parsing any digits, and if | |
| 880 | // the return value is true then the outputs are pointer to the end of the | |
| 881 | // number, and the mantissa and exponent for the closest float T representation. | |
| 882 | // If the return value is false, then it is assumed that there is no number | |
| 883 | // here. | |
| 884 | template <class T> | |
| 885 | LIBC_INLINE StrToNumResult<ExpandedFloat<T>> | |
| 886 | decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, | |
| 887 | RoundDirection round) { | |
| 878 | // Verifies that first prefix_len characters of str, when lowercased, match the | |
| 879 | // specified prefix. | |
| 880 | template <typename CharType> | |
| 881 | LIBC_INLINE static bool tolower_starts_with(const CharType *str, | |
| 882 | size_t prefix_len, | |
| 883 | const CharType *prefix) { | |
| 884 | for (size_t i = 0; i < prefix_len; ++i) { | |
| 885 | if (tolower(str[i]) != prefix[i]) | |
| 886 | return false; | |
| 887 | } | |
| 888 | return true; | |
| 889 | } | |
| 890 | ||
| 891 | // Attempts parsing a decimal floating point number at the start of the string. | |
| 892 | template <typename T, typename CharType> | |
| 893 | LIBC_INLINE static StrToNumResult<ExpandedFloat<T>> | |
| 894 | decimal_string_to_float(const CharType *__restrict src, RoundDirection round) { | |
| 888 | 895 | using FPBits = typename fputil::FPBits<T>; |
| 889 | 896 | using StorageType = typename FPBits::StorageType; |
| 890 | 897 | |
| 891 | 898 | constexpr uint32_t BASE = 10; |
| 892 | constexpr char EXPONENT_MARKER = 'e'; | |
| 893 | ||
| 894 | 899 | bool truncated = false; |
| 895 | 900 | bool seen_digit = false; |
| 896 | 901 | bool after_decimal = false; |
| ... | ... | @@ -927,7 +932,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, |
| 927 | 932 | ++index; |
| 928 | 933 | continue; |
| 929 | 934 | } |
| 930 | if (src[index] == DECIMAL_POINT) { | |
| 935 | if (src[index] == constants<CharType>::DECIMAL_POINT) { | |
| 931 | 936 | if (after_decimal) { |
| 932 | 937 | break; // this means that src[index] points to a second decimal point, |
| 933 | 938 | // ending the number. |
| ... | ... | @@ -944,13 +949,10 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, |
| 944 | 949 | return output; |
| 945 | 950 | |
| 946 | 951 | // TODO: When adding max length argument, handle the case of a trailing |
| 947 | // EXPONENT MARKER, see scanf for more details. | |
| 948 | if (tolower(src[index]) == EXPONENT_MARKER) { | |
| 949 | bool has_sign = false; | |
| 950 | if (src[index + 1] == '+' || src[index + 1] == '-') { | |
| 951 | has_sign = true; | |
| 952 | } | |
| 953 | if (isdigit(src[index + 1 + static_cast<size_t>(has_sign)])) { | |
| 952 | // exponent marker, see scanf for more details. | |
| 953 | if (tolower(src[index]) == constants<CharType>::DECIMAL_EXPONENT_MARKER) { | |
| 954 | int sign = get_sign(src + index + 1); | |
| 955 | if (isdigit(src[index + 1 + static_cast<size_t>(sign != 0)])) { | |
| 954 | 956 | ++index; |
| 955 | 957 | auto result = strtointeger<int32_t>(src + index, 10); |
| 956 | 958 | if (result.has_error()) |
| ... | ... | @@ -986,22 +988,16 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, |
| 986 | 988 | return output; |
| 987 | 989 | } |
| 988 | 990 | |
| 989 | // Takes the start of a string representing a hexadecimal float, as well as the | |
| 990 | // local decimal point. It returns if it suceeded in parsing any digits, and if | |
| 991 | // the return value is true then the outputs are pointer to the end of the | |
| 992 | // number, and the mantissa and exponent for the closest float T representation. | |
| 993 | // If the return value is false, then it is assumed that there is no number | |
| 994 | // here. | |
| 995 | template <class T> | |
| 996 | LIBC_INLINE StrToNumResult<ExpandedFloat<T>> | |
| 997 | hexadecimal_string_to_float(const char *__restrict src, | |
| 998 | const char DECIMAL_POINT, RoundDirection round) { | |
| 991 | // Attempts parsing a hexadecimal floating point number at the start of the | |
| 992 | // string. | |
| 993 | template <typename T, typename CharType> | |
| 994 | LIBC_INLINE static StrToNumResult<ExpandedFloat<T>> | |
| 995 | hexadecimal_string_to_float(const CharType *__restrict src, | |
| 996 | RoundDirection round) { | |
| 999 | 997 | using FPBits = typename fputil::FPBits<T>; |
| 1000 | 998 | using StorageType = typename FPBits::StorageType; |
| 1001 | 999 | |
| 1002 | 1000 | constexpr uint32_t BASE = 16; |
| 1003 | constexpr char EXPONENT_MARKER = 'p'; | |
| 1004 | ||
| 1005 | 1001 | bool truncated = false; |
| 1006 | 1002 | bool seen_digit = false; |
| 1007 | 1003 | bool after_decimal = false; |
| ... | ... | @@ -1039,7 +1035,7 @@ hexadecimal_string_to_float(const char *__restrict src, |
| 1039 | 1035 | ++index; |
| 1040 | 1036 | continue; |
| 1041 | 1037 | } |
| 1042 | if (src[index] == DECIMAL_POINT) { | |
| 1038 | if (src[index] == constants<CharType>::DECIMAL_POINT) { | |
| 1043 | 1039 | if (after_decimal) { |
| 1044 | 1040 | break; // this means that src[index] points to a second decimal point, |
| 1045 | 1041 | // ending the number. |
| ... | ... | @@ -1058,12 +1054,9 @@ hexadecimal_string_to_float(const char *__restrict src, |
| 1058 | 1054 | // Convert the exponent from having a base of 16 to having a base of 2. |
| 1059 | 1055 | exponent *= 4; |
| 1060 | 1056 | |
| 1061 | if (tolower(src[index]) == EXPONENT_MARKER) { | |
| 1062 | bool has_sign = false; | |
| 1063 | if (src[index + 1] == '+' || src[index + 1] == '-') { | |
| 1064 | has_sign = true; | |
| 1065 | } | |
| 1066 | if (isdigit(src[index + 1 + static_cast<size_t>(has_sign)])) { | |
| 1057 | if (tolower(src[index]) == constants<CharType>::HEX_EXPONENT_MARKER) { | |
| 1058 | int sign = get_sign(src + index + 1); | |
| 1059 | if (isdigit(src[index + 1 + static_cast<size_t>(sign != 0)])) { | |
| 1067 | 1060 | ++index; |
| 1068 | 1061 | auto result = strtointeger<int32_t>(src + index, 10); |
| 1069 | 1062 | if (result.has_error()) |
| ... | ... | @@ -1099,21 +1092,21 @@ hexadecimal_string_to_float(const char *__restrict src, |
| 1099 | 1092 | return output; |
| 1100 | 1093 | } |
| 1101 | 1094 | |
| 1102 | template <class T> | |
| 1095 | template <typename T, typename CharType> | |
| 1103 | 1096 | LIBC_INLINE typename fputil::FPBits<T>::StorageType |
| 1104 | nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) { | |
| 1097 | nan_mantissa_from_ncharseq(const CharType *str, size_t len) { | |
| 1105 | 1098 | using FPBits = typename fputil::FPBits<T>; |
| 1106 | 1099 | using StorageType = typename FPBits::StorageType; |
| 1107 | 1100 | |
| 1108 | 1101 | StorageType nan_mantissa = 0; |
| 1109 | 1102 | |
| 1110 | if (ncharseq.data() != nullptr && isdigit(ncharseq[0])) { | |
| 1103 | if (len > 0 && isdigit(str[0])) { | |
| 1111 | 1104 | StrToNumResult<StorageType> strtoint_result = |
| 1112 | strtointeger<StorageType>(ncharseq.data(), 0); | |
| 1105 | strtointeger<StorageType>(str, 0, len); | |
| 1113 | 1106 | if (!strtoint_result.has_error()) |
| 1114 | 1107 | nan_mantissa = strtoint_result.value; |
| 1115 | 1108 | |
| 1116 | if (strtoint_result.parsed_len != static_cast<ptrdiff_t>(ncharseq.size())) | |
| 1109 | if (strtoint_result.parsed_len != static_cast<ptrdiff_t>(len)) | |
| 1117 | 1110 | nan_mantissa = 0; |
| 1118 | 1111 | } |
| 1119 | 1112 | |
| ... | ... | @@ -1124,59 +1117,44 @@ nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) { |
| 1124 | 1117 | // is used as the backend for all of the string to float functions. |
| 1125 | 1118 | // TODO: Add src_len member to match strtointeger. |
| 1126 | 1119 | // TODO: Next, move from char* and length to string_view |
| 1127 | template <class T> | |
| 1128 | LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) { | |
| 1120 | template <typename T, typename CharType> | |
| 1121 | LIBC_INLINE StrToNumResult<T> | |
| 1122 | strtofloatingpoint(const CharType *__restrict src) { | |
| 1129 | 1123 | using FPBits = typename fputil::FPBits<T>; |
| 1130 | 1124 | using StorageType = typename FPBits::StorageType; |
| 1131 | 1125 | |
| 1132 | 1126 | FPBits result = FPBits(); |
| 1133 | 1127 | bool seen_digit = false; |
| 1134 | char sign = '+'; | |
| 1135 | ||
| 1136 | 1128 | int error = 0; |
| 1137 | 1129 | |
| 1138 | 1130 | size_t index = first_non_whitespace(src); |
| 1131 | int sign = get_sign(src + index); | |
| 1132 | bool is_positive = (sign >= 0); | |
| 1133 | index += (sign != 0); | |
| 1139 | 1134 | |
| 1140 | if (src[index] == '+' || src[index] == '-') { | |
| 1141 | sign = src[index]; | |
| 1142 | ++index; | |
| 1143 | } | |
| 1144 | ||
| 1145 | if (sign == '-') { | |
| 1135 | if (sign < 0) { | |
| 1146 | 1136 | result.set_sign(Sign::NEG); |
| 1147 | 1137 | } |
| 1148 | 1138 | |
| 1149 | static constexpr char DECIMAL_POINT = '.'; | |
| 1150 | static const char *inf_string = "infinity"; | |
| 1151 | static const char *nan_string = "nan"; | |
| 1152 | ||
| 1153 | if (isdigit(src[index]) || src[index] == DECIMAL_POINT) { // regular number | |
| 1139 | if (isdigit(src[index]) || | |
| 1140 | src[index] == constants<CharType>::DECIMAL_POINT) { // regular number | |
| 1154 | 1141 | int base = 10; |
| 1155 | if (is_float_hex_start(src + index, DECIMAL_POINT)) { | |
| 1142 | if (is_float_hex_start(src + index)) { | |
| 1156 | 1143 | base = 16; |
| 1157 | 1144 | index += 2; |
| 1158 | 1145 | seen_digit = true; |
| 1159 | 1146 | } |
| 1160 | 1147 | |
| 1161 | 1148 | RoundDirection round_direction = RoundDirection::Nearest; |
| 1162 | ||
| 1163 | 1149 | switch (fputil::quick_get_round()) { |
| 1164 | 1150 | case FE_TONEAREST: |
| 1165 | 1151 | round_direction = RoundDirection::Nearest; |
| 1166 | 1152 | break; |
| 1167 | 1153 | case FE_UPWARD: |
| 1168 | if (sign == '+') { | |
| 1169 | round_direction = RoundDirection::Up; | |
| 1170 | } else { | |
| 1171 | round_direction = RoundDirection::Down; | |
| 1172 | } | |
| 1154 | round_direction = is_positive ? RoundDirection::Up : RoundDirection::Down; | |
| 1173 | 1155 | break; |
| 1174 | 1156 | case FE_DOWNWARD: |
| 1175 | if (sign == '+') { | |
| 1176 | round_direction = RoundDirection::Down; | |
| 1177 | } else { | |
| 1178 | round_direction = RoundDirection::Up; | |
| 1179 | } | |
| 1157 | round_direction = is_positive ? RoundDirection::Down : RoundDirection::Up; | |
| 1180 | 1158 | break; |
| 1181 | 1159 | case FE_TOWARDZERO: |
| 1182 | 1160 | round_direction = RoundDirection::Down; |
| ... | ... | @@ -1185,58 +1163,53 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) { |
| 1185 | 1163 | |
| 1186 | 1164 | StrToNumResult<ExpandedFloat<T>> parse_result({0, 0}); |
| 1187 | 1165 | if (base == 16) { |
| 1188 | parse_result = hexadecimal_string_to_float<T>(src + index, DECIMAL_POINT, | |
| 1189 | round_direction); | |
| 1166 | parse_result = | |
| 1167 | hexadecimal_string_to_float<T>(src + index, round_direction); | |
| 1190 | 1168 | } else { // base is 10 |
| 1191 | parse_result = decimal_string_to_float<T>(src + index, DECIMAL_POINT, | |
| 1192 | round_direction); | |
| 1169 | parse_result = decimal_string_to_float<T>(src + index, round_direction); | |
| 1193 | 1170 | } |
| 1194 | 1171 | seen_digit = parse_result.parsed_len != 0; |
| 1195 | 1172 | result.set_mantissa(parse_result.value.mantissa); |
| 1196 | 1173 | result.set_biased_exponent(parse_result.value.exponent); |
| 1197 | 1174 | index += parse_result.parsed_len; |
| 1198 | 1175 | error = parse_result.error; |
| 1199 | } else if (tolower(src[index]) == 'n') { // NaN | |
| 1200 | if (tolower(src[index + 1]) == nan_string[1] && | |
| 1201 | tolower(src[index + 2]) == nan_string[2]) { | |
| 1202 | seen_digit = true; | |
| 1203 | index += 3; | |
| 1204 | StorageType nan_mantissa = 0; | |
| 1205 | // this handles the case of `NaN(n-character-sequence)`, where the | |
| 1206 | // n-character-sequence is made of 0 or more letters, numbers, or | |
| 1207 | // underscore characters in any order. | |
| 1208 | if (src[index] == '(') { | |
| 1209 | size_t left_paren = index; | |
| 1176 | } else if (tolower_starts_with(src + index, 3, | |
| 1177 | constants<CharType>::NAN_STRING)) { | |
| 1178 | // NAN | |
| 1179 | seen_digit = true; | |
| 1180 | index += 3; | |
| 1181 | StorageType nan_mantissa = 0; | |
| 1182 | // this handles the case of `NaN(n-character-sequence)`, where the | |
| 1183 | // n-character-sequence is made of 0 or more letters, numbers, or | |
| 1184 | // underscore characters in any order. | |
| 1185 | if (is_char_or_wchar(src[index], '(', L'(')) { | |
| 1186 | size_t left_paren = index; | |
| 1187 | ++index; | |
| 1188 | while (isalnum(src[index]) || is_char_or_wchar(src[index], '_', L'_')) | |
| 1210 | 1189 | ++index; |
| 1211 | while (isalnum(src[index]) || src[index] == '_') | |
| 1212 | ++index; | |
| 1213 | if (src[index] == ')') { | |
| 1214 | ++index; | |
| 1215 | nan_mantissa = nan_mantissa_from_ncharseq<T>( | |
| 1216 | cpp::string_view(src + (left_paren + 1), index - left_paren - 2)); | |
| 1217 | } else { | |
| 1218 | index = left_paren; | |
| 1219 | } | |
| 1220 | } | |
| 1221 | result = FPBits(result.quiet_nan(result.sign(), nan_mantissa)); | |
| 1222 | } | |
| 1223 | } else if (tolower(src[index]) == 'i') { // INF | |
| 1224 | if (tolower(src[index + 1]) == inf_string[1] && | |
| 1225 | tolower(src[index + 2]) == inf_string[2]) { | |
| 1226 | seen_digit = true; | |
| 1227 | result = FPBits(result.inf(result.sign())); | |
| 1228 | if (tolower(src[index + 3]) == inf_string[3] && | |
| 1229 | tolower(src[index + 4]) == inf_string[4] && | |
| 1230 | tolower(src[index + 5]) == inf_string[5] && | |
| 1231 | tolower(src[index + 6]) == inf_string[6] && | |
| 1232 | tolower(src[index + 7]) == inf_string[7]) { | |
| 1233 | // if the string is "INFINITY" then consume 8 characters. | |
| 1234 | index += 8; | |
| 1190 | if (is_char_or_wchar(src[index], ')', L')')) { | |
| 1191 | ++index; | |
| 1192 | nan_mantissa = nan_mantissa_from_ncharseq<T>(src + (left_paren + 1), | |
| 1193 | index - left_paren - 2); | |
| 1235 | 1194 | } else { |
| 1236 | index += 3; | |
| 1195 | index = left_paren; | |
| 1237 | 1196 | } |
| 1238 | 1197 | } |
| 1198 | result = FPBits(result.quiet_nan(result.sign(), nan_mantissa)); | |
| 1199 | } else if (tolower_starts_with(src + index, 8, | |
| 1200 | constants<CharType>::INF_STRING)) { | |
| 1201 | // INFINITY | |
| 1202 | seen_digit = true; | |
| 1203 | result = FPBits(result.inf(result.sign())); | |
| 1204 | index += 8; | |
| 1205 | } else if (tolower_starts_with(src + index, 3, | |
| 1206 | constants<CharType>::INF_STRING)) { | |
| 1207 | // INF | |
| 1208 | seen_digit = true; | |
| 1209 | result = FPBits(result.inf(result.sign())); | |
| 1210 | index += 3; | |
| 1239 | 1211 | } |
| 1212 | ||
| 1240 | 1213 | if (!seen_digit) { // If there is nothing to actually parse, then return 0. |
| 1241 | 1214 | return {T(0), 0, error}; |
| 1242 | 1215 | } |
| ... | ... | @@ -1263,7 +1236,7 @@ template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) { |
| 1263 | 1236 | ++index; |
| 1264 | 1237 | |
| 1265 | 1238 | if (arg[index] == '\0') |
| 1266 | nan_mantissa = nan_mantissa_from_ncharseq<T>(cpp::string_view(arg, index)); | |
| 1239 | nan_mantissa = nan_mantissa_from_ncharseq<T>(arg, index); | |
| 1267 | 1240 | |
| 1268 | 1241 | result = FPBits::quiet_nan(Sign::POS, nan_mantissa); |
| 1269 | 1242 | return {result.get_val(), 0, error}; |
lib/libcxx/libc/src/__support/str_to_integer.h+39-27| ... | ... | @@ -25,36 +25,51 @@ |
| 25 | 25 | #include "src/__support/macros/config.h" |
| 26 | 26 | #include "src/__support/str_to_num_result.h" |
| 27 | 27 | #include "src/__support/uint128.h" |
| 28 | #include "src/__support/wctype_utils.h" | |
| 28 | 29 | |
| 29 | 30 | namespace LIBC_NAMESPACE_DECL { |
| 30 | 31 | namespace internal { |
| 31 | 32 | |
| 32 | 33 | // Returns the idx to the first character in src that is not a whitespace |
| 33 | 34 | // character (as determined by isspace()) |
| 35 | template <typename CharType> | |
| 34 | 36 | LIBC_INLINE size_t |
| 35 | first_non_whitespace(const char *__restrict src, | |
| 37 | first_non_whitespace(const CharType *__restrict src, | |
| 36 | 38 | size_t src_len = cpp::numeric_limits<size_t>::max()) { |
| 37 | 39 | size_t src_cur = 0; |
| 38 | while (src_cur < src_len && internal::isspace(src[src_cur])) { | |
| 39 | ++src_cur; | |
| 40 | } | |
| 40 | for (; src_cur < src_len && internal::isspace(src[src_cur]); ++src_cur) | |
| 41 | ; | |
| 41 | 42 | return src_cur; |
| 42 | 43 | } |
| 43 | 44 | |
| 45 | // Returns +1, -1, or 0 if 'src' starts with (respectively) | |
| 46 | // plus sign, minus sign, or neither. | |
| 47 | template <typename CharType> | |
| 48 | LIBC_INLINE static int get_sign(const CharType *__restrict src) { | |
| 49 | if (is_char_or_wchar(src[0], '+', L'+')) | |
| 50 | return 1; | |
| 51 | if (is_char_or_wchar(src[0], '-', L'-')) | |
| 52 | return -1; | |
| 53 | return 0; | |
| 54 | } | |
| 55 | ||
| 44 | 56 | // checks if the next 3 characters of the string pointer are the start of a |
| 45 | 57 | // hexadecimal number. Does not advance the string pointer. |
| 46 | LIBC_INLINE bool | |
| 47 | is_hex_start(const char *__restrict src, | |
| 48 | size_t src_len = cpp::numeric_limits<size_t>::max()) { | |
| 58 | template <typename CharType> | |
| 59 | LIBC_INLINE static bool is_hex_start(const CharType *__restrict src, | |
| 60 | size_t src_len) { | |
| 49 | 61 | if (src_len < 3) |
| 50 | 62 | return false; |
| 51 | return *src == '0' && tolower(*(src + 1)) == 'x' && isalnum(*(src + 2)) && | |
| 52 | b36_char_to_int(*(src + 2)) < 16; | |
| 63 | return is_char_or_wchar(src[0], '0', L'0') && | |
| 64 | is_char_or_wchar(tolower(src[1]), 'x', L'x') && isalnum(src[2]) && | |
| 65 | b36_char_to_int(src[2]) < 16; | |
| 53 | 66 | } |
| 54 | 67 | |
| 55 | 68 | // Takes the address of the string pointer and parses the base from the start of |
| 56 | 69 | // it. |
| 57 | LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) { | |
| 70 | template <typename CharType> | |
| 71 | LIBC_INLINE static int infer_base(const CharType *__restrict src, | |
| 72 | size_t src_len) { | |
| 58 | 73 | // A hexadecimal number is defined as "the prefix 0x or 0X followed by a |
| 59 | 74 | // sequence of the decimal digits and the letters a (or A) through f (or F) |
| 60 | 75 | // with values 10 through 15 respectively." (C standard 6.4.4.1) |
| ... | ... | @@ -63,8 +78,9 @@ LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) { |
| 63 | 78 | // An octal number is defined as "the prefix 0 optionally followed by a |
| 64 | 79 | // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any |
| 65 | 80 | // number that starts with 0, including just 0, is an octal number. |
| 66 | if (src_len > 0 && src[0] == '0') | |
| 81 | if (src_len > 0 && is_char_or_wchar(src[0], '0', L'0')) { | |
| 67 | 82 | return 8; |
| 83 | } | |
| 68 | 84 | // A decimal number is defined as beginning "with a nonzero digit and |
| 69 | 85 | // consist[ing] of a sequence of decimal digits." (C standard 6.4.4.1) |
| 70 | 86 | return 10; |
| ... | ... | @@ -77,32 +93,27 @@ LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) { |
| 77 | 93 | // ----------------------------------------------------------------------------- |
| 78 | 94 | // Takes a pointer to a string and the base to convert to. This function is used |
| 79 | 95 | // as the backend for all of the string to int functions. |
| 80 | template <class T> | |
| 96 | template <typename T, typename CharType> | |
| 81 | 97 | LIBC_INLINE StrToNumResult<T> |
| 82 | strtointeger(const char *__restrict src, int base, | |
| 98 | strtointeger(const CharType *__restrict src, int base, | |
| 83 | 99 | const size_t src_len = cpp::numeric_limits<size_t>::max()) { |
| 84 | 100 | using ResultType = make_integral_or_big_int_unsigned_t<T>; |
| 85 | 101 | |
| 86 | ResultType result = 0; | |
| 87 | ||
| 88 | bool is_number = false; | |
| 89 | size_t src_cur = 0; | |
| 90 | int error_val = 0; | |
| 91 | ||
| 92 | 102 | if (src_len == 0) |
| 93 | 103 | return {0, 0, 0}; |
| 94 | 104 | |
| 95 | 105 | if (base < 0 || base == 1 || base > 36) |
| 96 | 106 | return {0, 0, EINVAL}; |
| 97 | 107 | |
| 98 | src_cur = first_non_whitespace(src, src_len); | |
| 99 | ||
| 100 | char result_sign = '+'; | |
| 101 | if (src[src_cur] == '+' || src[src_cur] == '-') { | |
| 102 | result_sign = src[src_cur]; | |
| 103 | ++src_cur; | |
| 108 | size_t src_cur = first_non_whitespace(src, src_len); | |
| 109 | if (src_cur == src_len) { | |
| 110 | return {0, 0, 0}; | |
| 104 | 111 | } |
| 105 | 112 | |
| 113 | int sign = get_sign(src + src_cur); | |
| 114 | bool is_positive = (sign >= 0); | |
| 115 | src_cur += (sign != 0); | |
| 116 | ||
| 106 | 117 | if (base == 0) |
| 107 | 118 | base = infer_base(src + src_cur, src_len - src_cur); |
| 108 | 119 | |
| ... | ... | @@ -110,8 +121,6 @@ strtointeger(const char *__restrict src, int base, |
| 110 | 121 | src_cur = src_cur + 2; |
| 111 | 122 | |
| 112 | 123 | constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>; |
| 113 | const bool is_positive = (result_sign == '+'); | |
| 114 | ||
| 115 | 124 | ResultType constexpr NEGATIVE_MAX = |
| 116 | 125 | !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1 |
| 117 | 126 | : cpp::numeric_limits<T>::max(); |
| ... | ... | @@ -120,6 +129,9 @@ strtointeger(const char *__restrict src, int base, |
| 120 | 129 | ResultType const abs_max_div_by_base = |
| 121 | 130 | abs_max / static_cast<ResultType>(base); |
| 122 | 131 | |
| 132 | bool is_number = false; | |
| 133 | int error_val = 0; | |
| 134 | ResultType result = 0; | |
| 123 | 135 | while (src_cur < src_len && isalnum(src[src_cur])) { |
| 124 | 136 | int cur_digit = b36_char_to_int(src[src_cur]); |
| 125 | 137 | if (cur_digit >= base) |
lib/libcxx/libc/src/__support/wctype_utils.h created+588| ... | ... | @@ -0,0 +1,588 @@ |
| 1 | //===-- Collection of utils for implementing wide char 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 | ||
| 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_WCTYPE_UTILS_H | |
| 10 | #define LLVM_LIBC_SRC___SUPPORT_WCTYPE_UTILS_H | |
| 11 | ||
| 12 | #include "hdr/types/wchar_t.h" | |
| 13 | #include "src/__support/macros/attributes.h" // LIBC_INLINE | |
| 14 | #include "src/__support/macros/config.h" | |
| 15 | ||
| 16 | namespace LIBC_NAMESPACE_DECL { | |
| 17 | namespace internal { | |
| 18 | ||
| 19 | // ----------------------------------------------------------------------------- | |
| 20 | // ****************** WARNING ****************** | |
| 21 | // ****************** DO NOT TRY TO OPTIMIZE THESE FUNCTIONS! ****************** | |
| 22 | // ----------------------------------------------------------------------------- | |
| 23 | // This switch/case form is easier for the compiler to understand, and is | |
| 24 | // optimized into a form that is almost always the same as or better than | |
| 25 | // versions written by hand (see https://godbolt.org/z/qvrebqvvr). Also this | |
| 26 | // form makes these functions encoding independent. If you want to rewrite these | |
| 27 | // functions, make sure you have benchmarks to show your new solution is faster, | |
| 28 | // as well as a way to support non-ASCII character encodings. | |
| 29 | ||
| 30 | // Similarly, do not change these fumarks to show your new solution is faster, | |
| 31 | // as well as a way to support non-Anctions to use case ranges. e.g. | |
| 32 | // bool islower(wchar_t ch) { | |
| 33 | // switch(ch) { | |
| 34 | // case L'a'...L'z': | |
| 35 | // return true; | |
| 36 | // } | |
| 37 | // } | |
| 38 | // 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 | |
| 40 | // to read. | |
| 41 | ||
| 42 | LIBC_INLINE static constexpr bool islower(wchar_t wch) { | |
| 43 | switch (wch) { | |
| 44 | case L'a': | |
| 45 | case L'b': | |
| 46 | case L'c': | |
| 47 | case L'd': | |
| 48 | case L'e': | |
| 49 | case L'f': | |
| 50 | case L'g': | |
| 51 | case L'h': | |
| 52 | case L'i': | |
| 53 | case L'j': | |
| 54 | case L'k': | |
| 55 | case L'l': | |
| 56 | case L'm': | |
| 57 | case L'n': | |
| 58 | case L'o': | |
| 59 | case L'p': | |
| 60 | case L'q': | |
| 61 | case L'r': | |
| 62 | case L's': | |
| 63 | case L't': | |
| 64 | case L'u': | |
| 65 | case L'v': | |
| 66 | case L'w': | |
| 67 | case L'x': | |
| 68 | case L'y': | |
| 69 | case L'z': | |
| 70 | return true; | |
| 71 | default: | |
| 72 | return false; | |
| 73 | } | |
| 74 | } | |
| 75 | ||
| 76 | LIBC_INLINE static constexpr bool isupper(wchar_t wch) { | |
| 77 | switch (wch) { | |
| 78 | case L'A': | |
| 79 | case L'B': | |
| 80 | case L'C': | |
| 81 | case L'D': | |
| 82 | case L'E': | |
| 83 | case L'F': | |
| 84 | case L'G': | |
| 85 | case L'H': | |
| 86 | case L'I': | |
| 87 | case L'J': | |
| 88 | case L'K': | |
| 89 | case L'L': | |
| 90 | case L'M': | |
| 91 | case L'N': | |
| 92 | case L'O': | |
| 93 | case L'P': | |
| 94 | case L'Q': | |
| 95 | case L'R': | |
| 96 | case L'S': | |
| 97 | case L'T': | |
| 98 | case L'U': | |
| 99 | case L'V': | |
| 100 | case L'W': | |
| 101 | case L'X': | |
| 102 | case L'Y': | |
| 103 | case L'Z': | |
| 104 | return true; | |
| 105 | default: | |
| 106 | return false; | |
| 107 | } | |
| 108 | } | |
| 109 | ||
| 110 | LIBC_INLINE static constexpr bool isdigit(wchar_t wch) { | |
| 111 | switch (wch) { | |
| 112 | case L'0': | |
| 113 | case L'1': | |
| 114 | case L'2': | |
| 115 | case L'3': | |
| 116 | case L'4': | |
| 117 | case L'5': | |
| 118 | case L'6': | |
| 119 | case L'7': | |
| 120 | case L'8': | |
| 121 | case L'9': | |
| 122 | return true; | |
| 123 | default: | |
| 124 | return false; | |
| 125 | } | |
| 126 | } | |
| 127 | ||
| 128 | LIBC_INLINE static constexpr wchar_t tolower(wchar_t wch) { | |
| 129 | switch (wch) { | |
| 130 | case L'A': | |
| 131 | return L'a'; | |
| 132 | case L'B': | |
| 133 | return L'b'; | |
| 134 | case L'C': | |
| 135 | return L'c'; | |
| 136 | case L'D': | |
| 137 | return L'd'; | |
| 138 | case L'E': | |
| 139 | return L'e'; | |
| 140 | case L'F': | |
| 141 | return L'f'; | |
| 142 | case L'G': | |
| 143 | return L'g'; | |
| 144 | case L'H': | |
| 145 | return L'h'; | |
| 146 | case L'I': | |
| 147 | return L'i'; | |
| 148 | case L'J': | |
| 149 | return L'j'; | |
| 150 | case L'K': | |
| 151 | return L'k'; | |
| 152 | case L'L': | |
| 153 | return L'l'; | |
| 154 | case L'M': | |
| 155 | return L'm'; | |
| 156 | case L'N': | |
| 157 | return L'n'; | |
| 158 | case L'O': | |
| 159 | return L'o'; | |
| 160 | case L'P': | |
| 161 | return L'p'; | |
| 162 | case L'Q': | |
| 163 | return L'q'; | |
| 164 | case L'R': | |
| 165 | return L'r'; | |
| 166 | case L'S': | |
| 167 | return L's'; | |
| 168 | case L'T': | |
| 169 | return L't'; | |
| 170 | case L'U': | |
| 171 | return L'u'; | |
| 172 | case L'V': | |
| 173 | return L'v'; | |
| 174 | case L'W': | |
| 175 | return L'w'; | |
| 176 | case L'X': | |
| 177 | return L'x'; | |
| 178 | case L'Y': | |
| 179 | return L'y'; | |
| 180 | case L'Z': | |
| 181 | return L'z'; | |
| 182 | default: | |
| 183 | return wch; | |
| 184 | } | |
| 185 | } | |
| 186 | ||
| 187 | LIBC_INLINE static constexpr wchar_t toupper(wchar_t wch) { | |
| 188 | switch (wch) { | |
| 189 | case L'a': | |
| 190 | return L'A'; | |
| 191 | case L'b': | |
| 192 | return L'B'; | |
| 193 | case L'c': | |
| 194 | return L'C'; | |
| 195 | case L'd': | |
| 196 | return L'D'; | |
| 197 | case L'e': | |
| 198 | return L'E'; | |
| 199 | case L'f': | |
| 200 | return L'F'; | |
| 201 | case L'g': | |
| 202 | return L'G'; | |
| 203 | case L'h': | |
| 204 | return L'H'; | |
| 205 | case L'i': | |
| 206 | return L'I'; | |
| 207 | case L'j': | |
| 208 | return L'J'; | |
| 209 | case L'k': | |
| 210 | return L'K'; | |
| 211 | case L'l': | |
| 212 | return L'L'; | |
| 213 | case L'm': | |
| 214 | return L'M'; | |
| 215 | case L'n': | |
| 216 | return L'N'; | |
| 217 | case L'o': | |
| 218 | return L'O'; | |
| 219 | case L'p': | |
| 220 | return L'P'; | |
| 221 | case L'q': | |
| 222 | return L'Q'; | |
| 223 | case L'r': | |
| 224 | return L'R'; | |
| 225 | case L's': | |
| 226 | return L'S'; | |
| 227 | case L't': | |
| 228 | return L'T'; | |
| 229 | case L'u': | |
| 230 | return L'U'; | |
| 231 | case L'v': | |
| 232 | return L'V'; | |
| 233 | case L'w': | |
| 234 | return L'W'; | |
| 235 | case L'x': | |
| 236 | return L'X'; | |
| 237 | case L'y': | |
| 238 | return L'Y'; | |
| 239 | case L'z': | |
| 240 | return L'Z'; | |
| 241 | default: | |
| 242 | return wch; | |
| 243 | } | |
| 244 | } | |
| 245 | ||
| 246 | LIBC_INLINE static constexpr bool isalpha(wchar_t wch) { | |
| 247 | switch (wch) { | |
| 248 | case L'a': | |
| 249 | case L'b': | |
| 250 | case L'c': | |
| 251 | case L'd': | |
| 252 | case L'e': | |
| 253 | 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': | |
| 275 | case L'B': | |
| 276 | case L'C': | |
| 277 | case L'D': | |
| 278 | case L'E': | |
| 279 | case L'F': | |
| 280 | case L'G': | |
| 281 | case L'H': | |
| 282 | case L'I': | |
| 283 | case L'J': | |
| 284 | case L'K': | |
| 285 | case L'L': | |
| 286 | case L'M': | |
| 287 | case L'N': | |
| 288 | case L'O': | |
| 289 | case L'P': | |
| 290 | case L'Q': | |
| 291 | case L'R': | |
| 292 | case L'S': | |
| 293 | case L'T': | |
| 294 | case L'U': | |
| 295 | case L'V': | |
| 296 | case L'W': | |
| 297 | case L'X': | |
| 298 | case L'Y': | |
| 299 | case L'Z': | |
| 300 | return true; | |
| 301 | default: | |
| 302 | return false; | |
| 303 | } | |
| 304 | } | |
| 305 | ||
| 306 | LIBC_INLINE static constexpr bool isalnum(wchar_t wch) { | |
| 307 | switch (wch) { | |
| 308 | case L'a': | |
| 309 | case L'b': | |
| 310 | case L'c': | |
| 311 | case L'd': | |
| 312 | case L'e': | |
| 313 | case L'f': | |
| 314 | case L'g': | |
| 315 | case L'h': | |
| 316 | case L'i': | |
| 317 | case L'j': | |
| 318 | case L'k': | |
| 319 | case L'l': | |
| 320 | case L'm': | |
| 321 | case L'n': | |
| 322 | case L'o': | |
| 323 | case L'p': | |
| 324 | case L'q': | |
| 325 | case L'r': | |
| 326 | case L's': | |
| 327 | case L't': | |
| 328 | case L'u': | |
| 329 | case L'v': | |
| 330 | case L'w': | |
| 331 | case L'x': | |
| 332 | case L'y': | |
| 333 | case L'z': | |
| 334 | case L'A': | |
| 335 | case L'B': | |
| 336 | case L'C': | |
| 337 | case L'D': | |
| 338 | case L'E': | |
| 339 | case L'F': | |
| 340 | case L'G': | |
| 341 | case L'H': | |
| 342 | case L'I': | |
| 343 | case L'J': | |
| 344 | case L'K': | |
| 345 | case L'L': | |
| 346 | case L'M': | |
| 347 | case L'N': | |
| 348 | case L'O': | |
| 349 | case L'P': | |
| 350 | case L'Q': | |
| 351 | case L'R': | |
| 352 | case L'S': | |
| 353 | case L'T': | |
| 354 | case L'U': | |
| 355 | case L'V': | |
| 356 | case L'W': | |
| 357 | case L'X': | |
| 358 | case L'Y': | |
| 359 | case L'Z': | |
| 360 | case L'0': | |
| 361 | case L'1': | |
| 362 | case L'2': | |
| 363 | case L'3': | |
| 364 | case L'4': | |
| 365 | case L'5': | |
| 366 | case L'6': | |
| 367 | case L'7': | |
| 368 | case L'8': | |
| 369 | case L'9': | |
| 370 | return true; | |
| 371 | default: | |
| 372 | return false; | |
| 373 | } | |
| 374 | } | |
| 375 | ||
| 376 | LIBC_INLINE static constexpr int b36_char_to_int(wchar_t wch) { | |
| 377 | switch (wch) { | |
| 378 | case L'0': | |
| 379 | return 0; | |
| 380 | case L'1': | |
| 381 | return 1; | |
| 382 | case L'2': | |
| 383 | return 2; | |
| 384 | case L'3': | |
| 385 | return 3; | |
| 386 | case L'4': | |
| 387 | return 4; | |
| 388 | case L'5': | |
| 389 | return 5; | |
| 390 | case L'6': | |
| 391 | return 6; | |
| 392 | case L'7': | |
| 393 | return 7; | |
| 394 | case L'8': | |
| 395 | return 8; | |
| 396 | case L'9': | |
| 397 | return 9; | |
| 398 | case L'a': | |
| 399 | case L'A': | |
| 400 | return 10; | |
| 401 | case L'b': | |
| 402 | case L'B': | |
| 403 | return 11; | |
| 404 | case L'c': | |
| 405 | case L'C': | |
| 406 | return 12; | |
| 407 | case L'd': | |
| 408 | case L'D': | |
| 409 | return 13; | |
| 410 | case L'e': | |
| 411 | case L'E': | |
| 412 | return 14; | |
| 413 | case L'f': | |
| 414 | case L'F': | |
| 415 | return 15; | |
| 416 | case L'g': | |
| 417 | case L'G': | |
| 418 | return 16; | |
| 419 | case L'h': | |
| 420 | case L'H': | |
| 421 | return 17; | |
| 422 | case L'i': | |
| 423 | case L'I': | |
| 424 | return 18; | |
| 425 | case L'j': | |
| 426 | case L'J': | |
| 427 | return 19; | |
| 428 | case L'k': | |
| 429 | case L'K': | |
| 430 | return 20; | |
| 431 | case L'l': | |
| 432 | case L'L': | |
| 433 | return 21; | |
| 434 | case L'm': | |
| 435 | case L'M': | |
| 436 | return 22; | |
| 437 | case L'n': | |
| 438 | case L'N': | |
| 439 | return 23; | |
| 440 | case L'o': | |
| 441 | case L'O': | |
| 442 | return 24; | |
| 443 | case L'p': | |
| 444 | case L'P': | |
| 445 | return 25; | |
| 446 | case L'q': | |
| 447 | case L'Q': | |
| 448 | return 26; | |
| 449 | case L'r': | |
| 450 | case L'R': | |
| 451 | return 27; | |
| 452 | case L's': | |
| 453 | case L'S': | |
| 454 | return 28; | |
| 455 | case L't': | |
| 456 | case L'T': | |
| 457 | return 29; | |
| 458 | case L'u': | |
| 459 | case L'U': | |
| 460 | return 30; | |
| 461 | case L'v': | |
| 462 | case L'V': | |
| 463 | return 31; | |
| 464 | case L'w': | |
| 465 | case L'W': | |
| 466 | return 32; | |
| 467 | case L'x': | |
| 468 | case L'X': | |
| 469 | return 33; | |
| 470 | case L'y': | |
| 471 | case L'Y': | |
| 472 | return 34; | |
| 473 | case L'z': | |
| 474 | case L'Z': | |
| 475 | return 35; | |
| 476 | default: | |
| 477 | return 0; | |
| 478 | } | |
| 479 | } | |
| 480 | ||
| 481 | LIBC_INLINE static constexpr wchar_t int_to_b36_wchar(int num) { | |
| 482 | // Can't actually use LIBC_ASSERT here because it depends on integer_to_string | |
| 483 | // which depends on this. | |
| 484 | ||
| 485 | // LIBC_ASSERT(num < 36); | |
| 486 | switch (num) { | |
| 487 | case 0: | |
| 488 | return L'0'; | |
| 489 | case 1: | |
| 490 | return L'1'; | |
| 491 | case 2: | |
| 492 | return L'2'; | |
| 493 | case 3: | |
| 494 | return L'3'; | |
| 495 | case 4: | |
| 496 | return L'4'; | |
| 497 | case 5: | |
| 498 | return L'5'; | |
| 499 | case 6: | |
| 500 | return L'6'; | |
| 501 | case 7: | |
| 502 | return L'7'; | |
| 503 | case 8: | |
| 504 | return L'8'; | |
| 505 | case 9: | |
| 506 | return L'9'; | |
| 507 | case 10: | |
| 508 | return L'a'; | |
| 509 | case 11: | |
| 510 | return L'b'; | |
| 511 | case 12: | |
| 512 | return L'c'; | |
| 513 | case 13: | |
| 514 | return L'd'; | |
| 515 | case 14: | |
| 516 | return L'e'; | |
| 517 | case 15: | |
| 518 | return L'f'; | |
| 519 | case 16: | |
| 520 | return L'g'; | |
| 521 | case 17: | |
| 522 | return L'h'; | |
| 523 | case 18: | |
| 524 | return L'i'; | |
| 525 | case 19: | |
| 526 | return L'j'; | |
| 527 | case 20: | |
| 528 | return L'k'; | |
| 529 | case 21: | |
| 530 | return L'l'; | |
| 531 | case 22: | |
| 532 | return L'm'; | |
| 533 | case 23: | |
| 534 | return L'n'; | |
| 535 | case 24: | |
| 536 | return L'o'; | |
| 537 | case 25: | |
| 538 | return L'p'; | |
| 539 | case 26: | |
| 540 | return L'q'; | |
| 541 | case 27: | |
| 542 | return L'r'; | |
| 543 | case 28: | |
| 544 | return L's'; | |
| 545 | case 29: | |
| 546 | return L't'; | |
| 547 | case 30: | |
| 548 | return L'u'; | |
| 549 | case 31: | |
| 550 | return L'v'; | |
| 551 | case 32: | |
| 552 | return L'w'; | |
| 553 | case 33: | |
| 554 | return L'x'; | |
| 555 | case 34: | |
| 556 | return L'y'; | |
| 557 | case 35: | |
| 558 | return L'z'; | |
| 559 | default: | |
| 560 | return L'!'; | |
| 561 | } | |
| 562 | } | |
| 563 | ||
| 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 | |
| 579 | // values, when input can be of a regular or a wide character type. | |
| 580 | LIBC_INLINE static constexpr bool | |
| 581 | is_char_or_wchar(wchar_t ch, [[maybe_unused]] char, wchar_t wc_value) { | |
| 582 | return (ch == wc_value); | |
| 583 | } | |
| 584 | ||
| 585 | } // namespace internal | |
| 586 | } // namespace LIBC_NAMESPACE_DECL | |
| 587 | ||
| 588 | #endif // LLVM_LIBC_SRC___SUPPORT_WCTYPE_UTILS_H |