authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-07-16 10:52:18+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-08-30 06:36:41+02:00
logc34fc8f19884ebe551b1dea9b8061efd3680848a
treea5a1517fd255f3c491d1023cff84769fb0206383
parentd9f0fbf9838060b1e8c2ec0df21b43e75430350f
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

llvm-libc: update to LLVM 21

Still only the subset needed for libcxx.

24 files changed, 313 insertions(+), 130 deletions(-)

lib/libcxx/libc/include/llvm-libc-macros/stdfix-macros.h+39
...@@ -323,6 +323,45 @@...@@ -323,6 +323,45 @@
323#define ULACCUM_EPSILON 0x1.0p-32ULK323#define ULACCUM_EPSILON 0x1.0p-32ULK
324#endif // ULACCUM_EPSILON324#endif // ULACCUM_EPSILON
325325
326#define absfx(x) \
327 _Generic((x), \
328 fract: absr, \
329 short fract: abshr, \
330 long fract: abslr, \
331 accum: absk, \
332 short accum: abshk, \
333 long accum: abslk)(x)
334
335#define countlsfx(x) \
336 _Generic((x), \
337 fract: countlsr, \
338 short fract: countlshr, \
339 long fract: countlslr, \
340 accum: countlsk, \
341 short accum: countlshk, \
342 long accum: countlslk, \
343 unsigned fract: countlsur, \
344 unsigned short fract: countlsuhr, \
345 unsigned long fract: countlsulr, \
346 unsigned accum: countlsuk, \
347 unsigned short accum: countlsuhk, \
348 unsigned long accum: countlsulk)(x)
349
350#define roundfx(x, y) \
351 _Generic((x), \
352 fract: roundr, \
353 short fract: roundhr, \
354 long fract: roundlr, \
355 accum: roundk, \
356 short accum: roundhk, \
357 long accum: roundlk, \
358 unsigned fract: roundur, \
359 unsigned short fract: rounduhr, \
360 unsigned long fract: roundulr, \
361 unsigned accum: rounduk, \
362 unsigned short accum: rounduhk, \
363 unsigned long accum: roundulk)(x, y)
364
326#endif // LIBC_COMPILER_HAS_FIXED_POINT365#endif // LIBC_COMPILER_HAS_FIXED_POINT
327366
328#endif // LLVM_LIBC_MACROS_STDFIX_MACROS_H367#endif // LLVM_LIBC_MACROS_STDFIX_MACROS_H
lib/libcxx/libc/shared/fp_bits.h+1
...@@ -9,6 +9,7 @@...@@ -9,6 +9,7 @@
9#ifndef LLVM_LIBC_SHARED_FP_BITS_H9#ifndef LLVM_LIBC_SHARED_FP_BITS_H
10#define LLVM_LIBC_SHARED_FP_BITS_H10#define LLVM_LIBC_SHARED_FP_BITS_H
1111
12#include "libc_common.h"
12#include "src/__support/FPUtil/FPBits.h"13#include "src/__support/FPUtil/FPBits.h"
1314
14namespace LIBC_NAMESPACE_DECL {15namespace LIBC_NAMESPACE_DECL {
lib/libcxx/libc/shared/libc_common.h created+26
...@@ -0,0 +1,26 @@
1//===-- Common defines for sharing LLVM libc with LLVM projects -*- 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_SHARED_LIBC_COMMON_H
10#define LLVM_LIBC_SHARED_LIBC_COMMON_H
11
12// Use system errno.
13#ifdef LIBC_ERRNO_MODE
14#if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SYSTEM_INLINE
15#error \
16 "LIBC_ERRNO_MODE was set to something different from LIBC_ERRNO_MODE_SYSTEM_INLINE."
17#endif // LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SYSTEM_INLINE
18#else
19#define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM_INLINE
20#endif // LIBC_ERRNO_MODE
21
22#ifndef LIBC_NAMESPACE
23#define LIBC_NAMESPACE __llvm_libc
24#endif // LIBC_NAMESPACE
25
26#endif // LLVM_LIBC_SHARED_LIBC_COMMON_H
lib/libcxx/libc/shared/str_to_float.h+1
...@@ -9,6 +9,7 @@...@@ -9,6 +9,7 @@
9#ifndef LLVM_LIBC_SHARED_STR_TO_FLOAT_H9#ifndef LLVM_LIBC_SHARED_STR_TO_FLOAT_H
10#define LLVM_LIBC_SHARED_STR_TO_FLOAT_H10#define LLVM_LIBC_SHARED_STR_TO_FLOAT_H
1111
12#include "libc_common.h"
12#include "src/__support/str_to_float.h"13#include "src/__support/str_to_float.h"
1314
14namespace LIBC_NAMESPACE_DECL {15namespace LIBC_NAMESPACE_DECL {
lib/libcxx/libc/shared/str_to_integer.h+1
...@@ -9,6 +9,7 @@...@@ -9,6 +9,7 @@
9#ifndef LLVM_LIBC_SHARED_STR_TO_INTEGER_H9#ifndef LLVM_LIBC_SHARED_STR_TO_INTEGER_H
10#define LLVM_LIBC_SHARED_STR_TO_INTEGER_H10#define LLVM_LIBC_SHARED_STR_TO_INTEGER_H
1111
12#include "libc_common.h"
12#include "src/__support/str_to_integer.h"13#include "src/__support/str_to_integer.h"
1314
14namespace LIBC_NAMESPACE_DECL {15namespace LIBC_NAMESPACE_DECL {
lib/libcxx/libc/src/__support/CPP/bit.h+8-8
...@@ -101,7 +101,7 @@ countr_zero(T value) {...@@ -101,7 +101,7 @@ countr_zero(T value) {
101 shift >>= 1;101 shift >>= 1;
102 mask >>= shift;102 mask >>= shift;
103 }103 }
104 return zero_bits;104 return static_cast<int>(zero_bits);
105}105}
106#if __has_builtin(__builtin_ctzs)106#if __has_builtin(__builtin_ctzs)
107ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs)107ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs)
...@@ -140,7 +140,7 @@ countl_zero(T value) {...@@ -140,7 +140,7 @@ countl_zero(T value) {
140 else140 else
141 zero_bits |= shift;141 zero_bits |= shift;
142 }142 }
143 return zero_bits;143 return static_cast<int>(zero_bits);
144}144}
145#if __has_builtin(__builtin_clzs)145#if __has_builtin(__builtin_clzs)
146ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs)146ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs)
...@@ -162,7 +162,7 @@ ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll)...@@ -162,7 +162,7 @@ ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll)
162template <typename T>162template <typename T>
163[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>163[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
164countl_one(T value) {164countl_one(T value) {
165 return cpp::countl_zero<T>(~value);165 return cpp::countl_zero<T>(static_cast<T>(~value));
166}166}
167167
168/// Count the number of ones from the least significant bit to the first168/// Count the number of ones from the least significant bit to the first
...@@ -175,7 +175,7 @@ countl_one(T value) {...@@ -175,7 +175,7 @@ countl_one(T value) {
175template <typename T>175template <typename T>
176[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>176[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
177countr_one(T value) {177countr_one(T value) {
178 return cpp::countr_zero<T>(~value);178 return cpp::countr_zero<T>(static_cast<T>(~value));
179}179}
180180
181/// Returns the number of bits needed to represent value if value is nonzero.181/// Returns the number of bits needed to represent value if value is nonzero.
...@@ -226,25 +226,25 @@ rotr(T value, int rotate);...@@ -226,25 +226,25 @@ rotr(T value, int rotate);
226template <typename T>226template <typename T>
227[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>227[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
228rotl(T value, int rotate) {228rotl(T value, int rotate) {
229 constexpr unsigned N = cpp::numeric_limits<T>::digits;229 constexpr int N = cpp::numeric_limits<T>::digits;
230 rotate = rotate % N;230 rotate = rotate % N;
231 if (!rotate)231 if (!rotate)
232 return value;232 return value;
233 if (rotate < 0)233 if (rotate < 0)
234 return cpp::rotr<T>(value, -rotate);234 return cpp::rotr<T>(value, -rotate);
235 return (value << rotate) | (value >> (N - rotate));235 return static_cast<T>((value << rotate) | (value >> (N - rotate)));
236}236}
237237
238template <typename T>238template <typename T>
239[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>239[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
240rotr(T value, int rotate) {240rotr(T value, int rotate) {
241 constexpr unsigned N = cpp::numeric_limits<T>::digits;241 constexpr int N = cpp::numeric_limits<T>::digits;
242 rotate = rotate % N;242 rotate = rotate % N;
243 if (!rotate)243 if (!rotate)
244 return value;244 return value;
245 if (rotate < 0)245 if (rotate < 0)
246 return cpp::rotl<T>(value, -rotate);246 return cpp::rotl<T>(value, -rotate);
247 return (value >> rotate) | (value << (N - rotate));247 return static_cast<T>((value >> rotate) | (value << (N - rotate)));
248}248}
249249
250// TODO: Do we need this function at all? How is it different from250// TODO: Do we need this function at all? How is it different from
lib/libcxx/libc/src/__support/CPP/string_view.h+4-2
...@@ -9,6 +9,7 @@...@@ -9,6 +9,7 @@
9#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H9#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
10#define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H10#define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
1111
12#include "limits.h"
12#include "src/__support/common.h"13#include "src/__support/common.h"
13#include "src/__support/macros/config.h"14#include "src/__support/macros/config.h"
1415
...@@ -40,7 +41,7 @@ private:...@@ -40,7 +41,7 @@ private:
40 LIBC_INLINE static constexpr size_t length(const char *Str) {41 LIBC_INLINE static constexpr size_t length(const char *Str) {
41 for (const char *End = Str;; ++End)42 for (const char *End = Str;; ++End)
42 if (*End == '\0')43 if (*End == '\0')
43 return End - Str;44 return static_cast<size_t>(End - Str);
44 }45 }
4546
46 LIBC_INLINE bool equals(string_view Other) const {47 LIBC_INLINE bool equals(string_view Other) const {
...@@ -61,7 +62,8 @@ public:...@@ -61,7 +62,8 @@ public:
6162
62 // special value equal to the maximum value representable by the type63 // special value equal to the maximum value representable by the type
63 // size_type.64 // size_type.
64 LIBC_INLINE_VAR static constexpr size_t npos = -1;65 LIBC_INLINE_VAR static constexpr size_t npos =
66 cpp::numeric_limits<size_t>::max();
6567
66 LIBC_INLINE constexpr string_view() : Data(nullptr), Len(0) {}68 LIBC_INLINE constexpr string_view() : Data(nullptr), Len(0) {}
6769
lib/libcxx/libc/src/__support/CPP/type_traits/is_floating_point.h+2-1
...@@ -36,7 +36,8 @@ public:...@@ -36,7 +36,8 @@ public:
36 ,36 ,
37 float12837 float128
38#endif38#endif
39 >();39 ,
40 bfloat16>();
40};41};
41template <typename T>42template <typename T>
42LIBC_INLINE_VAR constexpr bool is_floating_point_v =43LIBC_INLINE_VAR constexpr bool is_floating_point_v =
lib/libcxx/libc/src/__support/CPP/type_traits/is_signed.h+24-1
...@@ -8,20 +8,43 @@...@@ -8,20 +8,43 @@
8#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H8#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H
9#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H9#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H
1010
11#include "include/llvm-libc-macros/stdfix-macros.h"
11#include "src/__support/CPP/type_traits/bool_constant.h"12#include "src/__support/CPP/type_traits/bool_constant.h"
12#include "src/__support/CPP/type_traits/is_arithmetic.h"13#include "src/__support/CPP/type_traits/is_arithmetic.h"
14#include "src/__support/CPP/type_traits/is_same.h"
15#include "src/__support/CPP/type_traits/remove_cv.h"
13#include "src/__support/macros/attributes.h"16#include "src/__support/macros/attributes.h"
14#include "src/__support/macros/config.h"17#include "src/__support/macros/config.h"
1518
16namespace LIBC_NAMESPACE_DECL {19namespace LIBC_NAMESPACE_DECL {
17namespace cpp {20namespace cpp {
1821
19// is_signed22#ifndef LIBC_COMPILER_HAS_FIXED_POINT
20template <typename T>23template <typename T>
21struct is_signed : bool_constant<(is_arithmetic_v<T> && (T(-1) < T(0)))> {24struct is_signed : bool_constant<(is_arithmetic_v<T> && (T(-1) < T(0)))> {
22 LIBC_INLINE constexpr operator bool() const { return is_signed::value; }25 LIBC_INLINE constexpr operator bool() const { return is_signed::value; }
23 LIBC_INLINE constexpr bool operator()() const { return is_signed::value; }26 LIBC_INLINE constexpr bool operator()() const { return is_signed::value; }
24};27};
28#else
29template <typename T> struct is_signed {
30private:
31 template <typename Head, typename... Args>
32 LIBC_INLINE static constexpr bool __is_unqualified_any_of() {
33 return (... || is_same_v<remove_cv_t<Head>, Args>);
34 }
35
36public:
37 LIBC_INLINE_VAR static constexpr bool value =
38 (is_arithmetic_v<T> && (T(-1) < T(0))) ||
39 __is_unqualified_any_of<T, short fract, fract, long fract, short accum,
40 accum, long accum, short sat fract, sat fract,
41 long sat fract, short sat accum, sat accum,
42 long sat accum>();
43 LIBC_INLINE constexpr operator bool() const { return is_signed::value; }
44 LIBC_INLINE constexpr bool operator()() const { return is_signed::value; }
45};
46#endif // LIBC_COMPILER_HAS_FIXED_POINT
47
25template <typename T>48template <typename T>
26LIBC_INLINE_VAR constexpr bool is_signed_v = is_signed<T>::value;49LIBC_INLINE_VAR constexpr bool is_signed_v = is_signed<T>::value;
2750
lib/libcxx/libc/src/__support/CPP/type_traits/is_unsigned.h+26-1
...@@ -8,20 +8,45 @@...@@ -8,20 +8,45 @@
8#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H8#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H
9#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H9#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H
1010
11#include "include/llvm-libc-macros/stdfix-macros.h"
11#include "src/__support/CPP/type_traits/bool_constant.h"12#include "src/__support/CPP/type_traits/bool_constant.h"
12#include "src/__support/CPP/type_traits/is_arithmetic.h"13#include "src/__support/CPP/type_traits/is_arithmetic.h"
14#include "src/__support/CPP/type_traits/is_same.h"
15#include "src/__support/CPP/type_traits/remove_cv.h"
13#include "src/__support/macros/attributes.h"16#include "src/__support/macros/attributes.h"
14#include "src/__support/macros/config.h"17#include "src/__support/macros/config.h"
1518
16namespace LIBC_NAMESPACE_DECL {19namespace LIBC_NAMESPACE_DECL {
17namespace cpp {20namespace cpp {
1821
19// is_unsigned22#ifndef LIBC_COMPILER_HAS_FIXED_POINT
20template <typename T>23template <typename T>
21struct is_unsigned : bool_constant<(is_arithmetic_v<T> && (T(-1) > T(0)))> {24struct is_unsigned : bool_constant<(is_arithmetic_v<T> && (T(-1) > T(0)))> {
22 LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; }25 LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; }
23 LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; }26 LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; }
24};27};
28#else
29template <typename T> struct is_unsigned {
30private:
31 template <typename Head, typename... Args>
32 LIBC_INLINE static constexpr bool __is_unqualified_any_of() {
33 return (... || is_same_v<remove_cv_t<Head>, Args>);
34 }
35
36public:
37 LIBC_INLINE_VAR static constexpr bool value =
38 (is_arithmetic_v<T> && (T(-1) > T(0))) ||
39 __is_unqualified_any_of<T, unsigned short fract, unsigned fract,
40 unsigned long fract, unsigned short accum,
41 unsigned accum, unsigned long accum,
42 unsigned short sat fract, unsigned sat fract,
43 unsigned long sat fract, unsigned short sat accum,
44 unsigned sat accum, unsigned long sat accum>();
45 LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; }
46 LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; }
47};
48#endif // LIBC_COMPILER_HAS_FIXED_POINT
49
25template <typename T>50template <typename T>
26LIBC_INLINE_VAR constexpr bool is_unsigned_v = is_unsigned<T>::value;51LIBC_INLINE_VAR constexpr bool is_unsigned_v = is_unsigned<T>::value;
2752
lib/libcxx/libc/src/__support/FPUtil/FPBits.h+15-4
...@@ -38,6 +38,7 @@ enum class FPType {...@@ -38,6 +38,7 @@ enum class FPType {
38 IEEE754_Binary64,38 IEEE754_Binary64,
39 IEEE754_Binary128,39 IEEE754_Binary128,
40 X86_Binary80,40 X86_Binary80,
41 BFloat16
41};42};
4243
43// The classes hierarchy is as follows:44// The classes hierarchy is as follows:
...@@ -138,6 +139,14 @@ template <> struct FPLayout<FPType::X86_Binary80> {...@@ -138,6 +139,14 @@ template <> struct FPLayout<FPType::X86_Binary80> {
138 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN - 1;139 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN - 1;
139};140};
140141
142template <> struct FPLayout<FPType::BFloat16> {
143 using StorageType = uint16_t;
144 LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
145 LIBC_INLINE_VAR static constexpr int EXP_LEN = 8;
146 LIBC_INLINE_VAR static constexpr int SIG_LEN = 7;
147 LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
148};
149
141// FPStorage derives useful constants from the FPLayout above.150// FPStorage derives useful constants from the FPLayout above.
142template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {151template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
143 using UP = FPLayout<fp_type>;152 using UP = FPLayout<fp_type>;
...@@ -247,11 +256,11 @@ protected:...@@ -247,11 +256,11 @@ protected:
247 using UP::UP;256 using UP::UP;
248257
249 LIBC_INLINE constexpr BiasedExponent(Exponent exp)258 LIBC_INLINE constexpr BiasedExponent(Exponent exp)
250 : UP(static_cast<int32_t>(exp) + EXP_BIAS) {}259 : UP(static_cast<uint32_t>(static_cast<int32_t>(exp) + EXP_BIAS)) {}
251260
252 // Cast operator to get convert from BiasedExponent to Exponent.261 // Cast operator to get convert from BiasedExponent to Exponent.
253 LIBC_INLINE constexpr operator Exponent() const {262 LIBC_INLINE constexpr operator Exponent() const {
254 return Exponent(UP::value - EXP_BIAS);263 return Exponent(static_cast<int32_t>(UP::value - EXP_BIAS));
255 }264 }
256265
257 LIBC_INLINE constexpr BiasedExponent &operator++() {266 LIBC_INLINE constexpr BiasedExponent &operator++() {
...@@ -686,7 +695,7 @@ public:...@@ -686,7 +695,7 @@ public:
686 }695 }
687696
688 LIBC_INLINE constexpr void set_biased_exponent(StorageType biased) {697 LIBC_INLINE constexpr void set_biased_exponent(StorageType biased) {
689 UP::set_biased_exponent(BiasedExponent((int32_t)biased));698 UP::set_biased_exponent(BiasedExponent(static_cast<uint32_t>(biased)));
690 }699 }
691700
692 LIBC_INLINE constexpr int get_exponent() const {701 LIBC_INLINE constexpr int get_exponent() const {
...@@ -757,7 +766,7 @@ public:...@@ -757,7 +766,7 @@ public:
757 result.set_significand(number);766 result.set_significand(number);
758 result.set_biased_exponent(static_cast<StorageType>(ep + 1));767 result.set_biased_exponent(static_cast<StorageType>(ep + 1));
759 } else {768 } else {
760 result.set_significand(number >> -ep);769 result.set_significand(number >> static_cast<unsigned>(-ep));
761 }770 }
762 return RetT(result.uintval());771 return RetT(result.uintval());
763 }772 }
...@@ -801,6 +810,8 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {...@@ -801,6 +810,8 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
801 else if constexpr (cpp::is_same_v<UnqualT, float128>)810 else if constexpr (cpp::is_same_v<UnqualT, float128>)
802 return FPType::IEEE754_Binary128;811 return FPType::IEEE754_Binary128;
803#endif812#endif
813 else if constexpr (cpp::is_same_v<UnqualT, bfloat16>)
814 return FPType::BFloat16;
804 else815 else
805 static_assert(cpp::always_false<UnqualT>, "Unsupported type");816 static_assert(cpp::always_false<UnqualT>, "Unsupported type");
806}817}
lib/libcxx/libc/src/__support/big_int.h+33-26
...@@ -241,7 +241,7 @@ LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst,...@@ -241,7 +241,7 @@ LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst,
241}241}
242242
243template <typename word, size_t N>243template <typename word, size_t N>
244LIBC_INLINE constexpr bool is_negative(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 using signed_word = cpp::make_signed_t<word>;
246 return cpp::bit_cast<signed_word>(array.back()) < 0;246 return cpp::bit_cast<signed_word>(array.back()) < 0;
247}247}
...@@ -284,8 +284,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,...@@ -284,8 +284,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
284 if (i < 0)284 if (i < 0)
285 return 0;285 return 0;
286 if (i >= int(N))286 if (i >= int(N))
287 return is_neg ? -1 : 0;287 return is_neg ? cpp::numeric_limits<word>::max() : 0;
288 return array[i];288 return array[static_cast<unsigned>(i)];
289 };289 };
290 const size_t index_offset = offset / WORD_BITS;290 const size_t index_offset = offset / WORD_BITS;
291 const size_t bit_offset = offset % WORD_BITS;291 const size_t bit_offset = offset % WORD_BITS;
...@@ -296,7 +296,7 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,...@@ -296,7 +296,7 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
296 for (size_t index = 0; index < N; ++index) {296 for (size_t index = 0; index < N; ++index) {
297 const word part1 = safe_get_at(index + index_offset);297 const word part1 = safe_get_at(index + index_offset);
298 const word part2 = safe_get_at(index + index_offset + 1);298 const word part2 = safe_get_at(index + index_offset + 1);
299 word &dst = out[at(index)];299 word &dst = out[static_cast<unsigned>(at(index))];
300 if (bit_offset == 0)300 if (bit_offset == 0)
301 dst = part1; // no crosstalk between parts.301 dst = part1; // no crosstalk between parts.
302 else if constexpr (direction == LEFT)302 else if constexpr (direction == LEFT)
...@@ -465,8 +465,7 @@ public:...@@ -465,8 +465,7 @@ public:
465 }465 }
466466
467 // Initialize the first word to |v| and the rest to 0.467 // 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> &&468 template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T>>>
469 !cpp::is_same_v<T, bool>>>
470 LIBC_INLINE constexpr BigInt(T v) {469 LIBC_INLINE constexpr BigInt(T v) {
471 constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT;470 constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT;
472 const bool is_neg = v < 0;471 const bool is_neg = v < 0;
...@@ -697,7 +696,8 @@ public:...@@ -697,7 +696,8 @@ public:
697 }696 }
698 BigInt quotient;697 BigInt quotient;
699 WordType x_word = static_cast<WordType>(x);698 WordType x_word = static_cast<WordType>(x);
700 constexpr size_t LOG2_WORD_SIZE = cpp::bit_width(WORD_SIZE) - 1;699 constexpr size_t LOG2_WORD_SIZE =
700 static_cast<size_t>(cpp::bit_width(WORD_SIZE) - 1);
701 constexpr size_t HALF_WORD_SIZE = WORD_SIZE >> 1;701 constexpr size_t HALF_WORD_SIZE = WORD_SIZE >> 1;
702 constexpr WordType HALF_MASK = ((WordType(1) << HALF_WORD_SIZE) - 1);702 constexpr WordType HALF_MASK = ((WordType(1) << HALF_WORD_SIZE) - 1);
703 // lower = smallest multiple of WORD_SIZE that is >= e.703 // lower = smallest multiple of WORD_SIZE that is >= e.
...@@ -866,7 +866,7 @@ public:...@@ -866,7 +866,7 @@ public:
866 LIBC_INLINE constexpr BigInt operator~() const {866 LIBC_INLINE constexpr BigInt operator~() const {
867 BigInt result;867 BigInt result;
868 for (size_t i = 0; i < WORD_COUNT; ++i)868 for (size_t i = 0; i < WORD_COUNT; ++i)
869 result[i] = ~val[i];869 result[i] = static_cast<WordType>(~val[i]);
870 return result;870 return result;
871 }871 }
872872
...@@ -936,6 +936,18 @@ public:...@@ -936,6 +936,18 @@ public:
936 // Return the i-th word of the number.936 // Return the i-th word of the number.
937 LIBC_INLINE constexpr WordType &operator[](size_t i) { return val[i]; }937 LIBC_INLINE constexpr WordType &operator[](size_t i) { return val[i]; }
938938
939 // Return the i-th bit of the number.
940 LIBC_INLINE constexpr bool get_bit(size_t i) const {
941 const size_t word_index = i / WORD_SIZE;
942 return 1 & (val[word_index] >> (i % WORD_SIZE));
943 }
944
945 // Set the i-th bit of the number.
946 LIBC_INLINE constexpr void set_bit(size_t i) {
947 const size_t word_index = i / WORD_SIZE;
948 val[word_index] |= WordType(1) << (i % WORD_SIZE);
949 }
950
939private:951private:
940 LIBC_INLINE friend constexpr int cmp(const BigInt &lhs, const BigInt &rhs) {952 LIBC_INLINE friend constexpr int cmp(const BigInt &lhs, const BigInt &rhs) {
941 constexpr auto compare = [](WordType a, WordType b) {953 constexpr auto compare = [](WordType a, WordType b) {
...@@ -955,7 +967,7 @@ private:...@@ -955,7 +967,7 @@ private:
955967
956 LIBC_INLINE constexpr void bitwise_not() {968 LIBC_INLINE constexpr void bitwise_not() {
957 for (auto &part : val)969 for (auto &part : val)
958 part = ~part;970 part = static_cast<WordType>(~part);
959 }971 }
960972
961 LIBC_INLINE constexpr void negate() {973 LIBC_INLINE constexpr void negate() {
...@@ -968,7 +980,7 @@ private:...@@ -968,7 +980,7 @@ private:
968 }980 }
969981
970 LIBC_INLINE constexpr void decrement() {982 LIBC_INLINE constexpr void decrement() {
971 multiword::add_with_carry(val, cpp::array<WordType, 1>{1});983 multiword::sub_with_borrow(val, cpp::array<WordType, 1>{1});
972 }984 }
973985
974 LIBC_INLINE constexpr void extend(size_t index, bool is_neg) {986 LIBC_INLINE constexpr void extend(size_t index, bool is_neg) {
...@@ -989,12 +1001,6 @@ private:...@@ -989,12 +1001,6 @@ private:
989 LIBC_INLINE constexpr void clear_msb() {1001 LIBC_INLINE constexpr void clear_msb() {
990 val.back() &= mask_trailing_ones<WordType, WORD_SIZE - 1>();1002 val.back() &= mask_trailing_ones<WordType, WORD_SIZE - 1>();
991 }1003 }
992
993 LIBC_INLINE constexpr void set_bit(size_t i) {
994 const size_t word_index = i / WORD_SIZE;
995 val[word_index] |= WordType(1) << (i % WORD_SIZE);
996 }
997
998 LIBC_INLINE constexpr static Division divide_unsigned(const BigInt &dividend,1004 LIBC_INLINE constexpr static Division divide_unsigned(const BigInt &dividend,
999 const BigInt &divider) {1005 const BigInt &divider) {
1000 BigInt remainder = dividend;1006 BigInt remainder = dividend;
...@@ -1003,12 +1009,12 @@ private:...@@ -1003,12 +1009,12 @@ private:
1003 BigInt subtractor = divider;1009 BigInt subtractor = divider;
1004 int cur_bit = multiword::countl_zero(subtractor.val) -1010 int cur_bit = multiword::countl_zero(subtractor.val) -
1005 multiword::countl_zero(remainder.val);1011 multiword::countl_zero(remainder.val);
1006 subtractor <<= cur_bit;1012 subtractor <<= static_cast<size_t>(cur_bit);
1007 for (; cur_bit >= 0 && remainder > 0; --cur_bit, subtractor >>= 1) {1013 for (; cur_bit >= 0 && remainder > 0; --cur_bit, subtractor >>= 1) {
1008 if (remainder < subtractor)1014 if (remainder < subtractor)
1009 continue;1015 continue;
1010 remainder -= subtractor;1016 remainder -= subtractor;
1011 quotient.set_bit(cur_bit);1017 quotient.set_bit(static_cast<size_t>(cur_bit));
1012 }1018 }
1013 }1019 }
1014 return Division{quotient, remainder};1020 return Division{quotient, remainder};
...@@ -1270,26 +1276,28 @@ rotr(T value, int rotate);...@@ -1270,26 +1276,28 @@ rotr(T value, int rotate);
1270template <typename T>1276template <typename T>
1271[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>1277[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
1272rotl(T value, int rotate) {1278rotl(T value, int rotate) {
1273 constexpr unsigned N = cpp::numeric_limits<T>::digits;1279 constexpr int N = cpp::numeric_limits<T>::digits;
1274 rotate = rotate % N;1280 rotate = rotate % N;
1275 if (!rotate)1281 if (!rotate)
1276 return value;1282 return value;
1277 if (rotate < 0)1283 if (rotate < 0)
1278 return cpp::rotr<T>(value, -rotate);1284 return cpp::rotr<T>(value, -rotate);
1279 return (value << rotate) | (value >> (N - rotate));1285 return (value << static_cast<size_t>(rotate)) |
1286 (value >> (N - static_cast<size_t>(rotate)));
1280}1287}
12811288
1282// Specialization of cpp::rotr ('bit.h') for BigInt.1289// Specialization of cpp::rotr ('bit.h') for BigInt.
1283template <typename T>1290template <typename T>
1284[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>1291[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
1285rotr(T value, int rotate) {1292rotr(T value, int rotate) {
1286 constexpr unsigned N = cpp::numeric_limits<T>::digits;1293 constexpr int N = cpp::numeric_limits<T>::digits;
1287 rotate = rotate % N;1294 rotate = rotate % N;
1288 if (!rotate)1295 if (!rotate)
1289 return value;1296 return value;
1290 if (rotate < 0)1297 if (rotate < 0)
1291 return cpp::rotl<T>(value, -rotate);1298 return cpp::rotl<T>(value, -rotate);
1292 return (value >> rotate) | (value << (N - rotate));1299 return (value >> static_cast<size_t>(rotate)) |
1300 (value << (N - static_cast<size_t>(rotate)));
1293}1301}
12941302
1295} // namespace cpp1303} // namespace cpp
...@@ -1306,7 +1314,7 @@ mask_trailing_ones() {...@@ -1306,7 +1314,7 @@ mask_trailing_ones() {
1306 T out; // zero initialized1314 T out; // zero initialized
1307 for (size_t i = 0; i <= QUOTIENT; ++i)1315 for (size_t i = 0; i <= QUOTIENT; ++i)
1308 out[i] = i < QUOTIENT1316 out[i] = i < QUOTIENT
1309 ? -11317 ? cpp::numeric_limits<typename T::word_type>::max()
1310 : mask_trailing_ones<typename T::word_type, REMAINDER>();1318 : mask_trailing_ones<typename T::word_type, REMAINDER>();
1311 return out;1319 return out;
1312}1320}
...@@ -1322,7 +1330,7 @@ LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() {...@@ -1322,7 +1330,7 @@ LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() {
1322 T out; // zero initialized1330 T out; // zero initialized
1323 for (size_t i = QUOTIENT; i < T::WORD_COUNT; ++i)1331 for (size_t i = QUOTIENT; i < T::WORD_COUNT; ++i)
1324 out[i] = i > QUOTIENT1332 out[i] = i > QUOTIENT
1325 ? -11333 ? cpp::numeric_limits<typename T::word_type>::max()
1326 : mask_leading_ones<typename T::word_type, REMAINDER>();1334 : mask_leading_ones<typename T::word_type, REMAINDER>();
1327 return out;1335 return out;
1328}1336}
...@@ -1375,8 +1383,7 @@ first_trailing_zero(T value) {...@@ -1375,8 +1383,7 @@ first_trailing_zero(T value) {
1375template <typename T>1383template <typename T>
1376[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>1384[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
1377first_trailing_one(T value) {1385first_trailing_one(T value) {
1378 return value == cpp::numeric_limits<T>::max() ? 01386 return value == 0 ? 0 : cpp::countr_zero(value) + 1;
1379 : cpp::countr_zero(value) + 1;
1380}1387}
13811388
1382} // namespace LIBC_NAMESPACE_DECL1389} // namespace LIBC_NAMESPACE_DECL
lib/libcxx/libc/src/__support/common.h+14-4
...@@ -37,17 +37,27 @@...@@ -37,17 +37,27 @@
3737
38#define LLVM_LIBC_ATTR(name) EXPAND_THEN_SECOND(LLVM_LIBC_FUNCTION_ATTR_##name)38#define LLVM_LIBC_ATTR(name) EXPAND_THEN_SECOND(LLVM_LIBC_FUNCTION_ATTR_##name)
3939
40// MacOS needs to be excluded because it does not support aliasing.40// At the moment, [[gnu::alias()]] is not supported on MacOS, and it is needed
41#if defined(LIBC_COPT_PUBLIC_PACKAGING) && (!defined(__APPLE__))41// to cleanly export and alias the C++ symbol `LIBC_NAMESPACE::func` with the C
42// symbol `func`. So for public packaging on MacOS, we will only export the C
43// symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`.
44#if defined(LIBC_COPT_PUBLIC_PACKAGING)
45#ifndef __APPLE__
42#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \46#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \
43 LLVM_LIBC_ATTR(name) \47 LLVM_LIBC_ATTR(name) \
44 LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \48 LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \
45 __##name##_impl__ __asm__(#name); \49 __##name##_impl__ __asm__(#name); \
46 decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \50 decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \
47 type __##name##_impl__ arglist51 type __##name##_impl__ arglist
48#else52#else // __APPLE__
53#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \
54 LLVM_LIBC_ATTR(name) \
55 LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) name asm("_" #name); \
56 type name arglist
57#endif // __APPLE__
58#else // LIBC_COPT_PUBLIC_PACKAGING
49#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) type name arglist59#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) type name arglist
50#endif60#endif // LIBC_COPT_PUBLIC_PACKAGING
5161
52// This extra layer of macro allows `name` to be a macro to rename a function.62// This extra layer of macro allows `name` to be a macro to rename a function.
53#define LLVM_LIBC_FUNCTION(type, name, arglist) \63#define LLVM_LIBC_FUNCTION(type, name, arglist) \
lib/libcxx/libc/src/__support/high_precision_decimal.h+7-7
...@@ -264,7 +264,7 @@ private:...@@ -264,7 +264,7 @@ private:
264 LIBC_INLINE void left_shift(uint32_t shift_amount) {264 LIBC_INLINE void left_shift(uint32_t shift_amount) {
265 uint32_t new_digits = this->get_num_new_digits(shift_amount);265 uint32_t new_digits = this->get_num_new_digits(shift_amount);
266266
267 int32_t read_index = this->num_digits - 1;267 int32_t read_index = static_cast<int32_t>(this->num_digits - 1);
268 uint32_t write_index = this->num_digits + new_digits;268 uint32_t write_index = this->num_digits + new_digits;
269269
270 uint64_t accumulator = 0;270 uint64_t accumulator = 0;
...@@ -329,7 +329,7 @@ public:...@@ -329,7 +329,7 @@ public:
329 if (saw_dot) {329 if (saw_dot) {
330 break;330 break;
331 }331 }
332 this->decimal_point = total_digits;332 this->decimal_point = static_cast<int32_t>(total_digits);
333 saw_dot = true;333 saw_dot = true;
334 } else {334 } else {
335 if (num_string[num_cur] == '0' && this->num_digits == 0) {335 if (num_string[num_cur] == '0' && this->num_digits == 0) {
...@@ -350,7 +350,7 @@ public:...@@ -350,7 +350,7 @@ public:
350 }350 }
351351
352 if (!saw_dot)352 if (!saw_dot)
353 this->decimal_point = total_digits;353 this->decimal_point = static_cast<int32_t>(total_digits);
354354
355 if (num_cur < num_len &&355 if (num_cur < num_len &&
356 (num_string[num_cur] == 'e' || num_string[num_cur] == 'E')) {356 (num_string[num_cur] == 'e' || num_string[num_cur] == 'E')) {
...@@ -393,7 +393,7 @@ public:...@@ -393,7 +393,7 @@ public:
393 this->left_shift(MAX_SHIFT_AMOUNT);393 this->left_shift(MAX_SHIFT_AMOUNT);
394 shift_amount -= MAX_SHIFT_AMOUNT;394 shift_amount -= MAX_SHIFT_AMOUNT;
395 }395 }
396 this->left_shift(shift_amount);396 this->left_shift(static_cast<uint32_t>(shift_amount));
397 }397 }
398 // Right398 // Right
399 else {399 else {
...@@ -401,7 +401,7 @@ public:...@@ -401,7 +401,7 @@ public:
401 this->right_shift(MAX_SHIFT_AMOUNT);401 this->right_shift(MAX_SHIFT_AMOUNT);
402 shift_amount += MAX_SHIFT_AMOUNT;402 shift_amount += MAX_SHIFT_AMOUNT;
403 }403 }
404 this->right_shift(-shift_amount);404 this->right_shift(static_cast<uint32_t>(-shift_amount));
405 }405 }
406 }406 }
407407
...@@ -424,8 +424,8 @@ public:...@@ -424,8 +424,8 @@ public:
424 result *= 10;424 result *= 10;
425 ++cur_digit;425 ++cur_digit;
426 }426 }
427 return result + static_cast<unsigned int>(427 return result +
428 this->should_round_up(this->decimal_point, round));428 static_cast<T>(this->should_round_up(this->decimal_point, round));
429 }429 }
430430
431 // Extra functions for testing.431 // Extra functions for testing.
lib/libcxx/libc/src/__support/libc_assert.h+1-1
...@@ -9,7 +9,6 @@...@@ -9,7 +9,6 @@
9#ifndef LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H9#ifndef LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H
10#define LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H10#define LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H
1111
12#include "src/__support/macros/config.h"
13#if defined(LIBC_COPT_USE_C_ASSERT) || !defined(LIBC_FULL_BUILD)12#if defined(LIBC_COPT_USE_C_ASSERT) || !defined(LIBC_FULL_BUILD)
1413
15// The build is configured to just use the public <assert.h> API14// The build is configured to just use the public <assert.h> API
...@@ -25,6 +24,7 @@...@@ -25,6 +24,7 @@
25#include "src/__support/OSUtil/io.h"24#include "src/__support/OSUtil/io.h"
26#include "src/__support/integer_to_string.h"25#include "src/__support/integer_to_string.h"
27#include "src/__support/macros/attributes.h" // For LIBC_INLINE26#include "src/__support/macros/attributes.h" // For LIBC_INLINE
27#include "src/__support/macros/config.h"
28#include "src/__support/macros/optimization.h" // For LIBC_UNLIKELY28#include "src/__support/macros/optimization.h" // For LIBC_UNLIKELY
2929
30namespace LIBC_NAMESPACE_DECL {30namespace LIBC_NAMESPACE_DECL {
lib/libcxx/libc/src/__support/macros/null_check.h+9
...@@ -19,10 +19,19 @@...@@ -19,10 +19,19 @@
19 if (LIBC_UNLIKELY((ptr) == nullptr)) \19 if (LIBC_UNLIKELY((ptr) == nullptr)) \
20 __builtin_trap(); \20 __builtin_trap(); \
21 } while (0)21 } while (0)
22#define LIBC_CRASH_ON_VALUE(var, value) \
23 do { \
24 if (LIBC_UNLIKELY((var) == (value))) \
25 __builtin_trap(); \
26 } while (0)
27
22#else28#else
23#define LIBC_CRASH_ON_NULLPTR(ptr) \29#define LIBC_CRASH_ON_NULLPTR(ptr) \
24 do { \30 do { \
25 } while (0)31 } while (0)
32#define LIBC_CRASH_ON_VALUE(var, value) \
33 do { \
34 } while (0)
26#endif35#endif
2736
28#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_NULL_CHECK_H37#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_NULL_CHECK_H
lib/libcxx/libc/src/__support/macros/optimization.h+16-1
...@@ -10,7 +10,7 @@...@@ -10,7 +10,7 @@
10#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H10#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H
11#define LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H11#define LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H
1212
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"
15#include "src/__support/macros/properties/compiler.h" // LIBC_COMPILER_IS_CLANG15#include "src/__support/macros/properties/compiler.h" // LIBC_COMPILER_IS_CLANG
1616
...@@ -30,8 +30,10 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {...@@ -30,8 +30,10 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
3030
31#if defined(LIBC_COMPILER_IS_CLANG)31#if defined(LIBC_COMPILER_IS_CLANG)
32#define LIBC_LOOP_NOUNROLL _Pragma("nounroll")32#define LIBC_LOOP_NOUNROLL _Pragma("nounroll")
33#define LIBC_LOOP_UNROLL _Pragma("unroll")
33#elif defined(LIBC_COMPILER_IS_GCC)34#elif defined(LIBC_COMPILER_IS_GCC)
34#define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0")35#define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0")
36#define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048")
35#else37#else
36#error "Unhandled compiler"38#error "Unhandled compiler"
37#endif39#endif
...@@ -45,6 +47,7 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {...@@ -45,6 +47,7 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
45#define LIBC_MATH_FAST \47#define LIBC_MATH_FAST \
46 (LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | \48 (LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | \
47 LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)49 LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)
50#define LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT 0x10
4851
49#ifndef LIBC_MATH52#ifndef LIBC_MATH
50#define LIBC_MATH 053#define LIBC_MATH 0
...@@ -58,4 +61,16 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {...@@ -58,4 +61,16 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
58#define LIBC_MATH_HAS_SMALL_TABLES61#define LIBC_MATH_HAS_SMALL_TABLES
59#endif62#endif
6063
64#if (LIBC_MATH & LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT)
65#define LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT
66#endif
67
68#if (LIBC_MATH & LIBC_MATH_NO_ERRNO)
69#define LIBC_MATH_HAS_NO_ERRNO
70#endif
71
72#if (LIBC_MATH & LIBC_MATH_NO_EXCEPT)
73#define LIBC_MATH_HAS_NO_EXCEPT
74#endif
75
61#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H76#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H
lib/libcxx/libc/src/__support/macros/properties/cpu_features.h+48
...@@ -20,6 +20,8 @@...@@ -20,6 +20,8 @@
2020
21#if defined(__SSE2__)21#if defined(__SSE2__)
22#define LIBC_TARGET_CPU_HAS_SSE222#define LIBC_TARGET_CPU_HAS_SSE2
23#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
24#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
23#endif25#endif
2426
25#if defined(__SSE4_2__)27#if defined(__SSE4_2__)
...@@ -42,9 +44,55 @@...@@ -42,9 +44,55 @@
42#define LIBC_TARGET_CPU_HAS_AVX512BW44#define LIBC_TARGET_CPU_HAS_AVX512BW
43#endif45#endif
4446
47#if defined(__ARM_FP)
48#if (__ARM_FP & 0x2)
49#define LIBC_TARGET_CPU_HAS_ARM_FPU_HALF
50#define LIBC_TARGET_CPU_HAS_FPU_HALF
51#endif // LIBC_TARGET_CPU_HAS_ARM_FPU_HALF
52#if (__ARM_FP & 0x4)
53#define LIBC_TARGET_CPU_HAS_ARM_FPU_FLOAT
54#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
55#endif // LIBC_TARGET_CPU_HAS_ARM_FPU_FLOAT
56#if (__ARM_FP & 0x8)
57#define LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE
58#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
59#endif // LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE
60#endif // __ARM_FP
61
62#if defined(__riscv_flen)
63// https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc
64#if defined(__riscv_zfhmin)
65#define LIBC_TARGET_CPU_HAS_RISCV_FPU_HALF
66#define LIBC_TARGET_CPU_HAS_FPU_HALF
67#endif // LIBC_TARGET_CPU_HAS_RISCV_FPU_HALF
68#if (__riscv_flen >= 32)
69#define LIBC_TARGET_CPU_HAS_RISCV_FPU_FLOAT
70#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
71#endif // LIBC_TARGET_CPU_HAS_RISCV_FPU_FLOAT
72#if (__riscv_flen >= 64)
73#define LIBC_TARGET_CPU_HAS_RISCV_FPU_DOUBLE
74#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
75#endif // LIBC_TARGET_CPU_HAS_RISCV_FPU_DOUBLE
76#endif // __riscv_flen
77
78#if defined(__NVPTX__) || defined(__AMDGPU__)
79#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
80#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
81#endif
82
45#if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \83#if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \
46 defined(__NVPTX__) || defined(__AMDGPU__) || defined(__LIBC_RISCV_USE_FMA)84 defined(__NVPTX__) || defined(__AMDGPU__) || defined(__LIBC_RISCV_USE_FMA)
47#define LIBC_TARGET_CPU_HAS_FMA85#define LIBC_TARGET_CPU_HAS_FMA
86// Provide a more fine-grained control of FMA instruction for ARM targets.
87#if defined(LIBC_TARGET_CPU_HAS_FPU_HALF)
88#define LIBC_TARGET_CPU_HAS_FMA_HALF
89#endif // LIBC_TARGET_CPU_HAS_FMA_HALF
90#if defined(LIBC_TARGET_CPU_HAS_FPU_FLOAT)
91#define LIBC_TARGET_CPU_HAS_FMA_FLOAT
92#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
93#if defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE)
94#define LIBC_TARGET_CPU_HAS_FMA_DOUBLE
95#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
48#endif96#endif
4997
50#if defined(LIBC_TARGET_ARCH_IS_AARCH64) || \98#if defined(LIBC_TARGET_ARCH_IS_AARCH64) || \
lib/libcxx/libc/src/__support/macros/properties/types.h+12-1
...@@ -10,9 +10,10 @@...@@ -10,9 +10,10 @@
10#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H10#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
11#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H11#define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
1212
13#include "hdr/float_macros.h" // LDBL_MANT_DIG13#include "hdr/float_macros.h" // LDBL_MANT_DIG
14#include "include/llvm-libc-macros/float16-macros.h" // LIBC_TYPES_HAS_FLOAT1614#include "include/llvm-libc-macros/float16-macros.h" // LIBC_TYPES_HAS_FLOAT16
15#include "include/llvm-libc-types/float128.h" // float12815#include "include/llvm-libc-types/float128.h" // float128
16#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
16#include "src/__support/macros/properties/architectures.h"17#include "src/__support/macros/properties/architectures.h"
17#include "src/__support/macros/properties/compiler.h"18#include "src/__support/macros/properties/compiler.h"
18#include "src/__support/macros/properties/cpu_features.h"19#include "src/__support/macros/properties/cpu_features.h"
...@@ -58,4 +59,14 @@ using float16 = _Float16;...@@ -58,4 +59,14 @@ using float16 = _Float16;
58// LIBC_TYPES_HAS_FLOAT128 and 'float128' type are provided by59// LIBC_TYPES_HAS_FLOAT128 and 'float128' type are provided by
59// "include/llvm-libc-types/float128.h"60// "include/llvm-libc-types/float128.h"
6061
62// -- bfloat16 support ---------------------------------------------------------
63
64namespace LIBC_NAMESPACE_DECL {
65namespace fputil {
66struct BFloat16;
67}
68} // namespace LIBC_NAMESPACE_DECL
69
70using bfloat16 = LIBC_NAMESPACE::fputil::BFloat16;
71
61#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H72#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
lib/libcxx/libc/src/__support/math_extras.h+1-2
...@@ -146,8 +146,7 @@ first_trailing_zero(T value) {...@@ -146,8 +146,7 @@ first_trailing_zero(T value) {
146template <typename T>146template <typename T>
147[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>147[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
148first_trailing_one(T value) {148first_trailing_one(T value) {
149 return value == cpp::numeric_limits<T>::max() ? 0149 return value == 0 ? 0 : cpp::countr_zero(value) + 1;
150 : cpp::countr_zero(value) + 1;
151}150}
152151
153template <typename T>152template <typename T>
lib/libcxx/libc/src/__support/sign.h+2
...@@ -29,6 +29,8 @@ struct Sign {...@@ -29,6 +29,8 @@ struct Sign {
29 static const Sign POS;29 static const Sign POS;
30 static const Sign NEG;30 static const Sign NEG;
3131
32 LIBC_INLINE constexpr Sign negate() const { return Sign(!is_negative); }
33
32private:34private:
33 LIBC_INLINE constexpr explicit Sign(bool is_negative)35 LIBC_INLINE constexpr explicit Sign(bool is_negative)
34 : is_negative(is_negative) {}36 : is_negative(is_negative) {}
lib/libcxx/libc/src/__support/str_to_float.h+13-13
...@@ -15,6 +15,7 @@...@@ -15,6 +15,7 @@
15#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H15#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H
16#define LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H16#define LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H
1717
18#include "hdr/errno_macros.h" // For ERANGE
18#include "src/__support/CPP/bit.h"19#include "src/__support/CPP/bit.h"
19#include "src/__support/CPP/limits.h"20#include "src/__support/CPP/limits.h"
20#include "src/__support/CPP/optional.h"21#include "src/__support/CPP/optional.h"
...@@ -31,7 +32,6 @@...@@ -31,7 +32,6 @@
31#include "src/__support/str_to_integer.h"32#include "src/__support/str_to_integer.h"
32#include "src/__support/str_to_num_result.h"33#include "src/__support/str_to_num_result.h"
33#include "src/__support/uint128.h"34#include "src/__support/uint128.h"
34#include "src/errno/libc_errno.h" // For ERANGE
3535
36#include <stdint.h>36#include <stdint.h>
3737
...@@ -108,11 +108,11 @@ eisel_lemire(ExpandedFloat<T> init_num,...@@ -108,11 +108,11 @@ eisel_lemire(ExpandedFloat<T> init_num,
108 }108 }
109109
110 // Normalization110 // Normalization
111 uint32_t clz = cpp::countl_zero<StorageType>(mantissa);111 uint32_t clz = static_cast<uint32_t>(cpp::countl_zero<StorageType>(mantissa));
112 mantissa <<= clz;112 mantissa <<= clz;
113113
114 int32_t exp2 =114 int32_t exp2 = exp10_to_exp2(exp10) + FPBits::STORAGE_LEN + FPBits::EXP_BIAS -
115 exp10_to_exp2(exp10) + FPBits::STORAGE_LEN + FPBits::EXP_BIAS - clz;115 static_cast<int32_t>(clz);
116116
117 // Multiplication117 // Multiplication
118 const uint64_t *power_of_ten =118 const uint64_t *power_of_ten =
...@@ -225,8 +225,8 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num,...@@ -225,8 +225,8 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num,
225 }225 }
226226
227 // Normalization227 // Normalization
228 uint32_t clz = cpp::countl_zero(mantissa) -228 int32_t clz = static_cast<int32_t>(cpp::countl_zero(mantissa)) -
229 ((sizeof(UInt128) - sizeof(StorageType)) * CHAR_BIT);229 ((sizeof(UInt128) - sizeof(StorageType)) * CHAR_BIT);
230 mantissa <<= clz;230 mantissa <<= clz;
231231
232 int32_t exp2 =232 int32_t exp2 =
...@@ -802,7 +802,7 @@ LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num,...@@ -802,7 +802,7 @@ LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num,
802802
803 // Handle subnormals.803 // Handle subnormals.
804 if (biased_exponent <= 0) {804 if (biased_exponent <= 0) {
805 amount_to_shift_right += 1 - biased_exponent;805 amount_to_shift_right += static_cast<uint32_t>(1 - biased_exponent);
806 biased_exponent = 0;806 biased_exponent = 0;
807807
808 if (amount_to_shift_right > FPBits::STORAGE_LEN) {808 if (amount_to_shift_right > FPBits::STORAGE_LEN) {
...@@ -909,7 +909,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,...@@ -909,7 +909,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
909 cpp::numeric_limits<StorageType>::max() / BASE;909 cpp::numeric_limits<StorageType>::max() / BASE;
910 while (true) {910 while (true) {
911 if (isdigit(src[index])) {911 if (isdigit(src[index])) {
912 uint32_t digit = b36_char_to_int(src[index]);912 uint32_t digit = static_cast<uint32_t>(b36_char_to_int(src[index]));
913 seen_digit = true;913 seen_digit = true;
914914
915 if (mantissa < bitstype_max_div_by_base) {915 if (mantissa < bitstype_max_div_by_base) {
...@@ -956,7 +956,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,...@@ -956,7 +956,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
956 if (result.has_error())956 if (result.has_error())
957 output.error = result.error;957 output.error = result.error;
958 int32_t add_to_exponent = result.value;958 int32_t add_to_exponent = result.value;
959 index += result.parsed_len;959 index += static_cast<size_t>(result.parsed_len);
960960
961 // Here we do this operation as int64 to avoid overflow.961 // Here we do this operation as int64 to avoid overflow.
962 int64_t temp_exponent = static_cast<int64_t>(exponent) +962 int64_t temp_exponent = static_cast<int64_t>(exponent) +
...@@ -1020,7 +1020,7 @@ hexadecimal_string_to_float(const char *__restrict src,...@@ -1020,7 +1020,7 @@ hexadecimal_string_to_float(const char *__restrict src,
1020 cpp::numeric_limits<StorageType>::max() / BASE;1020 cpp::numeric_limits<StorageType>::max() / BASE;
1021 while (true) {1021 while (true) {
1022 if (isalnum(src[index])) {1022 if (isalnum(src[index])) {
1023 uint32_t digit = b36_char_to_int(src[index]);1023 uint32_t digit = static_cast<uint32_t>(b36_char_to_int(src[index]));
1024 if (digit < BASE)1024 if (digit < BASE)
1025 seen_digit = true;1025 seen_digit = true;
1026 else1026 else
...@@ -1070,7 +1070,7 @@ hexadecimal_string_to_float(const char *__restrict src,...@@ -1070,7 +1070,7 @@ hexadecimal_string_to_float(const char *__restrict src,
1070 output.error = result.error;1070 output.error = result.error;
10711071
1072 int32_t add_to_exponent = result.value;1072 int32_t add_to_exponent = result.value;
1073 index += result.parsed_len;1073 index += static_cast<size_t>(result.parsed_len);
10741074
1075 // Here we do this operation as int64 to avoid overflow.1075 // Here we do this operation as int64 to avoid overflow.
1076 int64_t temp_exponent = static_cast<int64_t>(exponent) +1076 int64_t temp_exponent = static_cast<int64_t>(exponent) +
...@@ -1135,7 +1135,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {...@@ -1135,7 +1135,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
11351135
1136 int error = 0;1136 int error = 0;
11371137
1138 ptrdiff_t index = first_non_whitespace(src) - src;1138 size_t index = first_non_whitespace(src);
11391139
1140 if (src[index] == '+' || src[index] == '-') {1140 if (src[index] == '+' || src[index] == '-') {
1141 sign = src[index];1141 sign = src[index];
...@@ -1245,7 +1245,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {...@@ -1245,7 +1245,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
1245 // special 80 bit long doubles. Otherwise it should be inlined out.1245 // special 80 bit long doubles. Otherwise it should be inlined out.
1246 set_implicit_bit<T>(result);1246 set_implicit_bit<T>(result);
12471247
1248 return {result.get_val(), index, error};1248 return {result.get_val(), static_cast<ptrdiff_t>(index), error};
1249}1249}
12501250
1251template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {1251template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
lib/libcxx/libc/src/__support/str_to_integer.h+10-11
...@@ -15,6 +15,7 @@...@@ -15,6 +15,7 @@
15#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H15#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H
16#define LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H16#define LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H
1717
18#include "hdr/errno_macros.h" // For ERANGE
18#include "src/__support/CPP/limits.h"19#include "src/__support/CPP/limits.h"
19#include "src/__support/CPP/type_traits.h"20#include "src/__support/CPP/type_traits.h"
20#include "src/__support/CPP/type_traits/make_unsigned.h"21#include "src/__support/CPP/type_traits/make_unsigned.h"
...@@ -24,22 +25,20 @@...@@ -24,22 +25,20 @@
24#include "src/__support/macros/config.h"25#include "src/__support/macros/config.h"
25#include "src/__support/str_to_num_result.h"26#include "src/__support/str_to_num_result.h"
26#include "src/__support/uint128.h"27#include "src/__support/uint128.h"
27#include "src/errno/libc_errno.h" // For ERANGE
2828
29namespace LIBC_NAMESPACE_DECL {29namespace LIBC_NAMESPACE_DECL {
30namespace internal {30namespace internal {
3131
32// Returns a pointer to the first character in src that is not a whitespace32// Returns the idx to the first character in src that is not a whitespace
33// character (as determined by isspace())33// character (as determined by isspace())
34// TODO: Change from returning a pointer to returning a length.34LIBC_INLINE size_t
35LIBC_INLINE const char *
36first_non_whitespace(const char *__restrict src,35first_non_whitespace(const char *__restrict src,
37 size_t src_len = cpp::numeric_limits<size_t>::max()) {36 size_t src_len = cpp::numeric_limits<size_t>::max()) {
38 size_t src_cur = 0;37 size_t src_cur = 0;
39 while (src_cur < src_len && internal::isspace(src[src_cur])) {38 while (src_cur < src_len && internal::isspace(src[src_cur])) {
40 ++src_cur;39 ++src_cur;
41 }40 }
42 return src + src_cur;41 return src_cur;
43}42}
4443
45// checks if the next 3 characters of the string pointer are the start of a44// checks if the next 3 characters of the string pointer are the start of a
...@@ -96,7 +95,7 @@ strtointeger(const char *__restrict src, int base,...@@ -96,7 +95,7 @@ strtointeger(const char *__restrict src, int base,
96 if (base < 0 || base == 1 || base > 36)95 if (base < 0 || base == 1 || base > 36)
97 return {0, 0, EINVAL};96 return {0, 0, EINVAL};
9897
99 src_cur = first_non_whitespace(src, src_len) - src;98 src_cur = first_non_whitespace(src, src_len);
10099
101 char result_sign = '+';100 char result_sign = '+';
102 if (src[src_cur] == '+' || src[src_cur] == '-') {101 if (src[src_cur] == '+' || src[src_cur] == '-') {
...@@ -119,7 +118,7 @@ strtointeger(const char *__restrict src, int base,...@@ -119,7 +118,7 @@ strtointeger(const char *__restrict src, int base,
119 ResultType const abs_max =118 ResultType const abs_max =
120 (is_positive ? cpp::numeric_limits<T>::max() : NEGATIVE_MAX);119 (is_positive ? cpp::numeric_limits<T>::max() : NEGATIVE_MAX);
121 ResultType const abs_max_div_by_base =120 ResultType const abs_max_div_by_base =
122 static_cast<ResultType>(abs_max / base);121 abs_max / static_cast<ResultType>(base);
123122
124 while (src_cur < src_len && isalnum(src[src_cur])) {123 while (src_cur < src_len && isalnum(src[src_cur])) {
125 int cur_digit = b36_char_to_int(src[src_cur]);124 int cur_digit = b36_char_to_int(src[src_cur]);
...@@ -141,17 +140,17 @@ strtointeger(const char *__restrict src, int base,...@@ -141,17 +140,17 @@ strtointeger(const char *__restrict src, int base,
141 result = abs_max;140 result = abs_max;
142 error_val = ERANGE;141 error_val = ERANGE;
143 } else {142 } else {
144 result = static_cast<ResultType>(result * base);143 result = result * static_cast<ResultType>(base);
145 }144 }
146 if (result > abs_max - cur_digit) {145 if (result > abs_max - static_cast<ResultType>(cur_digit)) {
147 result = abs_max;146 result = abs_max;
148 error_val = ERANGE;147 error_val = ERANGE;
149 } else {148 } else {
150 result = static_cast<ResultType>(result + cur_digit);149 result = result + static_cast<ResultType>(cur_digit);
151 }150 }
152 }151 }
153152
154 ptrdiff_t str_len = is_number ? (src_cur) : 0;153 ptrdiff_t str_len = is_number ? static_cast<ptrdiff_t>(src_cur) : 0;
155154
156 if (error_val == ERANGE) {155 if (error_val == ERANGE) {
157 if (is_positive || IS_UNSIGNED)156 if (is_positive || IS_UNSIGNED)
lib/libcxx/libc/src/errno/libc_errno.h deleted-47
...@@ -1,47 +0,0 @@
1//===-- Implementation header for libc_errno --------------------*- 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_ERRNO_LIBC_ERRNO_H
10#define LLVM_LIBC_SRC_ERRNO_LIBC_ERRNO_H
11
12#include "src/__support/macros/attributes.h"
13#include "src/__support/macros/config.h"
14#include "src/__support/macros/properties/architectures.h"
15
16#include "hdr/errno_macros.h"
17
18// This header is to be consumed by internal implementations, in which all of
19// them should refer to `libc_errno` instead of using `errno` directly from
20// <errno.h> header.
21
22// Unit and hermetic tests should:
23// - #include "src/errno/libc_errno.h"
24// - NOT #include <errno.h>
25// - Only use `libc_errno` in the code
26// - Depend on libc.src.errno.errno
27
28// Integration tests should:
29// - NOT #include "src/errno/libc_errno.h"
30// - #include <errno.h>
31// - Use regular `errno` in the code
32// - Still depend on libc.src.errno.errno
33
34namespace LIBC_NAMESPACE_DECL {
35
36extern "C" int *__llvm_libc_errno() noexcept;
37
38struct Errno {
39 void operator=(int);
40 operator int();
41};
42
43extern Errno libc_errno;
44
45} // namespace LIBC_NAMESPACE_DECL
46
47#endif // LLVM_LIBC_SRC_ERRNO_LIBC_ERRNO_H