authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-08-03 12:46:11+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-05 14:54:30+02:00
loge68a75dabdae364cd50daa11c197ab372149e8a7
tree6531b378f56f2bbdd4c17f1101c131be2a0133f2
parenta585482c352a77d4f4b6cc1ede616adf6db7d7b3
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

llvm-libc: update to LLVM 23


45 files changed, 1206 insertions(+), 458 deletions(-)

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