| 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,7 +15,9 @@ |
| 15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
| 16 | 16 | ||
| 17 | #include "include/llvm-libc-macros/error-number-macros.h" | 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 | #include "include/llvm-libc-macros/generic-error-number-macros.h" | 21 | #include "include/llvm-libc-macros/generic-error-number-macros.h" |
| 20 | #endif | 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,36 +9,19 @@ |
| 9 | #ifndef LLVM_LIBC_TYPES_CFLOAT128_H | 9 | #ifndef LLVM_LIBC_TYPES_CFLOAT128_H |
| 10 | #define LLVM_LIBC_TYPES_CFLOAT128_H | 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 | 14 | #ifdef LIBC_TYPES_HAS_CFLOAT128 |
| 15 | // built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For | 15 | #ifndef LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE |
| 16 | // clang, the complex variant of `__float128` is defined instead, and only on | 16 | #if defined(__GNUC__) && !defined(__clang__) |
| 17 | // x86-64 targets for clang 11 or later. | 17 | // Remove the workaround when https://gcc.gnu.org/PR32187 gets fixed. |
| 18 | // | 18 | typedef __typeof__(_Complex __float128) cfloat128; |
| 19 | // TODO: Update the complex variant of C23 `_Float128` type detection again when | 19 | #else // ^^^ workaround / no workaround vvv |
| 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 | typedef _Complex __float128 cfloat128; | 20 | typedef _Complex __float128 cfloat128; |
| 29 | #endif | 21 | #endif // ^^^ no workaround ^^^ |
| 30 | #elif defined(__GNUC__) | 22 | #else |
| 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 | ||
| 41 | typedef _Complex long double cfloat128; | 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 | #endif // LLVM_LIBC_TYPES_CFLOAT128_H | 27 | #endif // LLVM_LIBC_TYPES_CFLOAT128_H |
lib/libcxx/libc/include/llvm-libc-types/cfloat16.h+4-7| ... | @@ -9,13 +9,10 @@ | ... | @@ -9,13 +9,10 @@ |
| 9 | #ifndef LLVM_LIBC_TYPES_CFLOAT16_H | 9 | #ifndef LLVM_LIBC_TYPES_CFLOAT16_H |
| 10 | #define LLVM_LIBC_TYPES_CFLOAT16_H | 10 | #define LLVM_LIBC_TYPES_CFLOAT16_H |
| 11 | 11 | ||
| 12 | #if defined(__FLT16_MANT_DIG__) && \ | 12 | #include "../llvm-libc-macros/cfloat16-macros.h" |
| 13 | (!defined(__GNUC__) || __GNUC__ >= 13 || \ | 13 | |
| 14 | (defined(__clang__) && __clang_major__ >= 14)) && \ | 14 | #ifdef LIBC_TYPES_HAS_CFLOAT16 |
| 15 | !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \ | ||
| 16 | !defined(_WIN32) | ||
| 17 | #define LIBC_TYPES_HAS_CFLOAT16 | ||
| 18 | typedef _Complex _Float16 cfloat16; | 15 | typedef _Complex _Float16 cfloat16; |
| 19 | #endif | 16 | #endif // LIBC_TYPES_HAS_CFLOAT16 |
| 20 | 17 | ||
| 21 | #endif // LLVM_LIBC_TYPES_CFLOAT16_H | 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,6 +19,11 @@ |
| 19 | #define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM_INLINE | 19 | #define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM_INLINE |
| 20 | #endif // LIBC_ERRNO_MODE | 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 | #ifndef LIBC_NAMESPACE | 27 | #ifndef LIBC_NAMESPACE |
| 23 | #define LIBC_NAMESPACE __llvm_libc | 28 | #define LIBC_NAMESPACE __llvm_libc |
| 24 | #endif // LIBC_NAMESPACE | 29 | #endif // LIBC_NAMESPACE |
lib/libcxx/libc/src/__support/CPP/bit.h+50-12| ... | @@ -11,14 +11,14 @@ | ... | @@ -11,14 +11,14 @@ |
| 11 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H | 11 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H |
| 12 | #define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H | 12 | #define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H |
| 13 | 13 | ||
| 14 | #include "hdr/stdint_proxy.h" | ||
| 14 | #include "src/__support/CPP/limits.h" // numeric_limits | 15 | #include "src/__support/CPP/limits.h" // numeric_limits |
| 15 | #include "src/__support/CPP/type_traits.h" | 16 | #include "src/__support/CPP/type_traits.h" |
| 16 | #include "src/__support/macros/attributes.h" | 17 | #include "src/__support/macros/attributes.h" |
| 17 | #include "src/__support/macros/config.h" | 18 | #include "src/__support/macros/config.h" |
| 19 | #include "src/__support/macros/properties/compiler.h" | ||
| 18 | #include "src/__support/macros/sanitizer.h" | 20 | #include "src/__support/macros/sanitizer.h" |
| 19 | 21 | ||
| 20 | #include <stdint.h> | ||
| 21 | |||
| 22 | namespace LIBC_NAMESPACE_DECL { | 22 | namespace LIBC_NAMESPACE_DECL { |
| 23 | namespace cpp { | 23 | namespace cpp { |
| 24 | 24 | ||
| ... | @@ -26,6 +26,16 @@ namespace cpp { | ... | @@ -26,6 +26,16 @@ namespace cpp { |
| 26 | #define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE | 26 | #define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE |
| 27 | #endif | 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 | // This implementation of bit_cast requires trivially-constructible To, to avoid | 39 | // This implementation of bit_cast requires trivially-constructible To, to avoid |
| 30 | // UB in the implementation. | 40 | // UB in the implementation. |
| 31 | template <typename To, typename From> | 41 | template <typename To, typename From> |
| ... | @@ -37,22 +47,32 @@ LIBC_INLINE constexpr cpp::enable_if_t< | ... | @@ -37,22 +47,32 @@ LIBC_INLINE constexpr cpp::enable_if_t< |
| 37 | To> | 47 | To> |
| 38 | bit_cast(const From &from) { | 48 | bit_cast(const From &from) { |
| 39 | MSAN_UNPOISON(&from, sizeof(From)); | 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 | return __builtin_bit_cast(To, from); | 51 | return __builtin_bit_cast(To, from); |
| 42 | #else | 52 | #else |
| 43 | To to; | 53 | To to{}; |
| 44 | char *dst = reinterpret_cast<char *>(&to); | 54 | char *dst = reinterpret_cast<char *>(&to); |
| 45 | const char *src = reinterpret_cast<const char *>(&from); | 55 | const char *src = reinterpret_cast<const char *>(&from); |
| 46 | #if __has_builtin(__builtin_memcpy_inline) | 56 | inline_copy<sizeof(From)>(src, dst); |
| 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) | ||
| 52 | return to; | 57 | return to; |
| 53 | #endif // __has_builtin(__builtin_bit_cast) | 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 | template <typename T> | 76 | template <typename T> |
| 57 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, | 77 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, |
| 58 | bool> | 78 | bool> |
| ... | @@ -105,10 +125,16 @@ countr_zero(T value) { | ... | @@ -105,10 +125,16 @@ countr_zero(T value) { |
| 105 | } | 125 | } |
| 106 | #if __has_builtin(__builtin_ctzs) | 126 | #if __has_builtin(__builtin_ctzs) |
| 107 | ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs) | 127 | ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs) |
| 108 | #endif | 128 | #endif // __has_builtin(__builtin_ctzs) |
| 129 | #if __has_builtin(__builtin_ctz) | ||
| 109 | ADD_SPECIALIZATION(countr_zero, unsigned int, __builtin_ctz) | 130 | ADD_SPECIALIZATION(countr_zero, unsigned int, __builtin_ctz) |
| 131 | #endif // __has_builtin(__builtin_ctz) | ||
| 132 | #if __has_builtin(__builtin_ctzl) | ||
| 110 | ADD_SPECIALIZATION(countr_zero, unsigned long, __builtin_ctzl) | 133 | ADD_SPECIALIZATION(countr_zero, unsigned long, __builtin_ctzl) |
| 134 | #endif // __has_builtin(__builtin_ctzl) | ||
| 135 | #if __has_builtin(__builtin_ctzll) | ||
| 111 | ADD_SPECIALIZATION(countr_zero, unsigned long long, __builtin_ctzll) | 136 | ADD_SPECIALIZATION(countr_zero, unsigned long long, __builtin_ctzll) |
| 137 | #endif // __has_builtin(__builtin_ctzll) | ||
| 112 | #endif // __has_builtin(__builtin_ctzg) | 138 | #endif // __has_builtin(__builtin_ctzg) |
| 113 | 139 | ||
| 114 | /// Count number of 0's from the most significant bit to the least | 140 | /// Count number of 0's from the most significant bit to the least |
| ... | @@ -144,10 +170,16 @@ countl_zero(T value) { | ... | @@ -144,10 +170,16 @@ countl_zero(T value) { |
| 144 | } | 170 | } |
| 145 | #if __has_builtin(__builtin_clzs) | 171 | #if __has_builtin(__builtin_clzs) |
| 146 | ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs) | 172 | ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs) |
| 147 | #endif | 173 | #endif // __has_builtin(__builtin_clzs) |
| 174 | #if __has_builtin(__builtin_clz) | ||
| 148 | ADD_SPECIALIZATION(countl_zero, unsigned int, __builtin_clz) | 175 | ADD_SPECIALIZATION(countl_zero, unsigned int, __builtin_clz) |
| 176 | #endif // __has_builtin(__builtin_clz) | ||
| 177 | #if __has_builtin(__builtin_clzl) | ||
| 149 | ADD_SPECIALIZATION(countl_zero, unsigned long, __builtin_clzl) | 178 | ADD_SPECIALIZATION(countl_zero, unsigned long, __builtin_clzl) |
| 179 | #endif // __has_builtin(__builtin_clzl) | ||
| 180 | #if __has_builtin(__builtin_clzll) | ||
| 150 | ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll) | 181 | ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll) |
| 182 | #endif // __has_builtin(__builtin_clzll) | ||
| 151 | #endif // __has_builtin(__builtin_clzg) | 183 | #endif // __has_builtin(__builtin_clzg) |
| 152 | 184 | ||
| 153 | #undef ADD_SPECIALIZATION | 185 | #undef ADD_SPECIALIZATION |
| ... | @@ -284,11 +316,17 @@ popcount(T value) { | ... | @@ -284,11 +316,17 @@ popcount(T value) { |
| 284 | [[nodiscard]] LIBC_INLINE constexpr int popcount<TYPE>(TYPE value) { \ | 316 | [[nodiscard]] LIBC_INLINE constexpr int popcount<TYPE>(TYPE value) { \ |
| 285 | return BUILTIN(value); \ | 317 | return BUILTIN(value); \ |
| 286 | } | 318 | } |
| 319 | #if __has_builtin(__builtin_popcount) | ||
| 287 | ADD_SPECIALIZATION(unsigned char, __builtin_popcount) | 320 | ADD_SPECIALIZATION(unsigned char, __builtin_popcount) |
| 288 | ADD_SPECIALIZATION(unsigned short, __builtin_popcount) | 321 | ADD_SPECIALIZATION(unsigned short, __builtin_popcount) |
| 289 | ADD_SPECIALIZATION(unsigned, __builtin_popcount) | 322 | ADD_SPECIALIZATION(unsigned, __builtin_popcount) |
| 323 | #endif // __builtin_popcount | ||
| 324 | #if __has_builtin(__builtin_popcountl) | ||
| 290 | ADD_SPECIALIZATION(unsigned long, __builtin_popcountl) | 325 | ADD_SPECIALIZATION(unsigned long, __builtin_popcountl) |
| 326 | #endif // __builtin_popcountl | ||
| 327 | #if __has_builtin(__builtin_popcountll) | ||
| 291 | ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) | 328 | ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) |
| 329 | #endif // __builtin_popcountll | ||
| 292 | #endif // __builtin_popcountg | 330 | #endif // __builtin_popcountg |
| 293 | #undef ADD_SPECIALIZATION | 331 | #undef ADD_SPECIALIZATION |
| 294 | 332 |
lib/libcxx/libc/src/__support/CPP/type_traits/is_complex.h+7| ... | @@ -13,12 +13,17 @@ | ... | @@ -13,12 +13,17 @@ |
| 13 | #include "src/__support/macros/attributes.h" | 13 | #include "src/__support/macros/attributes.h" |
| 14 | #include "src/__support/macros/config.h" | 14 | #include "src/__support/macros/config.h" |
| 15 | // LIBC_TYPES_HAS_CFLOAT16 && LIBC_TYPES_HAS_CFLOAT128 | 15 | // LIBC_TYPES_HAS_CFLOAT16 && LIBC_TYPES_HAS_CFLOAT128 |
| 16 | #include "src/__support/macros/properties/compiler.h" | ||
| 16 | #include "src/__support/macros/properties/complex_types.h" | 17 | #include "src/__support/macros/properties/complex_types.h" |
| 17 | 18 | ||
| 18 | namespace LIBC_NAMESPACE_DECL { | 19 | namespace LIBC_NAMESPACE_DECL { |
| 19 | namespace cpp { | 20 | namespace cpp { |
| 20 | 21 | ||
| 21 | // is_complex | 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 | template <typename T> struct is_complex { | 27 | template <typename T> struct is_complex { |
| 23 | private: | 28 | private: |
| 24 | template <typename Head, typename... Args> | 29 | template <typename Head, typename... Args> |
| ... | @@ -40,6 +45,8 @@ public: | ... | @@ -40,6 +45,8 @@ public: |
| 40 | #endif | 45 | #endif |
| 41 | >(); | 46 | >(); |
| 42 | }; | 47 | }; |
| 48 | #endif // LIBC_COMPILER_IS_MSVC | ||
| 49 | |||
| 43 | template <typename T> | 50 | template <typename T> |
| 44 | LIBC_INLINE_VAR constexpr bool is_complex_v = is_complex<T>::value; | 51 | LIBC_INLINE_VAR constexpr bool is_complex_v = is_complex<T>::value; |
| 45 | template <typename T1, typename T2> | 52 | template <typename T1, typename T2> |
lib/libcxx/libc/src/__support/CPP/type_traits/is_destructible.h+2-1| ... | @@ -15,6 +15,7 @@ | ... | @@ -15,6 +15,7 @@ |
| 15 | #include "src/__support/CPP/type_traits/remove_all_extents.h" | 15 | #include "src/__support/CPP/type_traits/remove_all_extents.h" |
| 16 | #include "src/__support/CPP/type_traits/true_type.h" | 16 | #include "src/__support/CPP/type_traits/true_type.h" |
| 17 | #include "src/__support/CPP/type_traits/type_identity.h" | 17 | #include "src/__support/CPP/type_traits/type_identity.h" |
| 18 | #include "src/__support/CPP/utility/declval.h" | ||
| 18 | #include "src/__support/macros/attributes.h" | 19 | #include "src/__support/macros/attributes.h" |
| 19 | #include "src/__support/macros/config.h" | 20 | #include "src/__support/macros/config.h" |
| 20 | 21 | ||
| ... | @@ -22,7 +23,7 @@ namespace LIBC_NAMESPACE_DECL { | ... | @@ -22,7 +23,7 @@ namespace LIBC_NAMESPACE_DECL { |
| 22 | namespace cpp { | 23 | namespace cpp { |
| 23 | 24 | ||
| 24 | // is_destructible | 25 | // is_destructible |
| 25 | #if __has_builtin(__is_destructible) | 26 | #if __has_builtin(__is_destructible) || defined(LIBC_COMPILER_IS_MSVC) |
| 26 | template <typename T> | 27 | template <typename T> |
| 27 | struct is_destructible : bool_constant<__is_destructible(T)> {}; | 28 | struct is_destructible : bool_constant<__is_destructible(T)> {}; |
| 28 | #else | 29 | #else |
lib/libcxx/libc/src/__support/CPP/type_traits/is_unsigned.h+6| ... | @@ -16,6 +16,8 @@ | ... | @@ -16,6 +16,8 @@ |
| 16 | #include "src/__support/macros/attributes.h" | 16 | #include "src/__support/macros/attributes.h" |
| 17 | #include "src/__support/macros/config.h" | 17 | #include "src/__support/macros/config.h" |
| 18 | 18 | ||
| 19 | #include <stddef.h> | ||
| 20 | |||
| 19 | namespace LIBC_NAMESPACE_DECL { | 21 | namespace LIBC_NAMESPACE_DECL { |
| 20 | namespace cpp { | 22 | namespace cpp { |
| 21 | 23 | ||
| ... | @@ -46,6 +48,10 @@ public: | ... | @@ -46,6 +48,10 @@ public: |
| 46 | LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; } | 48 | LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; } |
| 47 | }; | 49 | }; |
| 48 | #endif // LIBC_COMPILER_HAS_FIXED_POINT | 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 | template <typename T> | 56 | template <typename T> |
| 51 | LIBC_INLINE_VAR constexpr bool is_unsigned_v = is_unsigned<T>::value; | 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,12 +5,15 @@ |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // | 6 | // |
| 7 | //===----------------------------------------------------------------------===// | 7 | //===----------------------------------------------------------------------===// |
| 8 | |||
| 8 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H | 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H |
| 9 | #define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H | 10 | #define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H |
| 10 | 11 | ||
| 11 | #include "src/__support/CPP/type_traits/is_integral.h" | 12 | #include "src/__support/CPP/type_traits/is_integral.h" |
| 12 | #include "src/__support/macros/config.h" | 13 | #include "src/__support/macros/config.h" |
| 13 | 14 | ||
| 15 | #include <stddef.h> | ||
| 16 | |||
| 14 | namespace LIBC_NAMESPACE_DECL { | 17 | namespace LIBC_NAMESPACE_DECL { |
| 15 | namespace cpp { | 18 | namespace cpp { |
| 16 | 19 | ||
| ... | @@ -34,6 +37,13 @@ template <typename T, int N> | ... | @@ -34,6 +37,13 @@ template <typename T, int N> |
| 34 | using make_integer_sequence = | 37 | using make_integer_sequence = |
| 35 | typename detail::make_integer_sequence<T, N - 1>::type; | 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 | } // namespace cpp | 47 | } // namespace cpp |
| 38 | } // namespace LIBC_NAMESPACE_DECL | 48 | } // namespace LIBC_NAMESPACE_DECL |
| 39 | 49 |
lib/libcxx/libc/src/__support/FPUtil/FPBits.h+6-7| ... | @@ -15,6 +15,7 @@ | ... | @@ -15,6 +15,7 @@ |
| 15 | #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H | 15 | #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H |
| 16 | #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H | 16 | #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H |
| 17 | 17 | ||
| 18 | #include "hdr/stdint_proxy.h" | ||
| 18 | #include "src/__support/CPP/bit.h" | 19 | #include "src/__support/CPP/bit.h" |
| 19 | #include "src/__support/CPP/type_traits.h" | 20 | #include "src/__support/CPP/type_traits.h" |
| 20 | #include "src/__support/common.h" | 21 | #include "src/__support/common.h" |
| ... | @@ -26,8 +27,6 @@ | ... | @@ -26,8 +27,6 @@ |
| 26 | #include "src/__support/sign.h" // Sign | 27 | #include "src/__support/sign.h" // Sign |
| 27 | #include "src/__support/uint128.h" | 28 | #include "src/__support/uint128.h" |
| 28 | 29 | ||
| 29 | #include <stdint.h> | ||
| 30 | |||
| 31 | namespace LIBC_NAMESPACE_DECL { | 30 | namespace LIBC_NAMESPACE_DECL { |
| 32 | namespace fputil { | 31 | namespace fputil { |
| 33 | 32 | ||
| ... | @@ -790,16 +789,16 @@ struct FPRep : public FPRepImpl<fp_type, FPRep<fp_type>> { | ... | @@ -790,16 +789,16 @@ struct FPRep : public FPRepImpl<fp_type, FPRep<fp_type>> { |
| 790 | // Returns the FPType corresponding to C++ type T on the host. | 789 | // Returns the FPType corresponding to C++ type T on the host. |
| 791 | template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() { | 790 | template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() { |
| 792 | using UnqualT = cpp::remove_cv_t<T>; | 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 | return FPType::IEEE754_Binary32; | 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 | return FPType::IEEE754_Binary64; | 795 | return FPType::IEEE754_Binary64; |
| 797 | else if constexpr (cpp::is_same_v<UnqualT, long double>) { | 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 | return FPType::IEEE754_Binary64; | 798 | return FPType::IEEE754_Binary64; |
| 800 | else if constexpr (__LDBL_MANT_DIG__ == 64) | 799 | else if constexpr (LDBL_MANT_DIG == 64) |
| 801 | return FPType::X86_Binary80; | 800 | return FPType::X86_Binary80; |
| 802 | else if constexpr (__LDBL_MANT_DIG__ == 113) | 801 | else if constexpr (LDBL_MANT_DIG == 113) |
| 803 | return FPType::IEEE754_Binary128; | 802 | return FPType::IEEE754_Binary128; |
| 804 | } | 803 | } |
| 805 | #if defined(LIBC_TYPES_HAS_FLOAT16) | 804 | #if defined(LIBC_TYPES_HAS_FLOAT16) |
lib/libcxx/libc/src/__support/FPUtil/rounding_mode.h+50-4| ... | @@ -10,18 +10,21 @@ | ... | @@ -10,18 +10,21 @@ |
| 10 | #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_ROUNDING_MODE_H | 10 | #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_ROUNDING_MODE_H |
| 11 | 11 | ||
| 12 | #include "hdr/fenv_macros.h" | 12 | #include "hdr/fenv_macros.h" |
| 13 | #include "src/__support/CPP/type_traits.h" // is_constant_evaluated | ||
| 13 | #include "src/__support/macros/attributes.h" // LIBC_INLINE | 14 | #include "src/__support/macros/attributes.h" // LIBC_INLINE |
| 14 | #include "src/__support/macros/config.h" | 15 | #include "src/__support/macros/config.h" |
| 15 | 16 | ||
| 16 | namespace LIBC_NAMESPACE_DECL { | 17 | namespace LIBC_NAMESPACE_DECL { |
| 17 | namespace fputil { | 18 | namespace fputil { |
| 18 | 19 | ||
| 20 | namespace generic { | ||
| 21 | |||
| 19 | // Quick free-standing test whether fegetround() == FE_UPWARD. | 22 | // Quick free-standing test whether fegetround() == FE_UPWARD. |
| 20 | // Using the following observation: | 23 | // Using the following observation: |
| 21 | // 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO | 24 | // 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO |
| 22 | // = 0x1.000002f for FE_UPWARD. | 25 | // = 0x1.000002f for FE_UPWARD. |
| 23 | LIBC_INLINE bool fenv_is_round_up() { | 26 | LIBC_INLINE bool fenv_is_round_up() { |
| 24 | volatile float x = 0x1.0p-25f; | 27 | static volatile float x = 0x1.0p-25f; |
| 25 | return (1.0f + x != 1.0f); | 28 | return (1.0f + x != 1.0f); |
| 26 | } | 29 | } |
| 27 | 30 | ||
| ... | @@ -30,7 +33,7 @@ LIBC_INLINE bool fenv_is_round_up() { | ... | @@ -30,7 +33,7 @@ LIBC_INLINE bool fenv_is_round_up() { |
| 30 | // -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO | 33 | // -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO |
| 31 | // = -0x1.000002f for FE_DOWNWARD. | 34 | // = -0x1.000002f for FE_DOWNWARD. |
| 32 | LIBC_INLINE bool fenv_is_round_down() { | 35 | LIBC_INLINE bool fenv_is_round_down() { |
| 33 | volatile float x = 0x1.0p-25f; | 36 | static volatile float x = 0x1.0p-25f; |
| 34 | return (-1.0f - x != -1.0f); | 37 | return (-1.0f - x != -1.0f); |
| 35 | } | 38 | } |
| 36 | 39 | ||
| ... | @@ -42,8 +45,8 @@ LIBC_INLINE bool fenv_is_round_down() { | ... | @@ -42,8 +45,8 @@ LIBC_INLINE bool fenv_is_round_down() { |
| 42 | // = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO | 45 | // = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO |
| 43 | LIBC_INLINE bool fenv_is_round_to_nearest() { | 46 | LIBC_INLINE bool fenv_is_round_to_nearest() { |
| 44 | static volatile float x = 0x1.0p-24f; | 47 | static volatile float x = 0x1.0p-24f; |
| 45 | float y = x; | 48 | float y = 1.5f + x; |
| 46 | return (1.5f + y == 1.5f - y); | 49 | return (y == 1.5f - x); |
| 47 | } | 50 | } |
| 48 | 51 | ||
| 49 | // Quick free-standing test whether fegetround() == FE_TOWARDZERO. | 52 | // Quick free-standing test whether fegetround() == FE_TOWARDZERO. |
| ... | @@ -75,6 +78,49 @@ LIBC_INLINE int quick_get_round() { | ... | @@ -75,6 +78,49 @@ LIBC_INLINE int quick_get_round() { |
| 75 | return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD; | 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 | } // namespace fputil | 124 | } // namespace fputil |
| 79 | } // namespace LIBC_NAMESPACE_DECL | 125 | } // namespace LIBC_NAMESPACE_DECL |
| 80 | 126 |
lib/libcxx/libc/src/__support/big_int.h+14-14| ... | @@ -9,6 +9,7 @@ | ... | @@ -9,6 +9,7 @@ |
| 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_BIG_INT_H | 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_BIG_INT_H |
| 10 | #define LLVM_LIBC_SRC___SUPPORT_BIG_INT_H | 10 | #define LLVM_LIBC_SRC___SUPPORT_BIG_INT_H |
| 11 | 11 | ||
| 12 | #include "hdr/stdint_proxy.h" | ||
| 12 | #include "src/__support/CPP/array.h" | 13 | #include "src/__support/CPP/array.h" |
| 13 | #include "src/__support/CPP/bit.h" // countl_zero | 14 | #include "src/__support/CPP/bit.h" // countl_zero |
| 14 | #include "src/__support/CPP/limits.h" | 15 | #include "src/__support/CPP/limits.h" |
| ... | @@ -23,7 +24,6 @@ | ... | @@ -23,7 +24,6 @@ |
| 23 | #include "src/__support/number_pair.h" | 24 | #include "src/__support/number_pair.h" |
| 24 | 25 | ||
| 25 | #include <stddef.h> // For size_t | 26 | #include <stddef.h> // For size_t |
| 26 | #include <stdint.h> | ||
| 27 | 27 | ||
| 28 | namespace LIBC_NAMESPACE_DECL { | 28 | namespace LIBC_NAMESPACE_DECL { |
| 29 | 29 | ||
| ... | @@ -95,10 +95,10 @@ LIBC_INLINE constexpr DoubleWide<word> mul2(word a, word b) { | ... | @@ -95,10 +95,10 @@ LIBC_INLINE constexpr DoubleWide<word> mul2(word a, word b) { |
| 95 | #endif | 95 | #endif |
| 96 | else { | 96 | else { |
| 97 | using half_word = half_width_t<word>; | 97 | using half_word = half_width_t<word>; |
| 98 | const auto shiftl = [](word value) -> word { | 98 | constexpr auto shiftl = [](word value) -> word { |
| 99 | return value << cpp::numeric_limits<half_word>::digits; | 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 | return value >> cpp::numeric_limits<half_word>::digits; | 102 | return value >> cpp::numeric_limits<half_word>::digits; |
| 103 | }; | 103 | }; |
| 104 | // Here we do a one digit multiplication where 'a' and 'b' are of type | 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,19 +111,19 @@ LIBC_INLINE constexpr DoubleWide<word> mul2(word a, word b) { |
| 111 | // c result | 111 | // c result |
| 112 | // We convert 'lo' and 'hi' from 'half_word' to 'word' so multiplication | 112 | // We convert 'lo' and 'hi' from 'half_word' to 'word' so multiplication |
| 113 | // doesn't overflow. | 113 | // doesn't overflow. |
| 114 | const word a_lo = lo(a); | 114 | word a_lo = lo(a); |
| 115 | const word b_lo = lo(b); | 115 | word b_lo = lo(b); |
| 116 | const word a_hi = hi(a); | 116 | word a_hi = hi(a); |
| 117 | const word b_hi = hi(b); | 117 | word b_hi = hi(b); |
| 118 | const word step1 = b_lo * a_lo; // no overflow; | 118 | word step1 = b_lo * a_lo; // no overflow; |
| 119 | const word step2 = b_lo * a_hi; // no overflow; | 119 | word step2 = b_lo * a_hi; // no overflow; |
| 120 | const word step3 = b_hi * a_lo; // no overflow; | 120 | word step3 = b_hi * a_lo; // no overflow; |
| 121 | const word step4 = b_hi * a_hi; // no overflow; | 121 | word step4 = b_hi * a_hi; // no overflow; |
| 122 | word lo_digit = step1; | 122 | word lo_digit = step1; |
| 123 | word hi_digit = step4; | 123 | word hi_digit = step4; |
| 124 | const word no_carry = 0; | 124 | word no_carry = 0; |
| 125 | word carry; | 125 | word carry = 0; |
| 126 | word _; // unused carry variable. | 126 | [[maybe_unused]] word _ = 0; // unused carry variable. |
| 127 | lo_digit = add_with_carry<word>(lo_digit, shiftl(step2), no_carry, carry); | 127 | lo_digit = add_with_carry<word>(lo_digit, shiftl(step2), no_carry, carry); |
| 128 | hi_digit = add_with_carry<word>(hi_digit, shiftr(step2), carry, _); | 128 | hi_digit = add_with_carry<word>(hi_digit, shiftr(step2), carry, _); |
| 129 | lo_digit = add_with_carry<word>(lo_digit, shiftl(step3), no_carry, carry); | 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,6 +16,7 @@ |
| 16 | #include "src/__support/macros/attributes.h" | 16 | #include "src/__support/macros/attributes.h" |
| 17 | #include "src/__support/macros/config.h" | 17 | #include "src/__support/macros/config.h" |
| 18 | #include "src/__support/macros/properties/architectures.h" | 18 | #include "src/__support/macros/properties/architectures.h" |
| 19 | #include "src/__support/macros/properties/compiler.h" | ||
| 19 | 20 | ||
| 20 | #ifndef LLVM_LIBC_FUNCTION_ATTR | 21 | #ifndef LLVM_LIBC_FUNCTION_ATTR |
| 21 | #define LLVM_LIBC_FUNCTION_ATTR | 22 | #define LLVM_LIBC_FUNCTION_ATTR |
| ... | @@ -41,12 +42,12 @@ | ... | @@ -41,12 +42,12 @@ |
| 41 | // to cleanly export and alias the C++ symbol `LIBC_NAMESPACE::func` with the C | 42 | // to cleanly export and alias the C++ symbol `LIBC_NAMESPACE::func` with the C |
| 42 | // symbol `func`. So for public packaging on MacOS, we will only export the C | 43 | // symbol `func`. So for public packaging on MacOS, we will only export the C |
| 43 | // symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`. | 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 | #ifndef __APPLE__ | 46 | #ifndef __APPLE__ |
| 46 | #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \ | 47 | #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \ |
| 47 | LLVM_LIBC_ATTR(name) \ | 48 | LLVM_LIBC_ATTR(name) \ |
| 48 | LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \ | 49 | LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \ |
| 49 | __##name##_impl__ __asm__(#name); \ | 50 | __##name##_impl__ asm(#name); \ |
| 50 | decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \ | 51 | decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \ |
| 51 | type __##name##_impl__ arglist | 52 | type __##name##_impl__ arglist |
| 52 | #else // __APPLE__ | 53 | #else // __APPLE__ |
lib/libcxx/libc/src/__support/ctype_utils.h+19-12| ... | @@ -27,7 +27,7 @@ namespace internal { | ... | @@ -27,7 +27,7 @@ namespace internal { |
| 27 | // as well as a way to support non-ASCII character encodings. | 27 | // as well as a way to support non-ASCII character encodings. |
| 28 | 28 | ||
| 29 | // Similarly, do not change these functions to use case ranges. e.g. | 29 | // Similarly, do not change these functions to use case ranges. e.g. |
| 30 | // bool islower(int ch) { | 30 | // bool islower(char ch) { |
| 31 | // switch(ch) { | 31 | // switch(ch) { |
| 32 | // case 'a'...'z': | 32 | // case 'a'...'z': |
| 33 | // return true; | 33 | // return true; |
| ... | @@ -37,7 +37,7 @@ namespace internal { | ... | @@ -37,7 +37,7 @@ namespace internal { |
| 37 | // EBCDIC. Technically we could use some smaller ranges, but that's even harder | 37 | // EBCDIC. Technically we could use some smaller ranges, but that's even harder |
| 38 | // to read. | 38 | // to read. |
| 39 | 39 | ||
| 40 | LIBC_INLINE static constexpr bool islower(int ch) { | 40 | LIBC_INLINE static constexpr bool islower(char ch) { |
| 41 | switch (ch) { | 41 | switch (ch) { |
| 42 | case 'a': | 42 | case 'a': |
| 43 | case 'b': | 43 | case 'b': |
| ... | @@ -71,7 +71,7 @@ LIBC_INLINE static constexpr bool islower(int ch) { | ... | @@ -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 | switch (ch) { | 75 | switch (ch) { |
| 76 | case 'A': | 76 | case 'A': |
| 77 | case 'B': | 77 | case 'B': |
| ... | @@ -105,7 +105,7 @@ LIBC_INLINE static constexpr bool isupper(int ch) { | ... | @@ -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 | switch (ch) { | 109 | switch (ch) { |
| 110 | case '0': | 110 | case '0': |
| 111 | case '1': | 111 | case '1': |
| ... | @@ -123,7 +123,7 @@ LIBC_INLINE static constexpr bool isdigit(int ch) { | ... | @@ -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 | switch (ch) { | 127 | switch (ch) { |
| 128 | case 'A': | 128 | case 'A': |
| 129 | return 'a'; | 129 | return 'a'; |
| ... | @@ -182,7 +182,7 @@ LIBC_INLINE static constexpr int tolower(int ch) { | ... | @@ -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 | switch (ch) { | 186 | switch (ch) { |
| 187 | case 'a': | 187 | case 'a': |
| 188 | return 'A'; | 188 | return 'A'; |
| ... | @@ -241,7 +241,7 @@ LIBC_INLINE static constexpr int toupper(int ch) { | ... | @@ -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 | switch (ch) { | 245 | switch (ch) { |
| 246 | case 'a': | 246 | case 'a': |
| 247 | case 'b': | 247 | case 'b': |
| ... | @@ -301,7 +301,7 @@ LIBC_INLINE static constexpr bool isalpha(int ch) { | ... | @@ -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 | switch (ch) { | 305 | switch (ch) { |
| 306 | case 'a': | 306 | case 'a': |
| 307 | case 'b': | 307 | case 'b': |
| ... | @@ -371,7 +371,7 @@ LIBC_INLINE static constexpr bool isalnum(int ch) { | ... | @@ -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 | switch (ch) { | 375 | switch (ch) { |
| 376 | case '0': | 376 | case '0': |
| 377 | return 0; | 377 | return 0; |
| ... | @@ -476,7 +476,7 @@ LIBC_INLINE static constexpr int b36_char_to_int(int ch) { | ... | @@ -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 | // Can't actually use LIBC_ASSERT here because it depends on integer_to_string | 480 | // Can't actually use LIBC_ASSERT here because it depends on integer_to_string |
| 481 | // which depends on this. | 481 | // which depends on this. |
| 482 | 482 | ||
| ... | @@ -559,7 +559,7 @@ LIBC_INLINE static constexpr int int_to_b36_char(int num) { | ... | @@ -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 | switch (ch) { | 563 | switch (ch) { |
| 564 | case ' ': | 564 | case ' ': |
| 565 | case '\t': | 565 | case '\t': |
| ... | @@ -574,10 +574,17 @@ LIBC_INLINE static constexpr bool isspace(int ch) { | ... | @@ -574,10 +574,17 @@ LIBC_INLINE static constexpr bool isspace(int ch) { |
| 574 | } | 574 | } |
| 575 | 575 | ||
| 576 | // not yet encoding independent. | 576 | // not yet encoding independent. |
| 577 | LIBC_INLINE static constexpr bool isgraph(int ch) { | 577 | LIBC_INLINE static constexpr bool isgraph(char ch) { |
| 578 | return 0x20 < ch && ch < 0x7f; | 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 | } // namespace internal | 588 | } // namespace internal |
| 582 | } // namespace LIBC_NAMESPACE_DECL | 589 | } // namespace LIBC_NAMESPACE_DECL |
| 583 | 590 |
lib/libcxx/libc/src/__support/detailed_powers_of_ten.h+1-2| ... | @@ -9,11 +9,10 @@ | ... | @@ -9,11 +9,10 @@ |
| 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H | 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H |
| 10 | #define LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H | 10 | #define LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H |
| 11 | 11 | ||
| 12 | #include "hdr/stdint_proxy.h" | ||
| 12 | #include "src/__support/common.h" | 13 | #include "src/__support/common.h" |
| 13 | #include "src/__support/macros/config.h" | 14 | #include "src/__support/macros/config.h" |
| 14 | 15 | ||
| 15 | #include <stdint.h> | ||
| 16 | |||
| 17 | namespace LIBC_NAMESPACE_DECL { | 16 | namespace LIBC_NAMESPACE_DECL { |
| 18 | namespace internal { | 17 | namespace internal { |
| 19 | 18 |
lib/libcxx/libc/src/__support/high_precision_decimal.h+33-14| ... | @@ -15,11 +15,12 @@ | ... | @@ -15,11 +15,12 @@ |
| 15 | #ifndef LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H | 15 | #ifndef LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H |
| 16 | #define LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H | 16 | #define LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H |
| 17 | 17 | ||
| 18 | #include "hdr/stdint_proxy.h" | ||
| 18 | #include "src/__support/CPP/limits.h" | 19 | #include "src/__support/CPP/limits.h" |
| 19 | #include "src/__support/ctype_utils.h" | 20 | #include "src/__support/ctype_utils.h" |
| 20 | #include "src/__support/macros/config.h" | 21 | #include "src/__support/macros/config.h" |
| 21 | #include "src/__support/str_to_integer.h" | 22 | #include "src/__support/str_to_integer.h" |
| 22 | #include <stdint.h> | 23 | #include "src/__support/wctype_utils.h" |
| 23 | 24 | ||
| 24 | namespace LIBC_NAMESPACE_DECL { | 25 | namespace LIBC_NAMESPACE_DECL { |
| 25 | namespace internal { | 26 | namespace internal { |
| ... | @@ -38,6 +39,24 @@ struct LShiftTableEntry { | ... | @@ -38,6 +39,24 @@ struct LShiftTableEntry { |
| 38 | // TODO: Figure out where to put this. | 39 | // TODO: Figure out where to put this. |
| 39 | enum class RoundDirection { Up, Down, Nearest }; | 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 | // This is based on the HPD data structure described as part of the Simple | 60 | // This is based on the HPD data structure described as part of the Simple |
| 42 | // Decimal Conversion algorithm by Nigel Tao, described at this link: | 61 | // Decimal Conversion algorithm by Nigel Tao, described at this link: |
| 43 | // https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html | 62 | // https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html |
| ... | @@ -314,9 +333,9 @@ private: | ... | @@ -314,9 +333,9 @@ private: |
| 314 | public: | 333 | public: |
| 315 | // num_string is assumed to be a string of numeric characters. It doesn't | 334 | // num_string is assumed to be a string of numeric characters. It doesn't |
| 316 | // handle leading spaces. | 335 | // handle leading spaces. |
| 317 | LIBC_INLINE | 336 | template <typename CharType> |
| 318 | HighPrecisionDecimal( | 337 | LIBC_INLINE HighPrecisionDecimal( |
| 319 | const char *__restrict num_string, | 338 | const CharType *__restrict num_string, |
| 320 | const size_t num_len = cpp::numeric_limits<size_t>::max()) { | 339 | const size_t num_len = cpp::numeric_limits<size_t>::max()) { |
| 321 | bool saw_dot = false; | 340 | bool saw_dot = false; |
| 322 | size_t num_cur = 0; | 341 | size_t num_cur = 0; |
| ... | @@ -324,25 +343,26 @@ public: | ... | @@ -324,25 +343,26 @@ public: |
| 324 | // them all. | 343 | // them all. |
| 325 | uint32_t total_digits = 0; | 344 | uint32_t total_digits = 0; |
| 326 | while (num_cur < num_len && | 345 | while (num_cur < num_len && |
| 327 | (isdigit(num_string[num_cur]) || num_string[num_cur] == '.')) { | 346 | (isdigit(num_string[num_cur]) || |
| 328 | if (num_string[num_cur] == '.') { | 347 | num_string[num_cur] == constants<CharType>::DECIMAL_POINT)) { |
| 348 | if (num_string[num_cur] == constants<CharType>::DECIMAL_POINT) { | ||
| 329 | if (saw_dot) { | 349 | if (saw_dot) { |
| 330 | break; | 350 | break; |
| 331 | } | 351 | } |
| 332 | this->decimal_point = static_cast<int32_t>(total_digits); | 352 | this->decimal_point = static_cast<int32_t>(total_digits); |
| 333 | saw_dot = true; | 353 | saw_dot = true; |
| 334 | } else { | 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 | --this->decimal_point; | 357 | --this->decimal_point; |
| 337 | ++num_cur; | 358 | ++num_cur; |
| 338 | continue; | 359 | continue; |
| 339 | } | 360 | } |
| 340 | ++total_digits; | 361 | ++total_digits; |
| 341 | if (this->num_digits < MAX_NUM_DIGITS) { | 362 | if (this->num_digits < MAX_NUM_DIGITS) { |
| 342 | this->digits[this->num_digits] = static_cast<uint8_t>( | 363 | this->digits[this->num_digits] = static_cast<uint8_t>(digit); |
| 343 | internal::b36_char_to_int(num_string[num_cur])); | ||
| 344 | ++this->num_digits; | 364 | ++this->num_digits; |
| 345 | } else if (num_string[num_cur] != '0') { | 365 | } else if (digit != 0) { |
| 346 | this->truncated = true; | 366 | this->truncated = true; |
| 347 | } | 367 | } |
| 348 | } | 368 | } |
| ... | @@ -352,11 +372,10 @@ public: | ... | @@ -352,11 +372,10 @@ public: |
| 352 | if (!saw_dot) | 372 | if (!saw_dot) |
| 353 | this->decimal_point = static_cast<int32_t>(total_digits); | 373 | this->decimal_point = static_cast<int32_t>(total_digits); |
| 354 | 374 | ||
| 355 | if (num_cur < num_len && | 375 | if (num_cur < num_len && tolower(num_string[num_cur]) == |
| 356 | (num_string[num_cur] == 'e' || num_string[num_cur] == 'E')) { | 376 | constants<CharType>::DECIMAL_EXPONENT_MARKER) { |
| 357 | ++num_cur; | 377 | ++num_cur; |
| 358 | if (isdigit(num_string[num_cur]) || num_string[num_cur] == '+' || | 378 | if (isdigit(num_string[num_cur]) || get_sign(num_string + num_cur) != 0) { |
| 359 | num_string[num_cur] == '-') { | ||
| 360 | auto result = | 379 | auto result = |
| 361 | strtointeger<int32_t>(num_string + num_cur, 10, num_len - num_cur); | 380 | strtointeger<int32_t>(num_string + num_cur, 10, num_len - num_cur); |
| 362 | if (result.has_error()) { | 381 | if (result.has_error()) { |
lib/libcxx/libc/src/__support/libc_assert.h+2| ... | @@ -14,9 +14,11 @@ | ... | @@ -14,9 +14,11 @@ |
| 14 | // The build is configured to just use the public <assert.h> API | 14 | // The build is configured to just use the public <assert.h> API |
| 15 | // for libc's internal assertions. | 15 | // for libc's internal assertions. |
| 16 | 16 | ||
| 17 | #ifndef LIBC_ASSERT | ||
| 17 | #include <assert.h> | 18 | #include <assert.h> |
| 18 | 19 | ||
| 19 | #define LIBC_ASSERT(COND) assert(COND) | 20 | #define LIBC_ASSERT(COND) assert(COND) |
| 21 | #endif // LIBC_ASSERT | ||
| 20 | 22 | ||
| 21 | #else // Not LIBC_COPT_USE_C_ASSERT | 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,6 +17,7 @@ |
| 17 | #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H | 17 | #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H |
| 18 | #define LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H | 18 | #define LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H |
| 19 | 19 | ||
| 20 | #include "config.h" | ||
| 20 | #include "properties/architectures.h" | 21 | #include "properties/architectures.h" |
| 21 | 22 | ||
| 22 | #ifndef __has_attribute | 23 | #ifndef __has_attribute |
| ... | @@ -28,7 +29,32 @@ | ... | @@ -28,7 +29,32 @@ |
| 28 | #define LIBC_INLINE_ASM __asm__ __volatile__ | 29 | #define LIBC_INLINE_ASM __asm__ __volatile__ |
| 29 | #define LIBC_UNUSED __attribute__((unused)) | 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 | #define LIBC_THREAD_LOCAL | 58 | #define LIBC_THREAD_LOCAL |
| 33 | #else | 59 | #else |
| 34 | #define LIBC_THREAD_LOCAL thread_local | 60 | #define LIBC_THREAD_LOCAL thread_local |
| ... | @@ -48,4 +74,21 @@ | ... | @@ -48,4 +74,21 @@ |
| 48 | #define LIBC_PREFERED_TYPE(TYPE) | 74 | #define LIBC_PREFERED_TYPE(TYPE) |
| 49 | #endif | 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 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H | 94 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H |
lib/libcxx/libc/src/__support/macros/config.h+23| ... | @@ -13,6 +13,13 @@ | ... | @@ -13,6 +13,13 @@ |
| 13 | #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H | 13 | #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H |
| 14 | #define LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H | 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 | // Workaround for compilers that do not support builtin detection. | 23 | // Workaround for compilers that do not support builtin detection. |
| 17 | // FIXME: This is only required for the GPU portion which should be moved. | 24 | // FIXME: This is only required for the GPU portion which should be moved. |
| 18 | #ifndef __has_builtin | 25 | #ifndef __has_builtin |
| ... | @@ -27,6 +34,22 @@ | ... | @@ -27,6 +34,22 @@ |
| 27 | #define LIBC_HAS_FEATURE(f) 0 | 34 | #define LIBC_HAS_FEATURE(f) 0 |
| 28 | #endif | 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 | #ifdef __clang__ | 53 | #ifdef __clang__ |
| 31 | // Declare a LIBC_NAMESPACE with hidden visibility. `namespace | 54 | // Declare a LIBC_NAMESPACE with hidden visibility. `namespace |
| 32 | // LIBC_NAMESPACE_DECL {` should be used around all declarations and definitions | 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,9 +11,8 @@ |
| 11 | 11 | ||
| 12 | #include "src/__support/macros/config.h" | 12 | #include "src/__support/macros/config.h" |
| 13 | #include "src/__support/macros/optimization.h" | 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 | #define LIBC_CRASH_ON_NULLPTR(ptr) \ | 16 | #define LIBC_CRASH_ON_NULLPTR(ptr) \ |
| 18 | do { \ | 17 | do { \ |
| 19 | if (LIBC_UNLIKELY((ptr) == nullptr)) \ | 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,6 +34,9 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) { |
| 34 | #elif defined(LIBC_COMPILER_IS_GCC) | 34 | #elif defined(LIBC_COMPILER_IS_GCC) |
| 35 | #define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0") | 35 | #define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0") |
| 36 | #define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048") | 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 | #else | 40 | #else |
| 38 | #error "Unhandled compiler" | 41 | #error "Unhandled compiler" |
| 39 | #endif | 42 | #endif |
lib/libcxx/libc/src/__support/macros/properties/architectures.h+5-1| ... | @@ -21,7 +21,7 @@ | ... | @@ -21,7 +21,7 @@ |
| 21 | #define LIBC_TARGET_ARCH_IS_GPU | 21 | #define LIBC_TARGET_ARCH_IS_GPU |
| 22 | #endif | 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 | #define LIBC_TARGET_ARCH_IS_VM | 25 | #define LIBC_TARGET_ARCH_IS_VM |
| 26 | #endif | 26 | #endif |
| 27 | 27 | ||
| ... | @@ -41,6 +41,10 @@ | ... | @@ -41,6 +41,10 @@ |
| 41 | #define LIBC_TARGET_ARCH_IS_ARM | 41 | #define LIBC_TARGET_ARCH_IS_ARM |
| 42 | #endif | 42 | #endif |
| 43 | 43 | ||
| 44 | #if defined(__wasm__) | ||
| 45 | #define LIBC_TARGET_ARCH_IS_WASM | ||
| 46 | #endif | ||
| 47 | |||
| 44 | #if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) | 48 | #if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) |
| 45 | #define LIBC_TARGET_ARCH_IS_AARCH64 | 49 | #define LIBC_TARGET_ARCH_IS_AARCH64 |
| 46 | #endif | 50 | #endif |
lib/libcxx/libc/src/__support/macros/properties/compiler.h+8-3| ... | @@ -34,10 +34,15 @@ | ... | @@ -34,10 +34,15 @@ |
| 34 | #define LIBC_COMPILER_GCC_VER (__GNUC__ * 100 + __GNUC_MINOR__) | 34 | #define LIBC_COMPILER_GCC_VER (__GNUC__ * 100 + __GNUC_MINOR__) |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| 37 | #if defined(_MSC_VER) | 37 | #if defined(_MSC_VER) && !defined(__clang__) |
| 38 | #define LIBC_COMPILER_IS_MSC | 38 | #define LIBC_COMPILER_IS_MSVC |
| 39 | // https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros | 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 | #endif | 46 | #endif |
| 42 | 47 | ||
| 43 | #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_COMPILER_H | 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,6 +18,18 @@ |
| 18 | #define LIBC_TARGET_CPU_HAS_FULLFP16 | 18 | #define LIBC_TARGET_CPU_HAS_FULLFP16 |
| 19 | #endif | 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 | #if defined(__SSE2__) | 33 | #if defined(__SSE2__) |
| 22 | #define LIBC_TARGET_CPU_HAS_SSE2 | 34 | #define LIBC_TARGET_CPU_HAS_SSE2 |
| 23 | #define LIBC_TARGET_CPU_HAS_FPU_FLOAT | 35 | #define LIBC_TARGET_CPU_HAS_FPU_FLOAT |
| ... | @@ -59,6 +71,10 @@ | ... | @@ -59,6 +71,10 @@ |
| 59 | #endif // LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE | 71 | #endif // LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE |
| 60 | #endif // __ARM_FP | 72 | #endif // __ARM_FP |
| 61 | 73 | ||
| 74 | #if defined(__ARM_NEON) | ||
| 75 | #define LIBC_TARGET_CPU_HAS_ARM_NEON | ||
| 76 | #endif | ||
| 77 | |||
| 62 | #if defined(__riscv_flen) | 78 | #if defined(__riscv_flen) |
| 63 | // https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc | 79 | // https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc |
| 64 | #if defined(__riscv_zfhmin) | 80 | #if defined(__riscv_zfhmin) |
| ... | @@ -81,7 +97,7 @@ | ... | @@ -81,7 +97,7 @@ |
| 81 | #endif | 97 | #endif |
| 82 | 98 | ||
| 83 | #if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \ | 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 | #define LIBC_TARGET_CPU_HAS_FMA | 101 | #define LIBC_TARGET_CPU_HAS_FMA |
| 86 | // Provide a more fine-grained control of FMA instruction for ARM targets. | 102 | // Provide a more fine-grained control of FMA instruction for ARM targets. |
| 87 | #if defined(LIBC_TARGET_CPU_HAS_FPU_HALF) | 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,7 +10,8 @@ |
| 10 | #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H | 10 | #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H |
| 11 | #define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H | 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 | #include "include/llvm-libc-macros/float16-macros.h" // LIBC_TYPES_HAS_FLOAT16 | 15 | #include "include/llvm-libc-macros/float16-macros.h" // LIBC_TYPES_HAS_FLOAT16 |
| 15 | #include "include/llvm-libc-types/float128.h" // float128 | 16 | #include "include/llvm-libc-types/float128.h" // float128 |
| 16 | #include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL | 17 | #include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL |
| ... | @@ -19,8 +20,6 @@ | ... | @@ -19,8 +20,6 @@ |
| 19 | #include "src/__support/macros/properties/cpu_features.h" | 20 | #include "src/__support/macros/properties/cpu_features.h" |
| 20 | #include "src/__support/macros/properties/os.h" | 21 | #include "src/__support/macros/properties/os.h" |
| 21 | 22 | ||
| 22 | #include <stdint.h> // UINT64_MAX, __SIZEOF_INT128__ | ||
| 23 | |||
| 24 | // 'long double' properties. | 23 | // 'long double' properties. |
| 25 | #if (LDBL_MANT_DIG == 53) | 24 | #if (LDBL_MANT_DIG == 53) |
| 26 | #define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64 | 25 | #define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64 |
lib/libcxx/libc/src/__support/macros/sanitizer.h-10| ... | @@ -23,16 +23,6 @@ | ... | @@ -23,16 +23,6 @@ |
| 23 | #define LIBC_HAS_MEMORY_SANITIZER | 23 | #define LIBC_HAS_MEMORY_SANITIZER |
| 24 | #endif | 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 | #ifdef LIBC_HAS_MEMORY_SANITIZER | 26 | #ifdef LIBC_HAS_MEMORY_SANITIZER |
| 37 | // Only perform MSAN unpoison in non-constexpr context. | 27 | // Only perform MSAN unpoison in non-constexpr context. |
| 38 | #include <sanitizer/msan_interface.h> | 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,7 +25,13 @@ LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> |
| 25 | mask_trailing_ones() { | 25 | mask_trailing_ones() { |
| 26 | constexpr unsigned T_BITS = CHAR_BIT * sizeof(T); | 26 | constexpr unsigned T_BITS = CHAR_BIT * sizeof(T); |
| 27 | static_assert(count <= T_BITS && "Invalid bit index"); | 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 | // Create a bitmask with the count left-most bits set to 1, and all other bits | 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,18 +61,28 @@ mask_leading_zeros() { |
| 55 | // Returns whether 'a + b' overflows, the result is stored in 'res'. | 61 | // Returns whether 'a + b' overflows, the result is stored in 'res'. |
| 56 | template <typename T> | 62 | template <typename T> |
| 57 | [[nodiscard]] LIBC_INLINE constexpr bool add_overflow(T a, T b, T &res) { | 63 | [[nodiscard]] LIBC_INLINE constexpr bool add_overflow(T a, T b, T &res) { |
| 64 | #if __has_builtin(__builtin_add_overflow) | ||
| 58 | return __builtin_add_overflow(a, b, &res); | 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 | // Returns whether 'a - b' overflows, the result is stored in 'res'. | 72 | // Returns whether 'a - b' overflows, the result is stored in 'res'. |
| 62 | template <typename T> | 73 | template <typename T> |
| 63 | [[nodiscard]] LIBC_INLINE constexpr bool sub_overflow(T a, T b, T &res) { | 74 | [[nodiscard]] LIBC_INLINE constexpr bool sub_overflow(T a, T b, T &res) { |
| 75 | #if __has_builtin(__builtin_sub_overflow) | ||
| 64 | return __builtin_sub_overflow(a, b, &res); | 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 | #define RETURN_IF(TYPE, BUILTIN) \ | 83 | #define RETURN_IF(TYPE, BUILTIN) \ |
| 68 | if constexpr (cpp::is_same_v<T, TYPE>) \ | 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 | // Returns the result of 'a + b' taking into account 'carry_in'. | 87 | // Returns the result of 'a + b' taking into account 'carry_in'. |
| 72 | // The carry out is stored in 'carry_out' it not 'nullptr', dropped otherwise. | 88 | // The carry out is stored in 'carry_out' it not 'nullptr', dropped otherwise. |
| ... | @@ -74,7 +90,7 @@ template <typename T> | ... | @@ -74,7 +90,7 @@ template <typename T> |
| 74 | template <typename T> | 90 | template <typename T> |
| 75 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> | 91 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> |
| 76 | add_with_carry(T a, T b, T carry_in, T &carry_out) { | 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 | #if __has_builtin(__builtin_addcb) | 94 | #if __has_builtin(__builtin_addcb) |
| 79 | RETURN_IF(unsigned char, __builtin_addcb) | 95 | RETURN_IF(unsigned char, __builtin_addcb) |
| 80 | #elif __has_builtin(__builtin_addcs) | 96 | #elif __has_builtin(__builtin_addcs) |
| ... | @@ -100,7 +116,7 @@ add_with_carry(T a, T b, T carry_in, T &carry_out) { | ... | @@ -100,7 +116,7 @@ add_with_carry(T a, T b, T carry_in, T &carry_out) { |
| 100 | template <typename T> | 116 | template <typename T> |
| 101 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> | 117 | [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T> |
| 102 | sub_with_borrow(T a, T b, T carry_in, T &carry_out) { | 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 | #if __has_builtin(__builtin_subcb) | 120 | #if __has_builtin(__builtin_subcb) |
| 105 | RETURN_IF(unsigned char, __builtin_subcb) | 121 | RETURN_IF(unsigned char, __builtin_subcb) |
| 106 | #elif __has_builtin(__builtin_subcs) | 122 | #elif __has_builtin(__builtin_subcs) |
lib/libcxx/libc/src/__support/str_to_float.h+98-125| ... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
| 16 | #define LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H | 16 | #define LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H |
| 17 | 17 | ||
| 18 | #include "hdr/errno_macros.h" // For ERANGE | 18 | #include "hdr/errno_macros.h" // For ERANGE |
| 19 | #include "hdr/stdint_proxy.h" | ||
| 19 | #include "src/__support/CPP/bit.h" | 20 | #include "src/__support/CPP/bit.h" |
| 20 | #include "src/__support/CPP/limits.h" | 21 | #include "src/__support/CPP/limits.h" |
| 21 | #include "src/__support/CPP/optional.h" | 22 | #include "src/__support/CPP/optional.h" |
| ... | @@ -32,8 +33,7 @@ | ... | @@ -32,8 +33,7 @@ |
| 32 | #include "src/__support/str_to_integer.h" | 33 | #include "src/__support/str_to_integer.h" |
| 33 | #include "src/__support/str_to_num_result.h" | 34 | #include "src/__support/str_to_num_result.h" |
| 34 | #include "src/__support/uint128.h" | 35 | #include "src/__support/uint128.h" |
| 35 | 36 | #include "src/__support/wctype_utils.h" | |
| 36 | #include <stdint.h> | ||
| 37 | 37 | ||
| 38 | namespace LIBC_NAMESPACE_DECL { | 38 | namespace LIBC_NAMESPACE_DECL { |
| 39 | namespace internal { | 39 | namespace internal { |
| ... | @@ -335,9 +335,9 @@ constexpr int32_t NUM_POWERS_OF_TWO = | ... | @@ -335,9 +335,9 @@ constexpr int32_t NUM_POWERS_OF_TWO = |
| 335 | // the Eisel-Lemire algorithm fails, it's slower but more accurate. It's based | 335 | // the Eisel-Lemire algorithm fails, it's slower but more accurate. It's based |
| 336 | // on the Simple Decimal Conversion algorithm by Nigel Tao, described at this | 336 | // on the Simple Decimal Conversion algorithm by Nigel Tao, described at this |
| 337 | // link: https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html | 337 | // link: https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html |
| 338 | template <class T> | 338 | template <typename T, typename CharType> |
| 339 | LIBC_INLINE FloatConvertReturn<T> simple_decimal_conversion( | 339 | LIBC_INLINE FloatConvertReturn<T> simple_decimal_conversion( |
| 340 | const char *__restrict numStart, | 340 | const CharType *__restrict numStart, |
| 341 | const size_t num_len = cpp::numeric_limits<size_t>::max(), | 341 | const size_t num_len = cpp::numeric_limits<size_t>::max(), |
| 342 | RoundDirection round = RoundDirection::Nearest) { | 342 | RoundDirection round = RoundDirection::Nearest) { |
| 343 | using FPBits = typename fputil::FPBits<T>; | 343 | using FPBits = typename fputil::FPBits<T>; |
| ... | @@ -677,12 +677,11 @@ template <> LIBC_INLINE constexpr int32_t get_lower_bound<double>() { | ... | @@ -677,12 +677,11 @@ template <> LIBC_INLINE constexpr int32_t get_lower_bound<double>() { |
| 677 | // Takes a mantissa and base 10 exponent and converts it into its closest | 677 | // Takes a mantissa and base 10 exponent and converts it into its closest |
| 678 | // floating point type T equivalient. First we try the Eisel-Lemire algorithm, | 678 | // floating point type T equivalient. First we try the Eisel-Lemire algorithm, |
| 679 | // then if that fails then we fall back to a more accurate algorithm for | 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 | 680 | // accuracy. |
| 681 | // and outputExp2. | 681 | template <typename T, typename CharType> |
| 682 | template <class T> | ||
| 683 | LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float( | 682 | LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float( |
| 684 | ExpandedFloat<T> init_num, bool truncated, RoundDirection round, | 683 | ExpandedFloat<T> init_num, bool truncated, RoundDirection round, |
| 685 | const char *__restrict numStart, | 684 | const CharType *__restrict numStart, |
| 686 | const size_t num_len = cpp::numeric_limits<size_t>::max()) { | 685 | const size_t num_len = cpp::numeric_limits<size_t>::max()) { |
| 687 | using FPBits = typename fputil::FPBits<T>; | 686 | using FPBits = typename fputil::FPBits<T>; |
| 688 | using StorageType = typename FPBits::StorageType; | 687 | using StorageType = typename FPBits::StorageType; |
| ... | @@ -861,36 +860,42 @@ LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num, | ... | @@ -861,36 +860,42 @@ LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num, |
| 861 | return output; | 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 | // hexadecimal floating point number. Does not advance the string pointer. | 864 | // hexadecimal floating point number. Does not advance the string pointer. |
| 866 | LIBC_INLINE bool is_float_hex_start(const char *__restrict src, | 865 | template <typename CharType> |
| 867 | const char decimalPoint) { | 866 | LIBC_INLINE static bool is_float_hex_start(const CharType *__restrict src) { |
| 868 | if (!(src[0] == '0' && tolower(src[1]) == 'x')) { | 867 | if (!is_char_or_wchar(src[0], '0', L'0') || |
| 868 | !is_char_or_wchar(tolower(src[1]), 'x', L'x')) { | ||
| 869 | return false; | 869 | return false; |
| 870 | } | 870 | } |
| 871 | size_t first_digit = 2; | 871 | size_t first_digit = 2; |
| 872 | if (src[2] == decimalPoint) { | 872 | if (src[2] == constants<CharType>::DECIMAL_POINT) { |
| 873 | ++first_digit; | 873 | ++first_digit; |
| 874 | } | 874 | } |
| 875 | return isalnum(src[first_digit]) && b36_char_to_int(src[first_digit]) < 16; | 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 | 878 | // Verifies that first prefix_len characters of str, when lowercased, match the |
| 879 | // local decimalPoint. It returns if it suceeded in parsing any digits, and if | 879 | // specified prefix. |
| 880 | // the return value is true then the outputs are pointer to the end of the | 880 | template <typename CharType> |
| 881 | // number, and the mantissa and exponent for the closest float T representation. | 881 | LIBC_INLINE static bool tolower_starts_with(const CharType *str, |
| 882 | // If the return value is false, then it is assumed that there is no number | 882 | size_t prefix_len, |
| 883 | // here. | 883 | const CharType *prefix) { |
| 884 | template <class T> | 884 | for (size_t i = 0; i < prefix_len; ++i) { |
| 885 | LIBC_INLINE StrToNumResult<ExpandedFloat<T>> | 885 | if (tolower(str[i]) != prefix[i]) |
| 886 | decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, | 886 | return false; |
| 887 | RoundDirection round) { | 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 | using FPBits = typename fputil::FPBits<T>; | 895 | using FPBits = typename fputil::FPBits<T>; |
| 889 | using StorageType = typename FPBits::StorageType; | 896 | using StorageType = typename FPBits::StorageType; |
| 890 | 897 | ||
| 891 | constexpr uint32_t BASE = 10; | 898 | constexpr uint32_t BASE = 10; |
| 892 | constexpr char EXPONENT_MARKER = 'e'; | ||
| 893 | |||
| 894 | bool truncated = false; | 899 | bool truncated = false; |
| 895 | bool seen_digit = false; | 900 | bool seen_digit = false; |
| 896 | bool after_decimal = false; | 901 | bool after_decimal = false; |
| ... | @@ -927,7 +932,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, | ... | @@ -927,7 +932,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, |
| 927 | ++index; | 932 | ++index; |
| 928 | continue; | 933 | continue; |
| 929 | } | 934 | } |
| 930 | if (src[index] == DECIMAL_POINT) { | 935 | if (src[index] == constants<CharType>::DECIMAL_POINT) { |
| 931 | if (after_decimal) { | 936 | if (after_decimal) { |
| 932 | break; // this means that src[index] points to a second decimal point, | 937 | break; // this means that src[index] points to a second decimal point, |
| 933 | // ending the number. | 938 | // ending the number. |
| ... | @@ -944,13 +949,10 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, | ... | @@ -944,13 +949,10 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, |
| 944 | return output; | 949 | return output; |
| 945 | 950 | ||
| 946 | // TODO: When adding max length argument, handle the case of a trailing | 951 | // TODO: When adding max length argument, handle the case of a trailing |
| 947 | // EXPONENT MARKER, see scanf for more details. | 952 | // exponent marker, see scanf for more details. |
| 948 | if (tolower(src[index]) == EXPONENT_MARKER) { | 953 | if (tolower(src[index]) == constants<CharType>::DECIMAL_EXPONENT_MARKER) { |
| 949 | bool has_sign = false; | 954 | int sign = get_sign(src + index + 1); |
| 950 | if (src[index + 1] == '+' || src[index + 1] == '-') { | 955 | if (isdigit(src[index + 1 + static_cast<size_t>(sign != 0)])) { |
| 951 | has_sign = true; | ||
| 952 | } | ||
| 953 | if (isdigit(src[index + 1 + static_cast<size_t>(has_sign)])) { | ||
| 954 | ++index; | 956 | ++index; |
| 955 | auto result = strtointeger<int32_t>(src + index, 10); | 957 | auto result = strtointeger<int32_t>(src + index, 10); |
| 956 | if (result.has_error()) | 958 | if (result.has_error()) |
| ... | @@ -986,22 +988,16 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, | ... | @@ -986,22 +988,16 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, |
| 986 | return output; | 988 | return output; |
| 987 | } | 989 | } |
| 988 | 990 | ||
| 989 | // Takes the start of a string representing a hexadecimal float, as well as the | 991 | // Attempts parsing a hexadecimal floating point number at the start of the |
| 990 | // local decimal point. It returns if it suceeded in parsing any digits, and if | 992 | // string. |
| 991 | // the return value is true then the outputs are pointer to the end of the | 993 | template <typename T, typename CharType> |
| 992 | // number, and the mantissa and exponent for the closest float T representation. | 994 | LIBC_INLINE static StrToNumResult<ExpandedFloat<T>> |
| 993 | // If the return value is false, then it is assumed that there is no number | 995 | hexadecimal_string_to_float(const CharType *__restrict src, |
| 994 | // here. | 996 | RoundDirection round) { |
| 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) { | ||
| 999 | using FPBits = typename fputil::FPBits<T>; | 997 | using FPBits = typename fputil::FPBits<T>; |
| 1000 | using StorageType = typename FPBits::StorageType; | 998 | using StorageType = typename FPBits::StorageType; |
| 1001 | 999 | ||
| 1002 | constexpr uint32_t BASE = 16; | 1000 | constexpr uint32_t BASE = 16; |
| 1003 | constexpr char EXPONENT_MARKER = 'p'; | ||
| 1004 | |||
| 1005 | bool truncated = false; | 1001 | bool truncated = false; |
| 1006 | bool seen_digit = false; | 1002 | bool seen_digit = false; |
| 1007 | bool after_decimal = false; | 1003 | bool after_decimal = false; |
| ... | @@ -1039,7 +1035,7 @@ hexadecimal_string_to_float(const char *__restrict src, | ... | @@ -1039,7 +1035,7 @@ hexadecimal_string_to_float(const char *__restrict src, |
| 1039 | ++index; | 1035 | ++index; |
| 1040 | continue; | 1036 | continue; |
| 1041 | } | 1037 | } |
| 1042 | if (src[index] == DECIMAL_POINT) { | 1038 | if (src[index] == constants<CharType>::DECIMAL_POINT) { |
| 1043 | if (after_decimal) { | 1039 | if (after_decimal) { |
| 1044 | break; // this means that src[index] points to a second decimal point, | 1040 | break; // this means that src[index] points to a second decimal point, |
| 1045 | // ending the number. | 1041 | // ending the number. |
| ... | @@ -1058,12 +1054,9 @@ hexadecimal_string_to_float(const char *__restrict src, | ... | @@ -1058,12 +1054,9 @@ hexadecimal_string_to_float(const char *__restrict src, |
| 1058 | // Convert the exponent from having a base of 16 to having a base of 2. | 1054 | // Convert the exponent from having a base of 16 to having a base of 2. |
| 1059 | exponent *= 4; | 1055 | exponent *= 4; |
| 1060 | 1056 | ||
| 1061 | if (tolower(src[index]) == EXPONENT_MARKER) { | 1057 | if (tolower(src[index]) == constants<CharType>::HEX_EXPONENT_MARKER) { |
| 1062 | bool has_sign = false; | 1058 | int sign = get_sign(src + index + 1); |
| 1063 | if (src[index + 1] == '+' || src[index + 1] == '-') { | 1059 | if (isdigit(src[index + 1 + static_cast<size_t>(sign != 0)])) { |
| 1064 | has_sign = true; | ||
| 1065 | } | ||
| 1066 | if (isdigit(src[index + 1 + static_cast<size_t>(has_sign)])) { | ||
| 1067 | ++index; | 1060 | ++index; |
| 1068 | auto result = strtointeger<int32_t>(src + index, 10); | 1061 | auto result = strtointeger<int32_t>(src + index, 10); |
| 1069 | if (result.has_error()) | 1062 | if (result.has_error()) |
| ... | @@ -1099,21 +1092,21 @@ hexadecimal_string_to_float(const char *__restrict src, | ... | @@ -1099,21 +1092,21 @@ hexadecimal_string_to_float(const char *__restrict src, |
| 1099 | return output; | 1092 | return output; |
| 1100 | } | 1093 | } |
| 1101 | 1094 | ||
| 1102 | template <class T> | 1095 | template <typename T, typename CharType> |
| 1103 | LIBC_INLINE typename fputil::FPBits<T>::StorageType | 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 | using FPBits = typename fputil::FPBits<T>; | 1098 | using FPBits = typename fputil::FPBits<T>; |
| 1106 | using StorageType = typename FPBits::StorageType; | 1099 | using StorageType = typename FPBits::StorageType; |
| 1107 | 1100 | ||
| 1108 | StorageType nan_mantissa = 0; | 1101 | StorageType nan_mantissa = 0; |
| 1109 | 1102 | ||
| 1110 | if (ncharseq.data() != nullptr && isdigit(ncharseq[0])) { | 1103 | if (len > 0 && isdigit(str[0])) { |
| 1111 | StrToNumResult<StorageType> strtoint_result = | 1104 | StrToNumResult<StorageType> strtoint_result = |
| 1112 | strtointeger<StorageType>(ncharseq.data(), 0); | 1105 | strtointeger<StorageType>(str, 0, len); |
| 1113 | if (!strtoint_result.has_error()) | 1106 | if (!strtoint_result.has_error()) |
| 1114 | nan_mantissa = strtoint_result.value; | 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 | nan_mantissa = 0; | 1110 | nan_mantissa = 0; |
| 1118 | } | 1111 | } |
| 1119 | 1112 | ||
| ... | @@ -1124,59 +1117,44 @@ nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) { | ... | @@ -1124,59 +1117,44 @@ nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) { |
| 1124 | // is used as the backend for all of the string to float functions. | 1117 | // is used as the backend for all of the string to float functions. |
| 1125 | // TODO: Add src_len member to match strtointeger. | 1118 | // TODO: Add src_len member to match strtointeger. |
| 1126 | // TODO: Next, move from char* and length to string_view | 1119 | // TODO: Next, move from char* and length to string_view |
| 1127 | template <class T> | 1120 | template <typename T, typename CharType> |
| 1128 | LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) { | 1121 | LIBC_INLINE StrToNumResult<T> |
| 1122 | strtofloatingpoint(const CharType *__restrict src) { | ||
| 1129 | using FPBits = typename fputil::FPBits<T>; | 1123 | using FPBits = typename fputil::FPBits<T>; |
| 1130 | using StorageType = typename FPBits::StorageType; | 1124 | using StorageType = typename FPBits::StorageType; |
| 1131 | 1125 | ||
| 1132 | FPBits result = FPBits(); | 1126 | FPBits result = FPBits(); |
| 1133 | bool seen_digit = false; | 1127 | bool seen_digit = false; |
| 1134 | char sign = '+'; | ||
| 1135 | |||
| 1136 | int error = 0; | 1128 | int error = 0; |
| 1137 | 1129 | ||
| 1138 | size_t index = first_non_whitespace(src); | 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] == '-') { | 1135 | if (sign < 0) { |
| 1141 | sign = src[index]; | ||
| 1142 | ++index; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | if (sign == '-') { | ||
| 1146 | result.set_sign(Sign::NEG); | 1136 | result.set_sign(Sign::NEG); |
| 1147 | } | 1137 | } |
| 1148 | 1138 | ||
| 1149 | static constexpr char DECIMAL_POINT = '.'; | 1139 | if (isdigit(src[index]) || |
| 1150 | static const char *inf_string = "infinity"; | 1140 | src[index] == constants<CharType>::DECIMAL_POINT) { // regular number |
| 1151 | static const char *nan_string = "nan"; | ||
| 1152 | |||
| 1153 | if (isdigit(src[index]) || src[index] == DECIMAL_POINT) { // regular number | ||
| 1154 | int base = 10; | 1141 | int base = 10; |
| 1155 | if (is_float_hex_start(src + index, DECIMAL_POINT)) { | 1142 | if (is_float_hex_start(src + index)) { |
| 1156 | base = 16; | 1143 | base = 16; |
| 1157 | index += 2; | 1144 | index += 2; |
| 1158 | seen_digit = true; | 1145 | seen_digit = true; |
| 1159 | } | 1146 | } |
| 1160 | 1147 | ||
| 1161 | RoundDirection round_direction = RoundDirection::Nearest; | 1148 | RoundDirection round_direction = RoundDirection::Nearest; |
| 1162 | |||
| 1163 | switch (fputil::quick_get_round()) { | 1149 | switch (fputil::quick_get_round()) { |
| 1164 | case FE_TONEAREST: | 1150 | case FE_TONEAREST: |
| 1165 | round_direction = RoundDirection::Nearest; | 1151 | round_direction = RoundDirection::Nearest; |
| 1166 | break; | 1152 | break; |
| 1167 | case FE_UPWARD: | 1153 | case FE_UPWARD: |
| 1168 | if (sign == '+') { | 1154 | round_direction = is_positive ? RoundDirection::Up : RoundDirection::Down; |
| 1169 | round_direction = RoundDirection::Up; | ||
| 1170 | } else { | ||
| 1171 | round_direction = RoundDirection::Down; | ||
| 1172 | } | ||
| 1173 | break; | 1155 | break; |
| 1174 | case FE_DOWNWARD: | 1156 | case FE_DOWNWARD: |
| 1175 | if (sign == '+') { | 1157 | round_direction = is_positive ? RoundDirection::Down : RoundDirection::Up; |
| 1176 | round_direction = RoundDirection::Down; | ||
| 1177 | } else { | ||
| 1178 | round_direction = RoundDirection::Up; | ||
| 1179 | } | ||
| 1180 | break; | 1158 | break; |
| 1181 | case FE_TOWARDZERO: | 1159 | case FE_TOWARDZERO: |
| 1182 | round_direction = RoundDirection::Down; | 1160 | round_direction = RoundDirection::Down; |
| ... | @@ -1185,58 +1163,53 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) { | ... | @@ -1185,58 +1163,53 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) { |
| 1185 | 1163 | ||
| 1186 | StrToNumResult<ExpandedFloat<T>> parse_result({0, 0}); | 1164 | StrToNumResult<ExpandedFloat<T>> parse_result({0, 0}); |
| 1187 | if (base == 16) { | 1165 | if (base == 16) { |
| 1188 | parse_result = hexadecimal_string_to_float<T>(src + index, DECIMAL_POINT, | 1166 | parse_result = |
| 1189 | round_direction); | 1167 | hexadecimal_string_to_float<T>(src + index, round_direction); |
| 1190 | } else { // base is 10 | 1168 | } else { // base is 10 |
| 1191 | parse_result = decimal_string_to_float<T>(src + index, DECIMAL_POINT, | 1169 | parse_result = decimal_string_to_float<T>(src + index, round_direction); |
| 1192 | round_direction); | ||
| 1193 | } | 1170 | } |
| 1194 | seen_digit = parse_result.parsed_len != 0; | 1171 | seen_digit = parse_result.parsed_len != 0; |
| 1195 | result.set_mantissa(parse_result.value.mantissa); | 1172 | result.set_mantissa(parse_result.value.mantissa); |
| 1196 | result.set_biased_exponent(parse_result.value.exponent); | 1173 | result.set_biased_exponent(parse_result.value.exponent); |
| 1197 | index += parse_result.parsed_len; | 1174 | index += parse_result.parsed_len; |
| 1198 | error = parse_result.error; | 1175 | error = parse_result.error; |
| 1199 | } else if (tolower(src[index]) == 'n') { // NaN | 1176 | } else if (tolower_starts_with(src + index, 3, |
| 1200 | if (tolower(src[index + 1]) == nan_string[1] && | 1177 | constants<CharType>::NAN_STRING)) { |
| 1201 | tolower(src[index + 2]) == nan_string[2]) { | 1178 | // NAN |
| 1202 | seen_digit = true; | 1179 | seen_digit = true; |
| 1203 | index += 3; | 1180 | index += 3; |
| 1204 | StorageType nan_mantissa = 0; | 1181 | StorageType nan_mantissa = 0; |
| 1205 | // this handles the case of `NaN(n-character-sequence)`, where the | 1182 | // this handles the case of `NaN(n-character-sequence)`, where the |
| 1206 | // n-character-sequence is made of 0 or more letters, numbers, or | 1183 | // n-character-sequence is made of 0 or more letters, numbers, or |
| 1207 | // underscore characters in any order. | 1184 | // underscore characters in any order. |
| 1208 | if (src[index] == '(') { | 1185 | if (is_char_or_wchar(src[index], '(', L'(')) { |
| 1209 | size_t left_paren = index; | 1186 | size_t left_paren = index; |
| 1187 | ++index; | ||
| 1188 | while (isalnum(src[index]) || is_char_or_wchar(src[index], '_', L'_')) | ||
| 1210 | ++index; | 1189 | ++index; |
| 1211 | while (isalnum(src[index]) || src[index] == '_') | 1190 | if (is_char_or_wchar(src[index], ')', L')')) { |
| 1212 | ++index; | 1191 | ++index; |
| 1213 | if (src[index] == ')') { | 1192 | nan_mantissa = nan_mantissa_from_ncharseq<T>(src + (left_paren + 1), |
| 1214 | ++index; | 1193 | index - left_paren - 2); |
| 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; | ||
| 1235 | } else { | 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 | if (!seen_digit) { // If there is nothing to actually parse, then return 0. | 1213 | if (!seen_digit) { // If there is nothing to actually parse, then return 0. |
| 1241 | return {T(0), 0, error}; | 1214 | return {T(0), 0, error}; |
| 1242 | } | 1215 | } |
| ... | @@ -1263,7 +1236,7 @@ template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) { | ... | @@ -1263,7 +1236,7 @@ template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) { |
| 1263 | ++index; | 1236 | ++index; |
| 1264 | 1237 | ||
| 1265 | if (arg[index] == '\0') | 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 | result = FPBits::quiet_nan(Sign::POS, nan_mantissa); | 1241 | result = FPBits::quiet_nan(Sign::POS, nan_mantissa); |
| 1269 | return {result.get_val(), 0, error}; | 1242 | return {result.get_val(), 0, error}; |
lib/libcxx/libc/src/__support/str_to_integer.h+39-27| ... | @@ -25,36 +25,51 @@ | ... | @@ -25,36 +25,51 @@ |
| 25 | #include "src/__support/macros/config.h" | 25 | #include "src/__support/macros/config.h" |
| 26 | #include "src/__support/str_to_num_result.h" | 26 | #include "src/__support/str_to_num_result.h" |
| 27 | #include "src/__support/uint128.h" | 27 | #include "src/__support/uint128.h" |
| 28 | #include "src/__support/wctype_utils.h" | ||
| 28 | 29 | ||
| 29 | namespace LIBC_NAMESPACE_DECL { | 30 | namespace LIBC_NAMESPACE_DECL { |
| 30 | namespace internal { | 31 | namespace internal { |
| 31 | 32 | ||
| 32 | // Returns the idx to the first character in src that is not a whitespace | 33 | // Returns the idx to the first character in src that is not a whitespace |
| 33 | // character (as determined by isspace()) | 34 | // character (as determined by isspace()) |
| 35 | template <typename CharType> | ||
| 34 | LIBC_INLINE size_t | 36 | LIBC_INLINE size_t |
| 35 | first_non_whitespace(const char *__restrict src, | 37 | first_non_whitespace(const CharType *__restrict src, |
| 36 | size_t src_len = cpp::numeric_limits<size_t>::max()) { | 38 | size_t src_len = cpp::numeric_limits<size_t>::max()) { |
| 37 | size_t src_cur = 0; | 39 | size_t src_cur = 0; |
| 38 | while (src_cur < src_len && internal::isspace(src[src_cur])) { | 40 | for (; src_cur < src_len && internal::isspace(src[src_cur]); ++src_cur) |
| 39 | ++src_cur; | 41 | ; |
| 40 | } | ||
| 41 | return src_cur; | 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 | // checks if the next 3 characters of the string pointer are the start of a | 56 | // checks if the next 3 characters of the string pointer are the start of a |
| 45 | // hexadecimal number. Does not advance the string pointer. | 57 | // hexadecimal number. Does not advance the string pointer. |
| 46 | LIBC_INLINE bool | 58 | template <typename CharType> |
| 47 | is_hex_start(const char *__restrict src, | 59 | LIBC_INLINE static bool is_hex_start(const CharType *__restrict src, |
| 48 | size_t src_len = cpp::numeric_limits<size_t>::max()) { | 60 | size_t src_len) { |
| 49 | if (src_len < 3) | 61 | if (src_len < 3) |
| 50 | return false; | 62 | return false; |
| 51 | return *src == '0' && tolower(*(src + 1)) == 'x' && isalnum(*(src + 2)) && | 63 | return is_char_or_wchar(src[0], '0', L'0') && |
| 52 | b36_char_to_int(*(src + 2)) < 16; | 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 | // Takes the address of the string pointer and parses the base from the start of | 68 | // Takes the address of the string pointer and parses the base from the start of |
| 56 | // it. | 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 | // A hexadecimal number is defined as "the prefix 0x or 0X followed by a | 73 | // A hexadecimal number is defined as "the prefix 0x or 0X followed by a |
| 59 | // sequence of the decimal digits and the letters a (or A) through f (or F) | 74 | // sequence of the decimal digits and the letters a (or A) through f (or F) |
| 60 | // with values 10 through 15 respectively." (C standard 6.4.4.1) | 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,8 +78,9 @@ LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) { |
| 63 | // An octal number is defined as "the prefix 0 optionally followed by a | 78 | // An octal number is defined as "the prefix 0 optionally followed by a |
| 64 | // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any | 79 | // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any |
| 65 | // number that starts with 0, including just 0, is an octal number. | 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 | return 8; | 82 | return 8; |
| 83 | } | ||
| 68 | // A decimal number is defined as beginning "with a nonzero digit and | 84 | // A decimal number is defined as beginning "with a nonzero digit and |
| 69 | // consist[ing] of a sequence of decimal digits." (C standard 6.4.4.1) | 85 | // consist[ing] of a sequence of decimal digits." (C standard 6.4.4.1) |
| 70 | return 10; | 86 | return 10; |
| ... | @@ -77,32 +93,27 @@ LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) { | ... | @@ -77,32 +93,27 @@ LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) { |
| 77 | // ----------------------------------------------------------------------------- | 93 | // ----------------------------------------------------------------------------- |
| 78 | // Takes a pointer to a string and the base to convert to. This function is used | 94 | // Takes a pointer to a string and the base to convert to. This function is used |
| 79 | // as the backend for all of the string to int functions. | 95 | // as the backend for all of the string to int functions. |
| 80 | template <class T> | 96 | template <typename T, typename CharType> |
| 81 | LIBC_INLINE StrToNumResult<T> | 97 | LIBC_INLINE StrToNumResult<T> |
| 82 | strtointeger(const char *__restrict src, int base, | 98 | strtointeger(const CharType *__restrict src, int base, |
| 83 | const size_t src_len = cpp::numeric_limits<size_t>::max()) { | 99 | const size_t src_len = cpp::numeric_limits<size_t>::max()) { |
| 84 | using ResultType = make_integral_or_big_int_unsigned_t<T>; | 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 | if (src_len == 0) | 102 | if (src_len == 0) |
| 93 | return {0, 0, 0}; | 103 | return {0, 0, 0}; |
| 94 | 104 | ||
| 95 | if (base < 0 || base == 1 || base > 36) | 105 | if (base < 0 || base == 1 || base > 36) |
| 96 | return {0, 0, EINVAL}; | 106 | return {0, 0, EINVAL}; |
| 97 | 107 | ||
| 98 | src_cur = first_non_whitespace(src, src_len); | 108 | size_t src_cur = first_non_whitespace(src, src_len); |
| 99 | 109 | if (src_cur == src_len) { | |
| 100 | char result_sign = '+'; | 110 | return {0, 0, 0}; |
| 101 | if (src[src_cur] == '+' || src[src_cur] == '-') { | ||
| 102 | result_sign = src[src_cur]; | ||
| 103 | ++src_cur; | ||
| 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 | if (base == 0) | 117 | if (base == 0) |
| 107 | base = infer_base(src + src_cur, src_len - src_cur); | 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,8 +121,6 @@ strtointeger(const char *__restrict src, int base, |
| 110 | src_cur = src_cur + 2; | 121 | src_cur = src_cur + 2; |
| 111 | 122 | ||
| 112 | constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>; | 123 | constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>; |
| 113 | const bool is_positive = (result_sign == '+'); | ||
| 114 | |||
| 115 | ResultType constexpr NEGATIVE_MAX = | 124 | ResultType constexpr NEGATIVE_MAX = |
| 116 | !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1 | 125 | !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1 |
| 117 | : cpp::numeric_limits<T>::max(); | 126 | : cpp::numeric_limits<T>::max(); |
| ... | @@ -120,6 +129,9 @@ strtointeger(const char *__restrict src, int base, | ... | @@ -120,6 +129,9 @@ strtointeger(const char *__restrict src, int base, |
| 120 | ResultType const abs_max_div_by_base = | 129 | ResultType const abs_max_div_by_base = |
| 121 | abs_max / static_cast<ResultType>(base); | 130 | abs_max / static_cast<ResultType>(base); |
| 122 | 131 | ||
| 132 | bool is_number = false; | ||
| 133 | int error_val = 0; | ||
| 134 | ResultType result = 0; | ||
| 123 | while (src_cur < src_len && isalnum(src[src_cur])) { | 135 | while (src_cur < src_len && isalnum(src[src_cur])) { |
| 124 | int cur_digit = b36_char_to_int(src[src_cur]); | 136 | int cur_digit = b36_char_to_int(src[src_cur]); |
| 125 | if (cur_digit >= base) | 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 | ||