authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-26 13:43:13+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-26 19:26:16+02:00
logc47c05386eab5982b0fb20aa58ab80e202e97393
treed53510783643e7ed7291fdc8652384e74ce6a303
parent9f2f6aaef519fe37a6936653bbd01b69b1f65a2f

llvm-libc: update to LLVM 22


37 files changed, 1277 insertions(+), 281 deletions(-)

lib/libcxx/libc/hdr/errno_macros.h+3-1
......@@ -15,7 +15,9 @@
1515#include <linux/errno.h>
1616
1717#include "include/llvm-libc-macros/error-number-macros.h"
18#else // __linux__
18#elif defined(__APPLE__)
19#include <sys/errno.h>
20#else // __APPLE__
1921#include "include/llvm-libc-macros/generic-error-number-macros.h"
2022#endif
2123
lib/libcxx/libc/hdr/stdint_proxy.h created+18
......@@ -0,0 +1,18 @@
1//===-- stdint.h ----------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_HDR_STDINT_PROXY_H
10#define LLVM_LIBC_HDR_STDINT_PROXY_H
11
12// This target is to make sure we have correct build order in full build mode,
13// that is `libc.include.stdint` is added to the dependency of all targets
14// that use <stdint.h> header.
15
16#include <stdint.h>
17
18#endif // LLVM_LIBC_HDR_STDINT_PROXY_H
lib/libcxx/libc/hdr/types/wchar_t.h created+23
......@@ -0,0 +1,23 @@
1//===-- Definition of wchar_t.h -------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_LIBC_HDR_TYPES_WCHAR_T_H
11#define LLVM_LIBC_HDR_TYPES_WCHAR_T_H
12
13#ifdef LIBC_FULL_BUILD
14
15#include "include/llvm-libc-types/wchar_t.h"
16
17#else // overlay mode
18
19#include "hdr/wchar_overlay.h"
20
21#endif // LLVM_LIBC_FULL_BUILD
22
23#endif // LLVM_LIBC_HDR_TYPES_WCHAR_T_H
lib/libcxx/libc/hdr/wchar_overlay.h created+69
......@@ -0,0 +1,69 @@
1//===-- Including wchar.h in overlay mode ---------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_HDR_WCHAR_OVERLAY_H
10#define LLVM_LIBC_HDR_WCHAR_OVERLAY_H
11
12#ifdef LIBC_FULL_BUILD
13#error "This header should only be included in overlay mode"
14#endif
15
16// Overlay mode
17
18// glibc <wchar.h> header might provide extern inline definitions for few
19// functions, causing external alias errors. They are guarded by
20// `__USE_EXTERN_INLINES` macro. We temporarily disable `__USE_EXTERN_INLINES`
21// macro by defining `__NO_INLINE__` before including <wchar.h>.
22// And the same with `__USE_FORTIFY_LEVEL`, which will be temporarily disabled
23// with `_FORTIFY_SOURCE`.
24
25#ifdef _FORTIFY_SOURCE
26#define LIBC_OLD_FORTIFY_SOURCE _FORTIFY_SOURCE
27#undef _FORTIFY_SOURCE
28#endif
29
30#ifndef __NO_INLINE__
31#define __NO_INLINE__ 1
32#define LIBC_SET_NO_INLINE
33#endif
34
35#ifdef __USE_EXTERN_INLINES
36#define LIBC_OLD_USE_EXTERN_INLINES
37#undef __USE_EXTERN_INLINES
38#endif
39
40#ifdef __USE_FORTIFY_LEVEL
41#define LIBC_OLD_USE_FORTIFY_LEVEL __USE_FORTIFY_LEVEL
42#undef __USE_FORTIFY_LEVEL
43#define __USE_FORTIFY_LEVEL 0
44#endif
45
46#include <wchar.h>
47
48#ifdef LIBC_OLD_FORTIFY_SOURCE
49#define _FORTIFY_SOURCE LIBC_OLD_FORTIFY_SOURCE
50#undef LIBC_OLD_FORTIFY_SOURCE
51#endif
52
53#ifdef LIBC_SET_NO_INLINE
54#undef __NO_INLINE__
55#undef LIBC_SET_NO_INLINE
56#endif
57
58#ifdef LIBC_OLD_USE_FORTIFY_LEVEL
59#undef __USE_FORTIFY_LEVEL
60#define __USE_FORTIFY_LEVEL LIBC_OLD_USE_FORTIFY_LEVEL
61#undef LIBC_OLD_USE_FORTIFY_LEVEL
62#endif
63
64#ifdef LIBC_OLD_USE_EXTERN_INLINES
65#define __USE_EXTERN_INLINES
66#undef LIBC_OLD_USE_EXTERN_INLINES
67#endif
68
69#endif // LLVM_LIBC_HDR_WCHAR_OVERLAY_H
lib/libcxx/libc/include/llvm-libc-macros/cfloat128-macros.h created+41
......@@ -0,0 +1,41 @@
1//===-- Detection of _Complex _Float128 compiler builtin type -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_MACROS_CFLOAT128_MACROS_H
10#define LLVM_LIBC_MACROS_CFLOAT128_MACROS_H
11
12#include "float-macros.h" // LDBL_MANT_DIG
13
14// Currently, the complex variant of C23 `_Float128` type is only defined as a
15// built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For
16// clang, the complex variant of `__float128` is defined instead, and only on
17// x86-64 targets for clang 11 or later.
18//
19// TODO: Update the complex variant of C23 `_Float128` type detection again when
20// clang supports it.
21#ifdef __clang__
22#if (__clang_major__ >= 11) && \
23 (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
24// Use _Complex __float128 type. clang uses __SIZEOF_FLOAT128__ or __FLOAT128__
25// macro to notify the availability of __float128 type:
26// https://reviews.llvm.org/D15120
27#define LIBC_TYPES_HAS_CFLOAT128
28#endif
29#elif defined(__GNUC__)
30#if (defined(__STDC_IEC_60559_COMPLEX__) || defined(__SIZEOF_FLOAT128__)) && \
31 (__GNUC__ >= 13 || (!defined(__cplusplus)))
32#define LIBC_TYPES_HAS_CFLOAT128
33#endif
34#endif
35
36#if !defined(LIBC_TYPES_HAS_CFLOAT128) && (LDBL_MANT_DIG == 113)
37#define LIBC_TYPES_HAS_CFLOAT128
38#define LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE
39#endif
40
41#endif // LLVM_LIBC_MACROS_CFLOAT128_MACROS_H
lib/libcxx/libc/include/llvm-libc-macros/cfloat16-macros.h created+20
......@@ -0,0 +1,20 @@
1//===-- Detection of _Complex _Float16 compiler builtin type --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_MACROS_CFLOAT16_MACROS_H
10#define LLVM_LIBC_MACROS_CFLOAT16_MACROS_H
11
12#if defined(__FLT16_MANT_DIG__) && \
13 (!defined(__GNUC__) || __GNUC__ >= 13 || \
14 (defined(__clang__) && __clang_major__ >= 14)) && \
15 !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \
16 !defined(_WIN32)
17#define LIBC_TYPES_HAS_CFLOAT16
18#endif
19
20#endif // LLVM_LIBC_MACROS_CFLOAT16_MACROS_H
lib/libcxx/libc/include/llvm-libc-macros/wchar-macros.h created+18
......@@ -0,0 +1,18 @@
1//===-- Macros defined in wchar.h header file -----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_MACROS_WCHAR_MACROS_H
10#define LLVM_LIBC_MACROS_WCHAR_MACROS_H
11
12#include "../llvm-libc-types/wint_t.h"
13
14#ifndef WEOF
15#define WEOF ((wint_t)(0xffffffffu))
16#endif
17
18#endif // LLVM_LIBC_MACROS_WCHAR_MACROS_H
lib/libcxx/libc/include/llvm-libc-types/cfloat128.h+11-28
......@@ -9,36 +9,19 @@
99#ifndef LLVM_LIBC_TYPES_CFLOAT128_H
1010#define LLVM_LIBC_TYPES_CFLOAT128_H
1111
12#include "../llvm-libc-macros/float-macros.h" // LDBL_MANT_DIG
12#include "../llvm-libc-macros/cfloat128-macros.h"
1313
14// Currently, the complex variant of C23 `_Float128` type is only defined as a
15// built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For
16// clang, the complex variant of `__float128` is defined instead, and only on
17// x86-64 targets for clang 11 or later.
18//
19// TODO: Update the complex variant of C23 `_Float128` type detection again when
20// clang supports it.
21#ifdef __clang__
22#if (__clang_major__ >= 11) && \
23 (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
24// Use _Complex __float128 type. clang uses __SIZEOF_FLOAT128__ or __FLOAT128__
25// macro to notify the availability of __float128 type:
26// https://reviews.llvm.org/D15120
27#define LIBC_TYPES_HAS_CFLOAT128
14#ifdef LIBC_TYPES_HAS_CFLOAT128
15#ifndef LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE
16#if defined(__GNUC__) && !defined(__clang__)
17// Remove the workaround when https://gcc.gnu.org/PR32187 gets fixed.
18typedef __typeof__(_Complex __float128) cfloat128;
19#else // ^^^ workaround / no workaround vvv
2820typedef _Complex __float128 cfloat128;
29#endif
30#elif defined(__GNUC__)
31#if (defined(__STDC_IEC_60559_COMPLEX__) || defined(__SIZEOF_FLOAT128__)) && \
32 (__GNUC__ >= 13 || (!defined(__cplusplus)))
33#define LIBC_TYPES_HAS_CFLOAT128
34typedef _Complex _Float128 cfloat128;
35#endif
36#endif
37
38#if !defined(LIBC_TYPES_HAS_CFLOAT128) && (LDBL_MANT_DIG == 113)
39#define LIBC_TYPES_HAS_CFLOAT128
40#define LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE
21#endif // ^^^ no workaround ^^^
22#else
4123typedef _Complex long double cfloat128;
42#endif
24#endif // LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE
25#endif // LIBC_TYPES_HAS_CFLOAT128
4326
4427#endif // LLVM_LIBC_TYPES_CFLOAT128_H
lib/libcxx/libc/include/llvm-libc-types/cfloat16.h+4-7
......@@ -9,13 +9,10 @@
99#ifndef LLVM_LIBC_TYPES_CFLOAT16_H
1010#define LLVM_LIBC_TYPES_CFLOAT16_H
1111
12#if defined(__FLT16_MANT_DIG__) && \
13 (!defined(__GNUC__) || __GNUC__ >= 13 || \
14 (defined(__clang__) && __clang_major__ >= 14)) && \
15 !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \
16 !defined(_WIN32)
17#define LIBC_TYPES_HAS_CFLOAT16
12#include "../llvm-libc-macros/cfloat16-macros.h"
13
14#ifdef LIBC_TYPES_HAS_CFLOAT16
1815typedef _Complex _Float16 cfloat16;
19#endif
16#endif // LIBC_TYPES_HAS_CFLOAT16
2017
2118#endif // LLVM_LIBC_TYPES_CFLOAT16_H
lib/libcxx/libc/include/llvm-libc-types/wint_t.h created+14
......@@ -0,0 +1,14 @@
1//===-- Definition of wint_t types ----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_TYPES_WINT_T_H
10#define LLVM_LIBC_TYPES_WINT_T_H
11
12typedef __WINT_TYPE__ wint_t;
13
14#endif // LLVM_LIBC_TYPES_WINT_T_H
lib/libcxx/libc/shared/libc_common.h+5
......@@ -19,6 +19,11 @@
1919#define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM_INLINE
2020#endif // LIBC_ERRNO_MODE
2121
22// Use system fenv functions in math implementations.
23#ifndef LIBC_MATH_USE_SYSTEM_FENV
24#define LIBC_MATH_USE_SYSTEM_FENV
25#endif // LIBC_MATH_USE_SYSTEM_FENV
26
2227#ifndef LIBC_NAMESPACE
2328#define LIBC_NAMESPACE __llvm_libc
2429#endif // LIBC_NAMESPACE
lib/libcxx/libc/src/__support/CPP/bit.h+50-12
......@@ -11,14 +11,14 @@
1111#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
1212#define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
1313
14#include "hdr/stdint_proxy.h"
1415#include "src/__support/CPP/limits.h" // numeric_limits
1516#include "src/__support/CPP/type_traits.h"
1617#include "src/__support/macros/attributes.h"
1718#include "src/__support/macros/config.h"
19#include "src/__support/macros/properties/compiler.h"
1820#include "src/__support/macros/sanitizer.h"
1921
20#include <stdint.h>
21
2222namespace LIBC_NAMESPACE_DECL {
2323namespace cpp {
2424
......@@ -26,6 +26,16 @@ namespace cpp {
2626#define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE
2727#endif
2828
29template <unsigned N>
30LIBC_INLINE static void inline_copy(const char *from, char *to) {
31#if __has_builtin(__builtin_memcpy_inline)
32 __builtin_memcpy_inline(to, from, N);
33#else
34 for (unsigned i = 0; i < N; ++i)
35 to[i] = from[i];
36#endif // __has_builtin(__builtin_memcpy_inline)
37}
38
2939// This implementation of bit_cast requires trivially-constructible To, to avoid
3040// UB in the implementation.
3141template <typename To, typename From>
......@@ -37,22 +47,32 @@ LIBC_INLINE constexpr cpp::enable_if_t<
3747 To>
3848bit_cast(const From &from) {
3949 MSAN_UNPOISON(&from, sizeof(From));
40#if __has_builtin(__builtin_bit_cast)
50#if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC)
4151 return __builtin_bit_cast(To, from);
4252#else
43 To to;
53 To to{};
4454 char *dst = reinterpret_cast<char *>(&to);
4555 const char *src = reinterpret_cast<const char *>(&from);
46#if __has_builtin(__builtin_memcpy_inline)
47 __builtin_memcpy_inline(dst, src, sizeof(To));
48#else
49 for (unsigned i = 0; i < sizeof(To); ++i)
50 dst[i] = src[i];
51#endif // __has_builtin(__builtin_memcpy_inline)
56 inline_copy<sizeof(From)>(src, dst);
5257 return to;
5358#endif // __has_builtin(__builtin_bit_cast)
5459}
5560
61// The following simple bit copy from a smaller type to maybe-larger type.
62template <typename To, typename From>
63LIBC_INLINE constexpr cpp::enable_if_t<
64 (sizeof(To) >= sizeof(From)) &&
65 cpp::is_trivially_constructible<To>::value &&
66 cpp::is_trivially_copyable<To>::value &&
67 cpp::is_trivially_copyable<From>::value,
68 void>
69bit_copy(const From &from, To &to) {
70 MSAN_UNPOISON(&from, sizeof(From));
71 char *dst = reinterpret_cast<char *>(&to);
72 const char *src = reinterpret_cast<const char *>(&from);
73 inline_copy<sizeof(From)>(src, dst);
74}
75
5676template <typename T>
5777[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>,
5878 bool>
......@@ -105,10 +125,16 @@ countr_zero(T value) {
105125}
106126#if __has_builtin(__builtin_ctzs)
107127ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs)
108#endif
128#endif // __has_builtin(__builtin_ctzs)
129#if __has_builtin(__builtin_ctz)
109130ADD_SPECIALIZATION(countr_zero, unsigned int, __builtin_ctz)
131#endif // __has_builtin(__builtin_ctz)
132#if __has_builtin(__builtin_ctzl)
110133ADD_SPECIALIZATION(countr_zero, unsigned long, __builtin_ctzl)
134#endif // __has_builtin(__builtin_ctzl)
135#if __has_builtin(__builtin_ctzll)
111136ADD_SPECIALIZATION(countr_zero, unsigned long long, __builtin_ctzll)
137#endif // __has_builtin(__builtin_ctzll)
112138#endif // __has_builtin(__builtin_ctzg)
113139
114140/// Count number of 0's from the most significant bit to the least
......@@ -144,10 +170,16 @@ countl_zero(T value) {
144170}
145171#if __has_builtin(__builtin_clzs)
146172ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs)
147#endif
173#endif // __has_builtin(__builtin_clzs)
174#if __has_builtin(__builtin_clz)
148175ADD_SPECIALIZATION(countl_zero, unsigned int, __builtin_clz)
176#endif // __has_builtin(__builtin_clz)
177#if __has_builtin(__builtin_clzl)
149178ADD_SPECIALIZATION(countl_zero, unsigned long, __builtin_clzl)
179#endif // __has_builtin(__builtin_clzl)
180#if __has_builtin(__builtin_clzll)
150181ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll)
182#endif // __has_builtin(__builtin_clzll)
151183#endif // __has_builtin(__builtin_clzg)
152184
153185#undef ADD_SPECIALIZATION
......@@ -284,11 +316,17 @@ popcount(T value) {
284316 [[nodiscard]] LIBC_INLINE constexpr int popcount<TYPE>(TYPE value) { \
285317 return BUILTIN(value); \
286318 }
319#if __has_builtin(__builtin_popcount)
287320ADD_SPECIALIZATION(unsigned char, __builtin_popcount)
288321ADD_SPECIALIZATION(unsigned short, __builtin_popcount)
289322ADD_SPECIALIZATION(unsigned, __builtin_popcount)
323#endif // __builtin_popcount
324#if __has_builtin(__builtin_popcountl)
290325ADD_SPECIALIZATION(unsigned long, __builtin_popcountl)
326#endif // __builtin_popcountl
327#if __has_builtin(__builtin_popcountll)
291328ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll)
329#endif // __builtin_popcountll
292330#endif // __builtin_popcountg
293331#undef ADD_SPECIALIZATION
294332
lib/libcxx/libc/src/__support/CPP/type_traits/is_complex.h+7
......@@ -13,12 +13,17 @@
1313#include "src/__support/macros/attributes.h"
1414#include "src/__support/macros/config.h"
1515// LIBC_TYPES_HAS_CFLOAT16 && LIBC_TYPES_HAS_CFLOAT128
16#include "src/__support/macros/properties/compiler.h"
1617#include "src/__support/macros/properties/complex_types.h"
1718
1819namespace LIBC_NAMESPACE_DECL {
1920namespace cpp {
2021
2122// is_complex
23#ifdef LIBC_COMPILER_IS_MSVC
24// TODO: Add support for complex types with MSVC.
25template <typename T> struct is_complex : false_type {};
26#else
2227template <typename T> struct is_complex {
2328private:
2429 template <typename Head, typename... Args>
......@@ -40,6 +45,8 @@ public:
4045#endif
4146 >();
4247};
48#endif // LIBC_COMPILER_IS_MSVC
49
4350template <typename T>
4451LIBC_INLINE_VAR constexpr bool is_complex_v = is_complex<T>::value;
4552template <typename T1, typename T2>
lib/libcxx/libc/src/__support/CPP/type_traits/is_destructible.h+2-1
......@@ -15,6 +15,7 @@
1515#include "src/__support/CPP/type_traits/remove_all_extents.h"
1616#include "src/__support/CPP/type_traits/true_type.h"
1717#include "src/__support/CPP/type_traits/type_identity.h"
18#include "src/__support/CPP/utility/declval.h"
1819#include "src/__support/macros/attributes.h"
1920#include "src/__support/macros/config.h"
2021
......@@ -22,7 +23,7 @@ namespace LIBC_NAMESPACE_DECL {
2223namespace cpp {
2324
2425// is_destructible
25#if __has_builtin(__is_destructible)
26#if __has_builtin(__is_destructible) || defined(LIBC_COMPILER_IS_MSVC)
2627template <typename T>
2728struct is_destructible : bool_constant<__is_destructible(T)> {};
2829#else
lib/libcxx/libc/src/__support/CPP/type_traits/is_unsigned.h+6
......@@ -16,6 +16,8 @@
1616#include "src/__support/macros/attributes.h"
1717#include "src/__support/macros/config.h"
1818
19#include <stddef.h>
20
1921namespace LIBC_NAMESPACE_DECL {
2022namespace cpp {
2123
......@@ -46,6 +48,10 @@ public:
4648 LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; }
4749};
4850#endif // LIBC_COMPILER_HAS_FIXED_POINT
51#if LIBC_HAS_VECTOR_TYPE
52template <typename T, size_t N>
53struct is_unsigned<T [[clang::ext_vector_type(N)]]> : bool_constant<false> {};
54#endif
4955
5056template <typename T>
5157LIBC_INLINE_VAR constexpr bool is_unsigned_v = is_unsigned<T>::value;
lib/libcxx/libc/src/__support/CPP/utility/integer_sequence.h+10
......@@ -5,12 +5,15 @@
55// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66//
77//===----------------------------------------------------------------------===//
8
89#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H
910#define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H
1011
1112#include "src/__support/CPP/type_traits/is_integral.h"
1213#include "src/__support/macros/config.h"
1314
15#include <stddef.h>
16
1417namespace LIBC_NAMESPACE_DECL {
1518namespace cpp {
1619
......@@ -34,6 +37,13 @@ template <typename T, int N>
3437using make_integer_sequence =
3538 typename detail::make_integer_sequence<T, N - 1>::type;
3639
40// index sequence
41template <size_t... Ints>
42using index_sequence = integer_sequence<size_t, Ints...>;
43template <int N>
44using make_index_sequence =
45 typename detail::make_integer_sequence<size_t, N - 1>::type;
46
3747} // namespace cpp
3848} // namespace LIBC_NAMESPACE_DECL
3949
lib/libcxx/libc/src/__support/FPUtil/FPBits.h+6-7
......@@ -15,6 +15,7 @@
1515#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H
1616#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H
1717
18#include "hdr/stdint_proxy.h"
1819#include "src/__support/CPP/bit.h"
1920#include "src/__support/CPP/type_traits.h"
2021#include "src/__support/common.h"
......@@ -26,8 +27,6 @@
2627#include "src/__support/sign.h" // Sign
2728#include "src/__support/uint128.h"
2829
29#include <stdint.h>
30
3130namespace LIBC_NAMESPACE_DECL {
3231namespace fputil {
3332
......@@ -790,16 +789,16 @@ struct FPRep : public FPRepImpl<fp_type, FPRep<fp_type>> {
790789// Returns the FPType corresponding to C++ type T on the host.
791790template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
792791 using UnqualT = cpp::remove_cv_t<T>;
793 if constexpr (cpp::is_same_v<UnqualT, float> && __FLT_MANT_DIG__ == 24)
792 if constexpr (cpp::is_same_v<UnqualT, float> && FLT_MANT_DIG == 24)
794793 return FPType::IEEE754_Binary32;
795 else if constexpr (cpp::is_same_v<UnqualT, double> && __DBL_MANT_DIG__ == 53)
794 else if constexpr (cpp::is_same_v<UnqualT, double> && DBL_MANT_DIG == 53)
796795 return FPType::IEEE754_Binary64;
797796 else if constexpr (cpp::is_same_v<UnqualT, long double>) {
798 if constexpr (__LDBL_MANT_DIG__ == 53)
797 if constexpr (LDBL_MANT_DIG == 53)
799798 return FPType::IEEE754_Binary64;
800 else if constexpr (__LDBL_MANT_DIG__ == 64)
799 else if constexpr (LDBL_MANT_DIG == 64)
801800 return FPType::X86_Binary80;
802 else if constexpr (__LDBL_MANT_DIG__ == 113)
801 else if constexpr (LDBL_MANT_DIG == 113)
803802 return FPType::IEEE754_Binary128;
804803 }
805804#if defined(LIBC_TYPES_HAS_FLOAT16)
lib/libcxx/libc/src/__support/FPUtil/rounding_mode.h+50-4
......@@ -10,18 +10,21 @@
1010#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_ROUNDING_MODE_H
1111
1212#include "hdr/fenv_macros.h"
13#include "src/__support/CPP/type_traits.h" // is_constant_evaluated
1314#include "src/__support/macros/attributes.h" // LIBC_INLINE
1415#include "src/__support/macros/config.h"
1516
1617namespace LIBC_NAMESPACE_DECL {
1718namespace fputil {
1819
20namespace generic {
21
1922// Quick free-standing test whether fegetround() == FE_UPWARD.
2023// Using the following observation:
2124// 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
2225// = 0x1.000002f for FE_UPWARD.
2326LIBC_INLINE bool fenv_is_round_up() {
24 volatile float x = 0x1.0p-25f;
27 static volatile float x = 0x1.0p-25f;
2528 return (1.0f + x != 1.0f);
2629}
2730
......@@ -30,7 +33,7 @@ LIBC_INLINE bool fenv_is_round_up() {
3033// -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
3134// = -0x1.000002f for FE_DOWNWARD.
3235LIBC_INLINE bool fenv_is_round_down() {
33 volatile float x = 0x1.0p-25f;
36 static volatile float x = 0x1.0p-25f;
3437 return (-1.0f - x != -1.0f);
3538}
3639
......@@ -42,8 +45,8 @@ LIBC_INLINE bool fenv_is_round_down() {
4245// = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO
4346LIBC_INLINE bool fenv_is_round_to_nearest() {
4447 static volatile float x = 0x1.0p-24f;
45 float y = x;
46 return (1.5f + y == 1.5f - y);
48 float y = 1.5f + x;
49 return (y == 1.5f - x);
4750}
4851
4952// Quick free-standing test whether fegetround() == FE_TOWARDZERO.
......@@ -75,6 +78,49 @@ LIBC_INLINE int quick_get_round() {
7578 return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
7679}
7780
81} // namespace generic
82
83LIBC_INLINE static constexpr bool fenv_is_round_up() {
84 if (cpp::is_constant_evaluated()) {
85 return false;
86 } else {
87 return generic::fenv_is_round_up();
88 }
89}
90
91LIBC_INLINE static constexpr bool fenv_is_round_down() {
92 if (cpp::is_constant_evaluated()) {
93 return false;
94 } else {
95 return generic::fenv_is_round_down();
96 }
97}
98
99LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
100 if (cpp::is_constant_evaluated()) {
101 return true;
102 } else {
103 return generic::fenv_is_round_to_nearest();
104 }
105}
106
107LIBC_INLINE static constexpr bool fenv_is_round_to_zero() {
108 if (cpp::is_constant_evaluated()) {
109 return false;
110 } else {
111 return generic::fenv_is_round_to_zero();
112 }
113}
114
115// Quick free standing get rounding mode based on the above observations.
116LIBC_INLINE static constexpr int quick_get_round() {
117 if (cpp::is_constant_evaluated()) {
118 return FE_TONEAREST;
119 } else {
120 return generic::quick_get_round();
121 }
122}
123
78124} // namespace fputil
79125} // namespace LIBC_NAMESPACE_DECL
80126
lib/libcxx/libc/src/__support/big_int.h+14-14
......@@ -9,6 +9,7 @@
99#ifndef LLVM_LIBC_SRC___SUPPORT_BIG_INT_H
1010#define LLVM_LIBC_SRC___SUPPORT_BIG_INT_H
1111
12#include "hdr/stdint_proxy.h"
1213#include "src/__support/CPP/array.h"
1314#include "src/__support/CPP/bit.h" // countl_zero
1415#include "src/__support/CPP/limits.h"
......@@ -23,7 +24,6 @@
2324#include "src/__support/number_pair.h"
2425
2526#include <stddef.h> // For size_t
26#include <stdint.h>
2727
2828namespace LIBC_NAMESPACE_DECL {
2929
......@@ -95,10 +95,10 @@ LIBC_INLINE constexpr DoubleWide<word> mul2(word a, word b) {
9595#endif
9696 else {
9797 using half_word = half_width_t<word>;
98 const auto shiftl = [](word value) -> word {
98 constexpr auto shiftl = [](word value) -> word {
9999 return value << cpp::numeric_limits<half_word>::digits;
100100 };
101 const auto shiftr = [](word value) -> word {
101 constexpr auto shiftr = [](word value) -> word {
102102 return value >> cpp::numeric_limits<half_word>::digits;
103103 };
104104 // Here we do a one digit multiplication where 'a' and 'b' are of type
......@@ -111,19 +111,19 @@ LIBC_INLINE constexpr DoubleWide<word> mul2(word a, word b) {
111111 // c result
112112 // We convert 'lo' and 'hi' from 'half_word' to 'word' so multiplication
113113 // doesn't overflow.
114 const word a_lo = lo(a);
115 const word b_lo = lo(b);
116 const word a_hi = hi(a);
117 const word b_hi = hi(b);
118 const word step1 = b_lo * a_lo; // no overflow;
119 const word step2 = b_lo * a_hi; // no overflow;
120 const word step3 = b_hi * a_lo; // no overflow;
121 const word step4 = b_hi * a_hi; // no overflow;
114 word a_lo = lo(a);
115 word b_lo = lo(b);
116 word a_hi = hi(a);
117 word b_hi = hi(b);
118 word step1 = b_lo * a_lo; // no overflow;
119 word step2 = b_lo * a_hi; // no overflow;
120 word step3 = b_hi * a_lo; // no overflow;
121 word step4 = b_hi * a_hi; // no overflow;
122122 word lo_digit = step1;
123123 word hi_digit = step4;
124 const word no_carry = 0;
125 word carry;
126 word _; // unused carry variable.
124 word no_carry = 0;
125 word carry = 0;
126 [[maybe_unused]] word _ = 0; // unused carry variable.
127127 lo_digit = add_with_carry<word>(lo_digit, shiftl(step2), no_carry, carry);
128128 hi_digit = add_with_carry<word>(hi_digit, shiftr(step2), carry, _);
129129 lo_digit = add_with_carry<word>(lo_digit, shiftl(step3), no_carry, carry);
lib/libcxx/libc/src/__support/common.h+3-2
......@@ -16,6 +16,7 @@
1616#include "src/__support/macros/attributes.h"
1717#include "src/__support/macros/config.h"
1818#include "src/__support/macros/properties/architectures.h"
19#include "src/__support/macros/properties/compiler.h"
1920
2021#ifndef LLVM_LIBC_FUNCTION_ATTR
2122#define LLVM_LIBC_FUNCTION_ATTR
......@@ -41,12 +42,12 @@
4142// to cleanly export and alias the C++ symbol `LIBC_NAMESPACE::func` with the C
4243// symbol `func`. So for public packaging on MacOS, we will only export the C
4344// symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`.
44#if defined(LIBC_COPT_PUBLIC_PACKAGING)
45#if defined(LIBC_COPT_PUBLIC_PACKAGING) && !defined(LIBC_COMPILER_IS_MSVC)
4546#ifndef __APPLE__
4647#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \
4748 LLVM_LIBC_ATTR(name) \
4849 LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \
49 __##name##_impl__ __asm__(#name); \
50 __##name##_impl__ asm(#name); \
5051 decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \
5152 type __##name##_impl__ arglist
5253#else // __APPLE__
lib/libcxx/libc/src/__support/ctype_utils.h+19-12
......@@ -27,7 +27,7 @@ namespace internal {
2727// as well as a way to support non-ASCII character encodings.
2828
2929// Similarly, do not change these functions to use case ranges. e.g.
30// bool islower(int ch) {
30// bool islower(char ch) {
3131// switch(ch) {
3232// case 'a'...'z':
3333// return true;
......@@ -37,7 +37,7 @@ namespace internal {
3737// EBCDIC. Technically we could use some smaller ranges, but that's even harder
3838// to read.
3939
40LIBC_INLINE static constexpr bool islower(int ch) {
40LIBC_INLINE static constexpr bool islower(char ch) {
4141 switch (ch) {
4242 case 'a':
4343 case 'b':
......@@ -71,7 +71,7 @@ LIBC_INLINE static constexpr bool islower(int ch) {
7171 }
7272}
7373
74LIBC_INLINE static constexpr bool isupper(int ch) {
74LIBC_INLINE static constexpr bool isupper(char ch) {
7575 switch (ch) {
7676 case 'A':
7777 case 'B':
......@@ -105,7 +105,7 @@ LIBC_INLINE static constexpr bool isupper(int ch) {
105105 }
106106}
107107
108LIBC_INLINE static constexpr bool isdigit(int ch) {
108LIBC_INLINE static constexpr bool isdigit(char ch) {
109109 switch (ch) {
110110 case '0':
111111 case '1':
......@@ -123,7 +123,7 @@ LIBC_INLINE static constexpr bool isdigit(int ch) {
123123 }
124124}
125125
126LIBC_INLINE static constexpr int tolower(int ch) {
126LIBC_INLINE static constexpr char tolower(char ch) {
127127 switch (ch) {
128128 case 'A':
129129 return 'a';
......@@ -182,7 +182,7 @@ LIBC_INLINE static constexpr int tolower(int ch) {
182182 }
183183}
184184
185LIBC_INLINE static constexpr int toupper(int ch) {
185LIBC_INLINE static constexpr char toupper(char ch) {
186186 switch (ch) {
187187 case 'a':
188188 return 'A';
......@@ -241,7 +241,7 @@ LIBC_INLINE static constexpr int toupper(int ch) {
241241 }
242242}
243243
244LIBC_INLINE static constexpr bool isalpha(int ch) {
244LIBC_INLINE static constexpr bool isalpha(char ch) {
245245 switch (ch) {
246246 case 'a':
247247 case 'b':
......@@ -301,7 +301,7 @@ LIBC_INLINE static constexpr bool isalpha(int ch) {
301301 }
302302}
303303
304LIBC_INLINE static constexpr bool isalnum(int ch) {
304LIBC_INLINE static constexpr bool isalnum(char ch) {
305305 switch (ch) {
306306 case 'a':
307307 case 'b':
......@@ -371,7 +371,7 @@ LIBC_INLINE static constexpr bool isalnum(int ch) {
371371 }
372372}
373373
374LIBC_INLINE static constexpr int b36_char_to_int(int ch) {
374LIBC_INLINE static constexpr int b36_char_to_int(char ch) {
375375 switch (ch) {
376376 case '0':
377377 return 0;
......@@ -476,7 +476,7 @@ LIBC_INLINE static constexpr int b36_char_to_int(int ch) {
476476 }
477477}
478478
479LIBC_INLINE static constexpr int int_to_b36_char(int num) {
479LIBC_INLINE static constexpr char int_to_b36_char(int num) {
480480 // Can't actually use LIBC_ASSERT here because it depends on integer_to_string
481481 // which depends on this.
482482
......@@ -559,7 +559,7 @@ LIBC_INLINE static constexpr int int_to_b36_char(int num) {
559559 }
560560}
561561
562LIBC_INLINE static constexpr bool isspace(int ch) {
562LIBC_INLINE static constexpr bool isspace(char ch) {
563563 switch (ch) {
564564 case ' ':
565565 case '\t':
......@@ -574,10 +574,17 @@ LIBC_INLINE static constexpr bool isspace(int ch) {
574574}
575575
576576// not yet encoding independent.
577LIBC_INLINE static constexpr bool isgraph(int ch) {
577LIBC_INLINE static constexpr bool isgraph(char ch) {
578578 return 0x20 < ch && ch < 0x7f;
579579}
580580
581// An overload which provides a way to compare input with specific character
582// values, when input can be of a regular or a wide character type.
583LIBC_INLINE static constexpr bool is_char_or_wchar(char ch, char c_value,
584 [[maybe_unused]] wchar_t) {
585 return (ch == c_value);
586}
587
581588} // namespace internal
582589} // namespace LIBC_NAMESPACE_DECL
583590
lib/libcxx/libc/src/__support/detailed_powers_of_ten.h+1-2
......@@ -9,11 +9,10 @@
99#ifndef LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H
1010#define LLVM_LIBC_SRC___SUPPORT_DETAILED_POWERS_OF_TEN_H
1111
12#include "hdr/stdint_proxy.h"
1213#include "src/__support/common.h"
1314#include "src/__support/macros/config.h"
1415
15#include <stdint.h>
16
1716namespace LIBC_NAMESPACE_DECL {
1817namespace internal {
1918
lib/libcxx/libc/src/__support/high_precision_decimal.h+33-14
......@@ -15,11 +15,12 @@
1515#ifndef LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H
1616#define LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H
1717
18#include "hdr/stdint_proxy.h"
1819#include "src/__support/CPP/limits.h"
1920#include "src/__support/ctype_utils.h"
2021#include "src/__support/macros/config.h"
2122#include "src/__support/str_to_integer.h"
22#include <stdint.h>
23#include "src/__support/wctype_utils.h"
2324
2425namespace LIBC_NAMESPACE_DECL {
2526namespace internal {
......@@ -38,6 +39,24 @@ struct LShiftTableEntry {
3839// TODO: Figure out where to put this.
3940enum class RoundDirection { Up, Down, Nearest };
4041
42// These constants are used in both this file and in the main str_to_float.h.
43// TODO: Figure out where to put this.
44template <typename CharType> struct constants;
45template <> struct constants<char> {
46 static constexpr char DECIMAL_POINT = '.';
47 static constexpr char DECIMAL_EXPONENT_MARKER = 'e';
48 static constexpr char HEX_EXPONENT_MARKER = 'p';
49 static constexpr char INF_STRING[] = "infinity";
50 static constexpr char NAN_STRING[] = "nan";
51};
52template <> struct constants<wchar_t> {
53 static constexpr wchar_t DECIMAL_POINT = L'.';
54 static constexpr wchar_t DECIMAL_EXPONENT_MARKER = L'e';
55 static constexpr wchar_t HEX_EXPONENT_MARKER = L'p';
56 static constexpr wchar_t INF_STRING[] = L"infinity";
57 static constexpr wchar_t NAN_STRING[] = L"nan";
58};
59
4160// This is based on the HPD data structure described as part of the Simple
4261// Decimal Conversion algorithm by Nigel Tao, described at this link:
4362// https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html
......@@ -314,9 +333,9 @@ private:
314333public:
315334 // num_string is assumed to be a string of numeric characters. It doesn't
316335 // handle leading spaces.
317 LIBC_INLINE
318 HighPrecisionDecimal(
319 const char *__restrict num_string,
336 template <typename CharType>
337 LIBC_INLINE HighPrecisionDecimal(
338 const CharType *__restrict num_string,
320339 const size_t num_len = cpp::numeric_limits<size_t>::max()) {
321340 bool saw_dot = false;
322341 size_t num_cur = 0;
......@@ -324,25 +343,26 @@ public:
324343 // them all.
325344 uint32_t total_digits = 0;
326345 while (num_cur < num_len &&
327 (isdigit(num_string[num_cur]) || num_string[num_cur] == '.')) {
328 if (num_string[num_cur] == '.') {
346 (isdigit(num_string[num_cur]) ||
347 num_string[num_cur] == constants<CharType>::DECIMAL_POINT)) {
348 if (num_string[num_cur] == constants<CharType>::DECIMAL_POINT) {
329349 if (saw_dot) {
330350 break;
331351 }
332352 this->decimal_point = static_cast<int32_t>(total_digits);
333353 saw_dot = true;
334354 } else {
335 if (num_string[num_cur] == '0' && this->num_digits == 0) {
355 int digit = b36_char_to_int(num_string[num_cur]);
356 if (digit == 0 && this->num_digits == 0) {
336357 --this->decimal_point;
337358 ++num_cur;
338359 continue;
339360 }
340361 ++total_digits;
341362 if (this->num_digits < MAX_NUM_DIGITS) {
342 this->digits[this->num_digits] = static_cast<uint8_t>(
343 internal::b36_char_to_int(num_string[num_cur]));
363 this->digits[this->num_digits] = static_cast<uint8_t>(digit);
344364 ++this->num_digits;
345 } else if (num_string[num_cur] != '0') {
365 } else if (digit != 0) {
346366 this->truncated = true;
347367 }
348368 }
......@@ -352,11 +372,10 @@ public:
352372 if (!saw_dot)
353373 this->decimal_point = static_cast<int32_t>(total_digits);
354374
355 if (num_cur < num_len &&
356 (num_string[num_cur] == 'e' || num_string[num_cur] == 'E')) {
375 if (num_cur < num_len && tolower(num_string[num_cur]) ==
376 constants<CharType>::DECIMAL_EXPONENT_MARKER) {
357377 ++num_cur;
358 if (isdigit(num_string[num_cur]) || num_string[num_cur] == '+' ||
359 num_string[num_cur] == '-') {
378 if (isdigit(num_string[num_cur]) || get_sign(num_string + num_cur) != 0) {
360379 auto result =
361380 strtointeger<int32_t>(num_string + num_cur, 10, num_len - num_cur);
362381 if (result.has_error()) {
lib/libcxx/libc/src/__support/libc_assert.h+2
......@@ -14,9 +14,11 @@
1414// The build is configured to just use the public <assert.h> API
1515// for libc's internal assertions.
1616
17#ifndef LIBC_ASSERT
1718#include <assert.h>
1819
1920#define LIBC_ASSERT(COND) assert(COND)
21#endif // LIBC_ASSERT
2022
2123#else // Not LIBC_COPT_USE_C_ASSERT
2224
lib/libcxx/libc/src/__support/macros/attributes.h+44-1
......@@ -17,6 +17,7 @@
1717#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
1818#define LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
1919
20#include "config.h"
2021#include "properties/architectures.h"
2122
2223#ifndef __has_attribute
......@@ -28,7 +29,32 @@
2829#define LIBC_INLINE_ASM __asm__ __volatile__
2930#define LIBC_UNUSED __attribute__((unused))
3031
31#ifdef LIBC_TARGET_ARCH_IS_GPU
32// Uses the platform specific specialization
33#define LIBC_THREAD_MODE_PLATFORM 0
34
35// Mutex guards nothing, used in single-threaded implementations
36#define LIBC_THREAD_MODE_SINGLE 1
37
38// Vendor provides implementation
39#define LIBC_THREAD_MODE_EXTERNAL 2
40
41// libcxx doesn't define LIBC_THREAD_MODE, unless that is passed in the command
42// line in the CMake invocation. This defaults to the original implementation
43// (before changes in https://github.com/llvm/llvm-project/pull/145358)
44#ifndef LIBC_THREAD_MODE
45#define LIBC_THREAD_MODE LIBC_THREAD_MODE_PLATFORM
46#endif // LIBC_THREAD_MODE
47
48#if LIBC_THREAD_MODE != LIBC_THREAD_MODE_PLATFORM && \
49 LIBC_THREAD_MODE != LIBC_THREAD_MODE_SINGLE && \
50 LIBC_THREAD_MODE != LIBC_THREAD_MODE_EXTERNAL
51#error LIBC_THREAD_MODE must be one of the following values: \
52LIBC_THREAD_MODE_PLATFORM, \
53LIBC_THREAD_MODE_SINGLE, \
54LIBC_THREAD_MODE_EXTERNAL.
55#endif
56
57#if LIBC_THREAD_MODE == LIBC_THREAD_MODE_SINGLE
3258#define LIBC_THREAD_LOCAL
3359#else
3460#define LIBC_THREAD_LOCAL thread_local
......@@ -48,4 +74,21 @@
4874#define LIBC_PREFERED_TYPE(TYPE)
4975#endif
5076
77#if __has_attribute(ext_vector_type) && \
78 LIBC_HAS_FEATURE(ext_vector_type_boolean)
79#define LIBC_HAS_VECTOR_TYPE 1
80#else
81#define LIBC_HAS_VECTOR_TYPE 0
82#endif
83
84#if __has_attribute(no_sanitize)
85// Disable regular and hardware-supported ASan for functions that may
86// intentionally make out-of-bounds access. Disable TSan as well, as it detects
87// out-of-bounds accesses to heap memory.
88#define LIBC_NO_SANITIZE_OOB_ACCESS \
89 __attribute__((no_sanitize("address", "hwaddress", "thread")))
90#else
91#define LIBC_NO_SANITIZE_OOB_ACCESS
92#endif
93
5194#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H
lib/libcxx/libc/src/__support/macros/config.h+23
......@@ -13,6 +13,13 @@
1313#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H
1414#define LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H
1515
16#include "src/__support/macros/properties/architectures.h"
17#include "src/__support/macros/properties/compiler.h"
18
19#ifdef LIBC_COMPILER_IS_MSVC
20#include <intrin.h>
21#endif // LIBC_COMPILER_IS_MSVC
22
1623// Workaround for compilers that do not support builtin detection.
1724// FIXME: This is only required for the GPU portion which should be moved.
1825#ifndef __has_builtin
......@@ -27,6 +34,22 @@
2734#define LIBC_HAS_FEATURE(f) 0
2835#endif
2936
37#ifdef LIBC_COMPILER_IS_MSVC
38
39// __builtin_trap replacement
40#ifdef LIBC_TARGET_ARCH_IS_X86
41#define __builtin_trap __ud2
42#else // arm64
43#define __builtin_trap() __break(1)
44#endif
45
46#define __builtin_expect(value, expectation) (value)
47#define __builtin_unreachable() __assume(0)
48
49#define __builtin_prefetch(X, Y, Z)
50
51#endif // LIBC_COMPILER_IS_MSVC
52
3053#ifdef __clang__
3154// Declare a LIBC_NAMESPACE with hidden visibility. `namespace
3255// LIBC_NAMESPACE_DECL {` should be used around all declarations and definitions
lib/libcxx/libc/src/__support/macros/null_check.h+1-2
......@@ -11,9 +11,8 @@
1111
1212#include "src/__support/macros/config.h"
1313#include "src/__support/macros/optimization.h"
14#include "src/__support/macros/sanitizer.h"
1514
16#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
15#if defined(LIBC_ADD_NULL_CHECKS)
1716#define LIBC_CRASH_ON_NULLPTR(ptr) \
1817 do { \
1918 if (LIBC_UNLIKELY((ptr) == nullptr)) \
lib/libcxx/libc/src/__support/macros/optimization.h+3
......@@ -34,6 +34,9 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
3434#elif defined(LIBC_COMPILER_IS_GCC)
3535#define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0")
3636#define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048")
37#elif defined(LIBC_COMPILER_IS_MSVC)
38#define LIBC_LOOP_NOUNROLL
39#define LIBC_LOOP_UNROLL
3740#else
3841#error "Unhandled compiler"
3942#endif
lib/libcxx/libc/src/__support/macros/properties/architectures.h+5-1
......@@ -21,7 +21,7 @@
2121#define LIBC_TARGET_ARCH_IS_GPU
2222#endif
2323
24#if defined(__pnacl__) || defined(__CLR_VER) || defined(LIBC_TARGET_ARCH_IS_GPU)
24#if defined(__CLR_VER) || defined(LIBC_TARGET_ARCH_IS_GPU)
2525#define LIBC_TARGET_ARCH_IS_VM
2626#endif
2727
......@@ -41,6 +41,10 @@
4141#define LIBC_TARGET_ARCH_IS_ARM
4242#endif
4343
44#if defined(__wasm__)
45#define LIBC_TARGET_ARCH_IS_WASM
46#endif
47
4448#if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)
4549#define LIBC_TARGET_ARCH_IS_AARCH64
4650#endif
lib/libcxx/libc/src/__support/macros/properties/compiler.h+8-3
......@@ -34,10 +34,15 @@
3434#define LIBC_COMPILER_GCC_VER (__GNUC__ * 100 + __GNUC_MINOR__)
3535#endif
3636
37#if defined(_MSC_VER)
38#define LIBC_COMPILER_IS_MSC
37#if defined(_MSC_VER) && !defined(__clang__)
38#define LIBC_COMPILER_IS_MSVC
3939// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros
40#define LIBC_COMPILER_MSC_VER (_MSC_VER)
40#define LIBC_COMPILER_MSVC_VER (_MSC_VER)
41#ifdef _M_X64
42#define LIBC_COMPILER_IS_MSVC_X64
43#else
44#define LIBC_COMPILER_IS_MSVC_X86
45#endif
4146#endif
4247
4348#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_COMPILER_H
lib/libcxx/libc/src/__support/macros/properties/cpu_features.h+17-1
......@@ -18,6 +18,18 @@
1818#define LIBC_TARGET_CPU_HAS_FULLFP16
1919#endif
2020
21#if defined(__ARM_FEATURE_SVE)
22#define LIBC_TARGET_CPU_HAS_SVE
23#endif
24
25#if defined(__ARM_FEATURE_SVE2)
26#define LIBC_TARGET_CPU_HAS_SVE2
27#endif
28
29#if defined(__ARM_FEATURE_MOPS)
30#define LIBC_TARGET_CPU_HAS_MOPS
31#endif
32
2133#if defined(__SSE2__)
2234#define LIBC_TARGET_CPU_HAS_SSE2
2335#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
......@@ -59,6 +71,10 @@
5971#endif // LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE
6072#endif // __ARM_FP
6173
74#if defined(__ARM_NEON)
75#define LIBC_TARGET_CPU_HAS_ARM_NEON
76#endif
77
6278#if defined(__riscv_flen)
6379// https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc
6480#if defined(__riscv_zfhmin)
......@@ -81,7 +97,7 @@
8197#endif
8298
8399#if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \
84 defined(__NVPTX__) || defined(__AMDGPU__) || defined(__LIBC_RISCV_USE_FMA)
100 defined(__NVPTX__) || defined(__AMDGPU__) || defined(__riscv_flen)
85101#define LIBC_TARGET_CPU_HAS_FMA
86102// Provide a more fine-grained control of FMA instruction for ARM targets.
87103#if defined(LIBC_TARGET_CPU_HAS_FPU_HALF)
lib/libcxx/libc/src/__support/macros/properties/types.h+2-3
......@@ -10,7 +10,8 @@
1010#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
1111#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
1212
13#include "hdr/float_macros.h" // LDBL_MANT_DIG
13#include "hdr/float_macros.h" // LDBL_MANT_DIG
14#include "hdr/stdint_proxy.h" // UINT64_MAX, __SIZEOF_INT128__
1415#include "include/llvm-libc-macros/float16-macros.h" // LIBC_TYPES_HAS_FLOAT16
1516#include "include/llvm-libc-types/float128.h" // float128
1617#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
......@@ -19,8 +20,6 @@
1920#include "src/__support/macros/properties/cpu_features.h"
2021#include "src/__support/macros/properties/os.h"
2122
22#include <stdint.h> // UINT64_MAX, __SIZEOF_INT128__
23
2423// 'long double' properties.
2524#if (LDBL_MANT_DIG == 53)
2625#define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64
lib/libcxx/libc/src/__support/macros/sanitizer.h-10
......@@ -23,16 +23,6 @@
2323#define LIBC_HAS_MEMORY_SANITIZER
2424#endif
2525
26#if LIBC_HAS_FEATURE(undefined_behavior_sanitizer)
27#define LIBC_HAS_UNDEFINED_BEHAVIOR_SANITIZER
28#endif
29
30#if defined(LIBC_HAS_ADDRESS_SANITIZER) || \
31 defined(LIBC_HAS_MEMORY_SANITIZER) || \
32 defined(LIBC_HAS_UNDEFINED_BEHAVIOR_SANITIZER)
33#define LIBC_HAS_SANITIZER
34#endif
35
3626#ifdef LIBC_HAS_MEMORY_SANITIZER
3727// Only perform MSAN unpoison in non-constexpr context.
3828#include <sanitizer/msan_interface.h>
lib/libcxx/libc/src/__support/math_extras.h+20-4
......@@ -25,7 +25,13 @@ LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
2525mask_trailing_ones() {
2626 constexpr unsigned T_BITS = CHAR_BIT * sizeof(T);
2727 static_assert(count <= T_BITS && "Invalid bit index");
28 return count == 0 ? 0 : (T(-1) >> (T_BITS - count));
28 // MSVC complains about out of range shifts.
29 if constexpr (count == 0)
30 return 0;
31 else if constexpr (count >= T_BITS)
32 return T(-1);
33 else
34 return T(-1) >> (T_BITS - count);
2935}
3036
3137// Create a bitmask with the count left-most bits set to 1, and all other bits
......@@ -55,18 +61,28 @@ mask_leading_zeros() {
5561// Returns whether 'a + b' overflows, the result is stored in 'res'.
5662template <typename T>
5763[[nodiscard]] LIBC_INLINE constexpr bool add_overflow(T a, T b, T &res) {
64#if __has_builtin(__builtin_add_overflow)
5865 return __builtin_add_overflow(a, b, &res);
66#else
67 res = a + b;
68 return (res < a) || (res < b);
69#endif // __builtin_add_overflow
5970}
6071
6172// Returns whether 'a - b' overflows, the result is stored in 'res'.
6273template <typename T>
6374[[nodiscard]] LIBC_INLINE constexpr bool sub_overflow(T a, T b, T &res) {
75#if __has_builtin(__builtin_sub_overflow)
6476 return __builtin_sub_overflow(a, b, &res);
77#else
78 res = a - b;
79 return (res > a);
80#endif // __builtin_sub_overflow
6581}
6682
6783#define RETURN_IF(TYPE, BUILTIN) \
6884 if constexpr (cpp::is_same_v<T, TYPE>) \
69 return BUILTIN(a, b, carry_in, carry_out);
85 return BUILTIN(a, b, carry_in, &carry_out);
7086
7187// Returns the result of 'a + b' taking into account 'carry_in'.
7288// The carry out is stored in 'carry_out' it not 'nullptr', dropped otherwise.
......@@ -74,7 +90,7 @@ template <typename T>
7490template <typename T>
7591[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
7692add_with_carry(T a, T b, T carry_in, T &carry_out) {
77 if constexpr (!cpp::is_constant_evaluated()) {
93 if (!cpp::is_constant_evaluated()) {
7894#if __has_builtin(__builtin_addcb)
7995 RETURN_IF(unsigned char, __builtin_addcb)
8096#elif __has_builtin(__builtin_addcs)
......@@ -100,7 +116,7 @@ add_with_carry(T a, T b, T carry_in, T &carry_out) {
100116template <typename T>
101117[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
102118sub_with_borrow(T a, T b, T carry_in, T &carry_out) {
103 if constexpr (!cpp::is_constant_evaluated()) {
119 if (!cpp::is_constant_evaluated()) {
104120#if __has_builtin(__builtin_subcb)
105121 RETURN_IF(unsigned char, __builtin_subcb)
106122#elif __has_builtin(__builtin_subcs)
lib/libcxx/libc/src/__support/str_to_float.h+98-125
......@@ -16,6 +16,7 @@
1616#define LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H
1717
1818#include "hdr/errno_macros.h" // For ERANGE
19#include "hdr/stdint_proxy.h"
1920#include "src/__support/CPP/bit.h"
2021#include "src/__support/CPP/limits.h"
2122#include "src/__support/CPP/optional.h"
......@@ -32,8 +33,7 @@
3233#include "src/__support/str_to_integer.h"
3334#include "src/__support/str_to_num_result.h"
3435#include "src/__support/uint128.h"
35
36#include <stdint.h>
36#include "src/__support/wctype_utils.h"
3737
3838namespace LIBC_NAMESPACE_DECL {
3939namespace internal {
......@@ -335,9 +335,9 @@ constexpr int32_t NUM_POWERS_OF_TWO =
335335// the Eisel-Lemire algorithm fails, it's slower but more accurate. It's based
336336// on the Simple Decimal Conversion algorithm by Nigel Tao, described at this
337337// link: https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html
338template <class T>
338template <typename T, typename CharType>
339339LIBC_INLINE FloatConvertReturn<T> simple_decimal_conversion(
340 const char *__restrict numStart,
340 const CharType *__restrict numStart,
341341 const size_t num_len = cpp::numeric_limits<size_t>::max(),
342342 RoundDirection round = RoundDirection::Nearest) {
343343 using FPBits = typename fputil::FPBits<T>;
......@@ -677,12 +677,11 @@ template <> LIBC_INLINE constexpr int32_t get_lower_bound<double>() {
677677// Takes a mantissa and base 10 exponent and converts it into its closest
678678// floating point type T equivalient. First we try the Eisel-Lemire algorithm,
679679// then if that fails then we fall back to a more accurate algorithm for
680// accuracy. The resulting mantissa and exponent are placed in outputMantissa
681// and outputExp2.
682template <class T>
680// accuracy.
681template <typename T, typename CharType>
683682LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float(
684683 ExpandedFloat<T> init_num, bool truncated, RoundDirection round,
685 const char *__restrict numStart,
684 const CharType *__restrict numStart,
686685 const size_t num_len = cpp::numeric_limits<size_t>::max()) {
687686 using FPBits = typename fputil::FPBits<T>;
688687 using StorageType = typename FPBits::StorageType;
......@@ -861,36 +860,42 @@ LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num,
861860 return output;
862861}
863862
864// checks if the next 4 characters of the string pointer are the start of a
863// Checks if the first characters of the string pointer are the start of a
865864// hexadecimal floating point number. Does not advance the string pointer.
866LIBC_INLINE bool is_float_hex_start(const char *__restrict src,
867 const char decimalPoint) {
868 if (!(src[0] == '0' && tolower(src[1]) == 'x')) {
865template <typename CharType>
866LIBC_INLINE static bool is_float_hex_start(const CharType *__restrict src) {
867 if (!is_char_or_wchar(src[0], '0', L'0') ||
868 !is_char_or_wchar(tolower(src[1]), 'x', L'x')) {
869869 return false;
870870 }
871871 size_t first_digit = 2;
872 if (src[2] == decimalPoint) {
872 if (src[2] == constants<CharType>::DECIMAL_POINT) {
873873 ++first_digit;
874874 }
875875 return isalnum(src[first_digit]) && b36_char_to_int(src[first_digit]) < 16;
876876}
877877
878// Takes the start of a string representing a decimal float, as well as the
879// local decimalPoint. It returns if it suceeded in parsing any digits, and if
880// the return value is true then the outputs are pointer to the end of the
881// number, and the mantissa and exponent for the closest float T representation.
882// If the return value is false, then it is assumed that there is no number
883// here.
884template <class T>
885LIBC_INLINE StrToNumResult<ExpandedFloat<T>>
886decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
887 RoundDirection round) {
878// Verifies that first prefix_len characters of str, when lowercased, match the
879// specified prefix.
880template <typename CharType>
881LIBC_INLINE static bool tolower_starts_with(const CharType *str,
882 size_t prefix_len,
883 const CharType *prefix) {
884 for (size_t i = 0; i < prefix_len; ++i) {
885 if (tolower(str[i]) != prefix[i])
886 return false;
887 }
888 return true;
889}
890
891// Attempts parsing a decimal floating point number at the start of the string.
892template <typename T, typename CharType>
893LIBC_INLINE static StrToNumResult<ExpandedFloat<T>>
894decimal_string_to_float(const CharType *__restrict src, RoundDirection round) {
888895 using FPBits = typename fputil::FPBits<T>;
889896 using StorageType = typename FPBits::StorageType;
890897
891898 constexpr uint32_t BASE = 10;
892 constexpr char EXPONENT_MARKER = 'e';
893
894899 bool truncated = false;
895900 bool seen_digit = false;
896901 bool after_decimal = false;
......@@ -927,7 +932,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
927932 ++index;
928933 continue;
929934 }
930 if (src[index] == DECIMAL_POINT) {
935 if (src[index] == constants<CharType>::DECIMAL_POINT) {
931936 if (after_decimal) {
932937 break; // this means that src[index] points to a second decimal point,
933938 // ending the number.
......@@ -944,13 +949,10 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
944949 return output;
945950
946951 // TODO: When adding max length argument, handle the case of a trailing
947 // EXPONENT MARKER, see scanf for more details.
948 if (tolower(src[index]) == EXPONENT_MARKER) {
949 bool has_sign = false;
950 if (src[index + 1] == '+' || src[index + 1] == '-') {
951 has_sign = true;
952 }
953 if (isdigit(src[index + 1 + static_cast<size_t>(has_sign)])) {
952 // exponent marker, see scanf for more details.
953 if (tolower(src[index]) == constants<CharType>::DECIMAL_EXPONENT_MARKER) {
954 int sign = get_sign(src + index + 1);
955 if (isdigit(src[index + 1 + static_cast<size_t>(sign != 0)])) {
954956 ++index;
955957 auto result = strtointeger<int32_t>(src + index, 10);
956958 if (result.has_error())
......@@ -986,22 +988,16 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
986988 return output;
987989}
988990
989// Takes the start of a string representing a hexadecimal float, as well as the
990// local decimal point. It returns if it suceeded in parsing any digits, and if
991// the return value is true then the outputs are pointer to the end of the
992// number, and the mantissa and exponent for the closest float T representation.
993// If the return value is false, then it is assumed that there is no number
994// here.
995template <class T>
996LIBC_INLINE StrToNumResult<ExpandedFloat<T>>
997hexadecimal_string_to_float(const char *__restrict src,
998 const char DECIMAL_POINT, RoundDirection round) {
991// Attempts parsing a hexadecimal floating point number at the start of the
992// string.
993template <typename T, typename CharType>
994LIBC_INLINE static StrToNumResult<ExpandedFloat<T>>
995hexadecimal_string_to_float(const CharType *__restrict src,
996 RoundDirection round) {
999997 using FPBits = typename fputil::FPBits<T>;
1000998 using StorageType = typename FPBits::StorageType;
1001999
10021000 constexpr uint32_t BASE = 16;
1003 constexpr char EXPONENT_MARKER = 'p';
1004
10051001 bool truncated = false;
10061002 bool seen_digit = false;
10071003 bool after_decimal = false;
......@@ -1039,7 +1035,7 @@ hexadecimal_string_to_float(const char *__restrict src,
10391035 ++index;
10401036 continue;
10411037 }
1042 if (src[index] == DECIMAL_POINT) {
1038 if (src[index] == constants<CharType>::DECIMAL_POINT) {
10431039 if (after_decimal) {
10441040 break; // this means that src[index] points to a second decimal point,
10451041 // ending the number.
......@@ -1058,12 +1054,9 @@ hexadecimal_string_to_float(const char *__restrict src,
10581054 // Convert the exponent from having a base of 16 to having a base of 2.
10591055 exponent *= 4;
10601056
1061 if (tolower(src[index]) == EXPONENT_MARKER) {
1062 bool has_sign = false;
1063 if (src[index + 1] == '+' || src[index + 1] == '-') {
1064 has_sign = true;
1065 }
1066 if (isdigit(src[index + 1 + static_cast<size_t>(has_sign)])) {
1057 if (tolower(src[index]) == constants<CharType>::HEX_EXPONENT_MARKER) {
1058 int sign = get_sign(src + index + 1);
1059 if (isdigit(src[index + 1 + static_cast<size_t>(sign != 0)])) {
10671060 ++index;
10681061 auto result = strtointeger<int32_t>(src + index, 10);
10691062 if (result.has_error())
......@@ -1099,21 +1092,21 @@ hexadecimal_string_to_float(const char *__restrict src,
10991092 return output;
11001093}
11011094
1102template <class T>
1095template <typename T, typename CharType>
11031096LIBC_INLINE typename fputil::FPBits<T>::StorageType
1104nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) {
1097nan_mantissa_from_ncharseq(const CharType *str, size_t len) {
11051098 using FPBits = typename fputil::FPBits<T>;
11061099 using StorageType = typename FPBits::StorageType;
11071100
11081101 StorageType nan_mantissa = 0;
11091102
1110 if (ncharseq.data() != nullptr && isdigit(ncharseq[0])) {
1103 if (len > 0 && isdigit(str[0])) {
11111104 StrToNumResult<StorageType> strtoint_result =
1112 strtointeger<StorageType>(ncharseq.data(), 0);
1105 strtointeger<StorageType>(str, 0, len);
11131106 if (!strtoint_result.has_error())
11141107 nan_mantissa = strtoint_result.value;
11151108
1116 if (strtoint_result.parsed_len != static_cast<ptrdiff_t>(ncharseq.size()))
1109 if (strtoint_result.parsed_len != static_cast<ptrdiff_t>(len))
11171110 nan_mantissa = 0;
11181111 }
11191112
......@@ -1124,59 +1117,44 @@ nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) {
11241117// is used as the backend for all of the string to float functions.
11251118// TODO: Add src_len member to match strtointeger.
11261119// TODO: Next, move from char* and length to string_view
1127template <class T>
1128LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
1120template <typename T, typename CharType>
1121LIBC_INLINE StrToNumResult<T>
1122strtofloatingpoint(const CharType *__restrict src) {
11291123 using FPBits = typename fputil::FPBits<T>;
11301124 using StorageType = typename FPBits::StorageType;
11311125
11321126 FPBits result = FPBits();
11331127 bool seen_digit = false;
1134 char sign = '+';
1135
11361128 int error = 0;
11371129
11381130 size_t index = first_non_whitespace(src);
1131 int sign = get_sign(src + index);
1132 bool is_positive = (sign >= 0);
1133 index += (sign != 0);
11391134
1140 if (src[index] == '+' || src[index] == '-') {
1141 sign = src[index];
1142 ++index;
1143 }
1144
1145 if (sign == '-') {
1135 if (sign < 0) {
11461136 result.set_sign(Sign::NEG);
11471137 }
11481138
1149 static constexpr char DECIMAL_POINT = '.';
1150 static const char *inf_string = "infinity";
1151 static const char *nan_string = "nan";
1152
1153 if (isdigit(src[index]) || src[index] == DECIMAL_POINT) { // regular number
1139 if (isdigit(src[index]) ||
1140 src[index] == constants<CharType>::DECIMAL_POINT) { // regular number
11541141 int base = 10;
1155 if (is_float_hex_start(src + index, DECIMAL_POINT)) {
1142 if (is_float_hex_start(src + index)) {
11561143 base = 16;
11571144 index += 2;
11581145 seen_digit = true;
11591146 }
11601147
11611148 RoundDirection round_direction = RoundDirection::Nearest;
1162
11631149 switch (fputil::quick_get_round()) {
11641150 case FE_TONEAREST:
11651151 round_direction = RoundDirection::Nearest;
11661152 break;
11671153 case FE_UPWARD:
1168 if (sign == '+') {
1169 round_direction = RoundDirection::Up;
1170 } else {
1171 round_direction = RoundDirection::Down;
1172 }
1154 round_direction = is_positive ? RoundDirection::Up : RoundDirection::Down;
11731155 break;
11741156 case FE_DOWNWARD:
1175 if (sign == '+') {
1176 round_direction = RoundDirection::Down;
1177 } else {
1178 round_direction = RoundDirection::Up;
1179 }
1157 round_direction = is_positive ? RoundDirection::Down : RoundDirection::Up;
11801158 break;
11811159 case FE_TOWARDZERO:
11821160 round_direction = RoundDirection::Down;
......@@ -1185,58 +1163,53 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
11851163
11861164 StrToNumResult<ExpandedFloat<T>> parse_result({0, 0});
11871165 if (base == 16) {
1188 parse_result = hexadecimal_string_to_float<T>(src + index, DECIMAL_POINT,
1189 round_direction);
1166 parse_result =
1167 hexadecimal_string_to_float<T>(src + index, round_direction);
11901168 } else { // base is 10
1191 parse_result = decimal_string_to_float<T>(src + index, DECIMAL_POINT,
1192 round_direction);
1169 parse_result = decimal_string_to_float<T>(src + index, round_direction);
11931170 }
11941171 seen_digit = parse_result.parsed_len != 0;
11951172 result.set_mantissa(parse_result.value.mantissa);
11961173 result.set_biased_exponent(parse_result.value.exponent);
11971174 index += parse_result.parsed_len;
11981175 error = parse_result.error;
1199 } else if (tolower(src[index]) == 'n') { // NaN
1200 if (tolower(src[index + 1]) == nan_string[1] &&
1201 tolower(src[index + 2]) == nan_string[2]) {
1202 seen_digit = true;
1203 index += 3;
1204 StorageType nan_mantissa = 0;
1205 // this handles the case of `NaN(n-character-sequence)`, where the
1206 // n-character-sequence is made of 0 or more letters, numbers, or
1207 // underscore characters in any order.
1208 if (src[index] == '(') {
1209 size_t left_paren = index;
1176 } else if (tolower_starts_with(src + index, 3,
1177 constants<CharType>::NAN_STRING)) {
1178 // NAN
1179 seen_digit = true;
1180 index += 3;
1181 StorageType nan_mantissa = 0;
1182 // this handles the case of `NaN(n-character-sequence)`, where the
1183 // n-character-sequence is made of 0 or more letters, numbers, or
1184 // underscore characters in any order.
1185 if (is_char_or_wchar(src[index], '(', L'(')) {
1186 size_t left_paren = index;
1187 ++index;
1188 while (isalnum(src[index]) || is_char_or_wchar(src[index], '_', L'_'))
12101189 ++index;
1211 while (isalnum(src[index]) || src[index] == '_')
1212 ++index;
1213 if (src[index] == ')') {
1214 ++index;
1215 nan_mantissa = nan_mantissa_from_ncharseq<T>(
1216 cpp::string_view(src + (left_paren + 1), index - left_paren - 2));
1217 } else {
1218 index = left_paren;
1219 }
1220 }
1221 result = FPBits(result.quiet_nan(result.sign(), nan_mantissa));
1222 }
1223 } else if (tolower(src[index]) == 'i') { // INF
1224 if (tolower(src[index + 1]) == inf_string[1] &&
1225 tolower(src[index + 2]) == inf_string[2]) {
1226 seen_digit = true;
1227 result = FPBits(result.inf(result.sign()));
1228 if (tolower(src[index + 3]) == inf_string[3] &&
1229 tolower(src[index + 4]) == inf_string[4] &&
1230 tolower(src[index + 5]) == inf_string[5] &&
1231 tolower(src[index + 6]) == inf_string[6] &&
1232 tolower(src[index + 7]) == inf_string[7]) {
1233 // if the string is "INFINITY" then consume 8 characters.
1234 index += 8;
1190 if (is_char_or_wchar(src[index], ')', L')')) {
1191 ++index;
1192 nan_mantissa = nan_mantissa_from_ncharseq<T>(src + (left_paren + 1),
1193 index - left_paren - 2);
12351194 } else {
1236 index += 3;
1195 index = left_paren;
12371196 }
12381197 }
1198 result = FPBits(result.quiet_nan(result.sign(), nan_mantissa));
1199 } else if (tolower_starts_with(src + index, 8,
1200 constants<CharType>::INF_STRING)) {
1201 // INFINITY
1202 seen_digit = true;
1203 result = FPBits(result.inf(result.sign()));
1204 index += 8;
1205 } else if (tolower_starts_with(src + index, 3,
1206 constants<CharType>::INF_STRING)) {
1207 // INF
1208 seen_digit = true;
1209 result = FPBits(result.inf(result.sign()));
1210 index += 3;
12391211 }
1212
12401213 if (!seen_digit) { // If there is nothing to actually parse, then return 0.
12411214 return {T(0), 0, error};
12421215 }
......@@ -1263,7 +1236,7 @@ template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
12631236 ++index;
12641237
12651238 if (arg[index] == '\0')
1266 nan_mantissa = nan_mantissa_from_ncharseq<T>(cpp::string_view(arg, index));
1239 nan_mantissa = nan_mantissa_from_ncharseq<T>(arg, index);
12671240
12681241 result = FPBits::quiet_nan(Sign::POS, nan_mantissa);
12691242 return {result.get_val(), 0, error};
lib/libcxx/libc/src/__support/str_to_integer.h+39-27
......@@ -25,36 +25,51 @@
2525#include "src/__support/macros/config.h"
2626#include "src/__support/str_to_num_result.h"
2727#include "src/__support/uint128.h"
28#include "src/__support/wctype_utils.h"
2829
2930namespace LIBC_NAMESPACE_DECL {
3031namespace internal {
3132
3233// Returns the idx to the first character in src that is not a whitespace
3334// character (as determined by isspace())
35template <typename CharType>
3436LIBC_INLINE size_t
35first_non_whitespace(const char *__restrict src,
37first_non_whitespace(const CharType *__restrict src,
3638 size_t src_len = cpp::numeric_limits<size_t>::max()) {
3739 size_t src_cur = 0;
38 while (src_cur < src_len && internal::isspace(src[src_cur])) {
39 ++src_cur;
40 }
40 for (; src_cur < src_len && internal::isspace(src[src_cur]); ++src_cur)
41 ;
4142 return src_cur;
4243}
4344
45// Returns +1, -1, or 0 if 'src' starts with (respectively)
46// plus sign, minus sign, or neither.
47template <typename CharType>
48LIBC_INLINE static int get_sign(const CharType *__restrict src) {
49 if (is_char_or_wchar(src[0], '+', L'+'))
50 return 1;
51 if (is_char_or_wchar(src[0], '-', L'-'))
52 return -1;
53 return 0;
54}
55
4456// checks if the next 3 characters of the string pointer are the start of a
4557// hexadecimal number. Does not advance the string pointer.
46LIBC_INLINE bool
47is_hex_start(const char *__restrict src,
48 size_t src_len = cpp::numeric_limits<size_t>::max()) {
58template <typename CharType>
59LIBC_INLINE static bool is_hex_start(const CharType *__restrict src,
60 size_t src_len) {
4961 if (src_len < 3)
5062 return false;
51 return *src == '0' && tolower(*(src + 1)) == 'x' && isalnum(*(src + 2)) &&
52 b36_char_to_int(*(src + 2)) < 16;
63 return is_char_or_wchar(src[0], '0', L'0') &&
64 is_char_or_wchar(tolower(src[1]), 'x', L'x') && isalnum(src[2]) &&
65 b36_char_to_int(src[2]) < 16;
5366}
5467
5568// Takes the address of the string pointer and parses the base from the start of
5669// it.
57LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) {
70template <typename CharType>
71LIBC_INLINE static int infer_base(const CharType *__restrict src,
72 size_t src_len) {
5873 // A hexadecimal number is defined as "the prefix 0x or 0X followed by a
5974 // sequence of the decimal digits and the letters a (or A) through f (or F)
6075 // with values 10 through 15 respectively." (C standard 6.4.4.1)
......@@ -63,8 +78,9 @@ LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) {
6378 // An octal number is defined as "the prefix 0 optionally followed by a
6479 // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any
6580 // number that starts with 0, including just 0, is an octal number.
66 if (src_len > 0 && src[0] == '0')
81 if (src_len > 0 && is_char_or_wchar(src[0], '0', L'0')) {
6782 return 8;
83 }
6884 // A decimal number is defined as beginning "with a nonzero digit and
6985 // consist[ing] of a sequence of decimal digits." (C standard 6.4.4.1)
7086 return 10;
......@@ -77,32 +93,27 @@ LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) {
7793// -----------------------------------------------------------------------------
7894// Takes a pointer to a string and the base to convert to. This function is used
7995// as the backend for all of the string to int functions.
80template <class T>
96template <typename T, typename CharType>
8197LIBC_INLINE StrToNumResult<T>
82strtointeger(const char *__restrict src, int base,
98strtointeger(const CharType *__restrict src, int base,
8399 const size_t src_len = cpp::numeric_limits<size_t>::max()) {
84100 using ResultType = make_integral_or_big_int_unsigned_t<T>;
85101
86 ResultType result = 0;
87
88 bool is_number = false;
89 size_t src_cur = 0;
90 int error_val = 0;
91
92102 if (src_len == 0)
93103 return {0, 0, 0};
94104
95105 if (base < 0 || base == 1 || base > 36)
96106 return {0, 0, EINVAL};
97107
98 src_cur = first_non_whitespace(src, src_len);
99
100 char result_sign = '+';
101 if (src[src_cur] == '+' || src[src_cur] == '-') {
102 result_sign = src[src_cur];
103 ++src_cur;
108 size_t src_cur = first_non_whitespace(src, src_len);
109 if (src_cur == src_len) {
110 return {0, 0, 0};
104111 }
105112
113 int sign = get_sign(src + src_cur);
114 bool is_positive = (sign >= 0);
115 src_cur += (sign != 0);
116
106117 if (base == 0)
107118 base = infer_base(src + src_cur, src_len - src_cur);
108119
......@@ -110,8 +121,6 @@ strtointeger(const char *__restrict src, int base,
110121 src_cur = src_cur + 2;
111122
112123 constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>;
113 const bool is_positive = (result_sign == '+');
114
115124 ResultType constexpr NEGATIVE_MAX =
116125 !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1
117126 : cpp::numeric_limits<T>::max();
......@@ -120,6 +129,9 @@ strtointeger(const char *__restrict src, int base,
120129 ResultType const abs_max_div_by_base =
121130 abs_max / static_cast<ResultType>(base);
122131
132 bool is_number = false;
133 int error_val = 0;
134 ResultType result = 0;
123135 while (src_cur < src_len && isalnum(src[src_cur])) {
124136 int cur_digit = b36_char_to_int(src[src_cur]);
125137 if (cur_digit >= base)
lib/libcxx/libc/src/__support/wctype_utils.h created+588
......@@ -0,0 +1,588 @@
1//===-- Collection of utils for implementing wide char functions --*-C++-*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_SRC___SUPPORT_WCTYPE_UTILS_H
10#define LLVM_LIBC_SRC___SUPPORT_WCTYPE_UTILS_H
11
12#include "hdr/types/wchar_t.h"
13#include "src/__support/macros/attributes.h" // LIBC_INLINE
14#include "src/__support/macros/config.h"
15
16namespace LIBC_NAMESPACE_DECL {
17namespace internal {
18
19// -----------------------------------------------------------------------------
20// ****************** WARNING ******************
21// ****************** DO NOT TRY TO OPTIMIZE THESE FUNCTIONS! ******************
22// -----------------------------------------------------------------------------
23// This switch/case form is easier for the compiler to understand, and is
24// optimized into a form that is almost always the same as or better than
25// versions written by hand (see https://godbolt.org/z/qvrebqvvr). Also this
26// form makes these functions encoding independent. If you want to rewrite these
27// functions, make sure you have benchmarks to show your new solution is faster,
28// as well as a way to support non-ASCII character encodings.
29
30// Similarly, do not change these fumarks to show your new solution is faster,
31// as well as a way to support non-Anctions to use case ranges. e.g.
32// bool islower(wchar_t ch) {
33// switch(ch) {
34// case L'a'...L'z':
35// return true;
36// }
37// }
38// This assumes the character ranges are contiguous, which they aren't in
39// EBCDIC. Technically we could use some smaller ranges, but that's even harder
40// to read.
41
42LIBC_INLINE static constexpr bool islower(wchar_t wch) {
43 switch (wch) {
44 case L'a':
45 case L'b':
46 case L'c':
47 case L'd':
48 case L'e':
49 case L'f':
50 case L'g':
51 case L'h':
52 case L'i':
53 case L'j':
54 case L'k':
55 case L'l':
56 case L'm':
57 case L'n':
58 case L'o':
59 case L'p':
60 case L'q':
61 case L'r':
62 case L's':
63 case L't':
64 case L'u':
65 case L'v':
66 case L'w':
67 case L'x':
68 case L'y':
69 case L'z':
70 return true;
71 default:
72 return false;
73 }
74}
75
76LIBC_INLINE static constexpr bool isupper(wchar_t wch) {
77 switch (wch) {
78 case L'A':
79 case L'B':
80 case L'C':
81 case L'D':
82 case L'E':
83 case L'F':
84 case L'G':
85 case L'H':
86 case L'I':
87 case L'J':
88 case L'K':
89 case L'L':
90 case L'M':
91 case L'N':
92 case L'O':
93 case L'P':
94 case L'Q':
95 case L'R':
96 case L'S':
97 case L'T':
98 case L'U':
99 case L'V':
100 case L'W':
101 case L'X':
102 case L'Y':
103 case L'Z':
104 return true;
105 default:
106 return false;
107 }
108}
109
110LIBC_INLINE static constexpr bool isdigit(wchar_t wch) {
111 switch (wch) {
112 case L'0':
113 case L'1':
114 case L'2':
115 case L'3':
116 case L'4':
117 case L'5':
118 case L'6':
119 case L'7':
120 case L'8':
121 case L'9':
122 return true;
123 default:
124 return false;
125 }
126}
127
128LIBC_INLINE static constexpr wchar_t tolower(wchar_t wch) {
129 switch (wch) {
130 case L'A':
131 return L'a';
132 case L'B':
133 return L'b';
134 case L'C':
135 return L'c';
136 case L'D':
137 return L'd';
138 case L'E':
139 return L'e';
140 case L'F':
141 return L'f';
142 case L'G':
143 return L'g';
144 case L'H':
145 return L'h';
146 case L'I':
147 return L'i';
148 case L'J':
149 return L'j';
150 case L'K':
151 return L'k';
152 case L'L':
153 return L'l';
154 case L'M':
155 return L'm';
156 case L'N':
157 return L'n';
158 case L'O':
159 return L'o';
160 case L'P':
161 return L'p';
162 case L'Q':
163 return L'q';
164 case L'R':
165 return L'r';
166 case L'S':
167 return L's';
168 case L'T':
169 return L't';
170 case L'U':
171 return L'u';
172 case L'V':
173 return L'v';
174 case L'W':
175 return L'w';
176 case L'X':
177 return L'x';
178 case L'Y':
179 return L'y';
180 case L'Z':
181 return L'z';
182 default:
183 return wch;
184 }
185}
186
187LIBC_INLINE static constexpr wchar_t toupper(wchar_t wch) {
188 switch (wch) {
189 case L'a':
190 return L'A';
191 case L'b':
192 return L'B';
193 case L'c':
194 return L'C';
195 case L'd':
196 return L'D';
197 case L'e':
198 return L'E';
199 case L'f':
200 return L'F';
201 case L'g':
202 return L'G';
203 case L'h':
204 return L'H';
205 case L'i':
206 return L'I';
207 case L'j':
208 return L'J';
209 case L'k':
210 return L'K';
211 case L'l':
212 return L'L';
213 case L'm':
214 return L'M';
215 case L'n':
216 return L'N';
217 case L'o':
218 return L'O';
219 case L'p':
220 return L'P';
221 case L'q':
222 return L'Q';
223 case L'r':
224 return L'R';
225 case L's':
226 return L'S';
227 case L't':
228 return L'T';
229 case L'u':
230 return L'U';
231 case L'v':
232 return L'V';
233 case L'w':
234 return L'W';
235 case L'x':
236 return L'X';
237 case L'y':
238 return L'Y';
239 case L'z':
240 return L'Z';
241 default:
242 return wch;
243 }
244}
245
246LIBC_INLINE static constexpr bool isalpha(wchar_t wch) {
247 switch (wch) {
248 case L'a':
249 case L'b':
250 case L'c':
251 case L'd':
252 case L'e':
253 case L'f':
254 case L'g':
255 case L'h':
256 case L'i':
257 case L'j':
258 case L'k':
259 case L'l':
260 case L'm':
261 case L'n':
262 case L'o':
263 case L'p':
264 case L'q':
265 case L'r':
266 case L's':
267 case L't':
268 case L'u':
269 case L'v':
270 case L'w':
271 case L'x':
272 case L'y':
273 case L'z':
274 case L'A':
275 case L'B':
276 case L'C':
277 case L'D':
278 case L'E':
279 case L'F':
280 case L'G':
281 case L'H':
282 case L'I':
283 case L'J':
284 case L'K':
285 case L'L':
286 case L'M':
287 case L'N':
288 case L'O':
289 case L'P':
290 case L'Q':
291 case L'R':
292 case L'S':
293 case L'T':
294 case L'U':
295 case L'V':
296 case L'W':
297 case L'X':
298 case L'Y':
299 case L'Z':
300 return true;
301 default:
302 return false;
303 }
304}
305
306LIBC_INLINE static constexpr bool isalnum(wchar_t wch) {
307 switch (wch) {
308 case L'a':
309 case L'b':
310 case L'c':
311 case L'd':
312 case L'e':
313 case L'f':
314 case L'g':
315 case L'h':
316 case L'i':
317 case L'j':
318 case L'k':
319 case L'l':
320 case L'm':
321 case L'n':
322 case L'o':
323 case L'p':
324 case L'q':
325 case L'r':
326 case L's':
327 case L't':
328 case L'u':
329 case L'v':
330 case L'w':
331 case L'x':
332 case L'y':
333 case L'z':
334 case L'A':
335 case L'B':
336 case L'C':
337 case L'D':
338 case L'E':
339 case L'F':
340 case L'G':
341 case L'H':
342 case L'I':
343 case L'J':
344 case L'K':
345 case L'L':
346 case L'M':
347 case L'N':
348 case L'O':
349 case L'P':
350 case L'Q':
351 case L'R':
352 case L'S':
353 case L'T':
354 case L'U':
355 case L'V':
356 case L'W':
357 case L'X':
358 case L'Y':
359 case L'Z':
360 case L'0':
361 case L'1':
362 case L'2':
363 case L'3':
364 case L'4':
365 case L'5':
366 case L'6':
367 case L'7':
368 case L'8':
369 case L'9':
370 return true;
371 default:
372 return false;
373 }
374}
375
376LIBC_INLINE static constexpr int b36_char_to_int(wchar_t wch) {
377 switch (wch) {
378 case L'0':
379 return 0;
380 case L'1':
381 return 1;
382 case L'2':
383 return 2;
384 case L'3':
385 return 3;
386 case L'4':
387 return 4;
388 case L'5':
389 return 5;
390 case L'6':
391 return 6;
392 case L'7':
393 return 7;
394 case L'8':
395 return 8;
396 case L'9':
397 return 9;
398 case L'a':
399 case L'A':
400 return 10;
401 case L'b':
402 case L'B':
403 return 11;
404 case L'c':
405 case L'C':
406 return 12;
407 case L'd':
408 case L'D':
409 return 13;
410 case L'e':
411 case L'E':
412 return 14;
413 case L'f':
414 case L'F':
415 return 15;
416 case L'g':
417 case L'G':
418 return 16;
419 case L'h':
420 case L'H':
421 return 17;
422 case L'i':
423 case L'I':
424 return 18;
425 case L'j':
426 case L'J':
427 return 19;
428 case L'k':
429 case L'K':
430 return 20;
431 case L'l':
432 case L'L':
433 return 21;
434 case L'm':
435 case L'M':
436 return 22;
437 case L'n':
438 case L'N':
439 return 23;
440 case L'o':
441 case L'O':
442 return 24;
443 case L'p':
444 case L'P':
445 return 25;
446 case L'q':
447 case L'Q':
448 return 26;
449 case L'r':
450 case L'R':
451 return 27;
452 case L's':
453 case L'S':
454 return 28;
455 case L't':
456 case L'T':
457 return 29;
458 case L'u':
459 case L'U':
460 return 30;
461 case L'v':
462 case L'V':
463 return 31;
464 case L'w':
465 case L'W':
466 return 32;
467 case L'x':
468 case L'X':
469 return 33;
470 case L'y':
471 case L'Y':
472 return 34;
473 case L'z':
474 case L'Z':
475 return 35;
476 default:
477 return 0;
478 }
479}
480
481LIBC_INLINE static constexpr wchar_t int_to_b36_wchar(int num) {
482 // Can't actually use LIBC_ASSERT here because it depends on integer_to_string
483 // which depends on this.
484
485 // LIBC_ASSERT(num < 36);
486 switch (num) {
487 case 0:
488 return L'0';
489 case 1:
490 return L'1';
491 case 2:
492 return L'2';
493 case 3:
494 return L'3';
495 case 4:
496 return L'4';
497 case 5:
498 return L'5';
499 case 6:
500 return L'6';
501 case 7:
502 return L'7';
503 case 8:
504 return L'8';
505 case 9:
506 return L'9';
507 case 10:
508 return L'a';
509 case 11:
510 return L'b';
511 case 12:
512 return L'c';
513 case 13:
514 return L'd';
515 case 14:
516 return L'e';
517 case 15:
518 return L'f';
519 case 16:
520 return L'g';
521 case 17:
522 return L'h';
523 case 18:
524 return L'i';
525 case 19:
526 return L'j';
527 case 20:
528 return L'k';
529 case 21:
530 return L'l';
531 case 22:
532 return L'm';
533 case 23:
534 return L'n';
535 case 24:
536 return L'o';
537 case 25:
538 return L'p';
539 case 26:
540 return L'q';
541 case 27:
542 return L'r';
543 case 28:
544 return L's';
545 case 29:
546 return L't';
547 case 30:
548 return L'u';
549 case 31:
550 return L'v';
551 case 32:
552 return L'w';
553 case 33:
554 return L'x';
555 case 34:
556 return L'y';
557 case 35:
558 return L'z';
559 default:
560 return L'!';
561 }
562}
563
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 character
579// values, when input can be of a regular or a wide character type.
580LIBC_INLINE static constexpr bool
581is_char_or_wchar(wchar_t ch, [[maybe_unused]] char, wchar_t wc_value) {
582 return (ch == wc_value);
583}
584
585} // namespace internal
586} // namespace LIBC_NAMESPACE_DECL
587
588#endif // LLVM_LIBC_SRC___SUPPORT_WCTYPE_UTILS_H