llvm-libc: update to LLVM 21

Still only the subset needed for libcxx.
This commit is contained in:
Alex Rønne Petersen 2025-07-16 10:52:18 +02:00
parent d9f0fbf983
commit c34fc8f198
No known key found for this signature in database
24 changed files with 313 additions and 130 deletions

View File

@ -323,6 +323,45 @@
#define ULACCUM_EPSILON 0x1.0p-32ULK
#endif // ULACCUM_EPSILON
#define absfx(x) \
_Generic((x), \
fract: absr, \
short fract: abshr, \
long fract: abslr, \
accum: absk, \
short accum: abshk, \
long accum: abslk)(x)
#define countlsfx(x) \
_Generic((x), \
fract: countlsr, \
short fract: countlshr, \
long fract: countlslr, \
accum: countlsk, \
short accum: countlshk, \
long accum: countlslk, \
unsigned fract: countlsur, \
unsigned short fract: countlsuhr, \
unsigned long fract: countlsulr, \
unsigned accum: countlsuk, \
unsigned short accum: countlsuhk, \
unsigned long accum: countlsulk)(x)
#define roundfx(x, y) \
_Generic((x), \
fract: roundr, \
short fract: roundhr, \
long fract: roundlr, \
accum: roundk, \
short accum: roundhk, \
long accum: roundlk, \
unsigned fract: roundur, \
unsigned short fract: rounduhr, \
unsigned long fract: roundulr, \
unsigned accum: rounduk, \
unsigned short accum: rounduhk, \
unsigned long accum: roundulk)(x, y)
#endif // LIBC_COMPILER_HAS_FIXED_POINT
#endif // LLVM_LIBC_MACROS_STDFIX_MACROS_H

View File

@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_SHARED_FP_BITS_H
#define LLVM_LIBC_SHARED_FP_BITS_H
#include "libc_common.h"
#include "src/__support/FPUtil/FPBits.h"
namespace LIBC_NAMESPACE_DECL {

26
lib/libcxx/libc/shared/libc_common.h vendored Normal file
View File

@ -0,0 +1,26 @@
//===-- Common defines for sharing LLVM libc with LLVM projects -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SHARED_LIBC_COMMON_H
#define LLVM_LIBC_SHARED_LIBC_COMMON_H
// Use system errno.
#ifdef LIBC_ERRNO_MODE
#if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SYSTEM_INLINE
#error \
"LIBC_ERRNO_MODE was set to something different from LIBC_ERRNO_MODE_SYSTEM_INLINE."
#endif // LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SYSTEM_INLINE
#else
#define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM_INLINE
#endif // LIBC_ERRNO_MODE
#ifndef LIBC_NAMESPACE
#define LIBC_NAMESPACE __llvm_libc
#endif // LIBC_NAMESPACE
#endif // LLVM_LIBC_SHARED_LIBC_COMMON_H

View File

@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_SHARED_STR_TO_FLOAT_H
#define LLVM_LIBC_SHARED_STR_TO_FLOAT_H
#include "libc_common.h"
#include "src/__support/str_to_float.h"
namespace LIBC_NAMESPACE_DECL {

View File

@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_SHARED_STR_TO_INTEGER_H
#define LLVM_LIBC_SHARED_STR_TO_INTEGER_H
#include "libc_common.h"
#include "src/__support/str_to_integer.h"
namespace LIBC_NAMESPACE_DECL {

View File

@ -101,7 +101,7 @@ countr_zero(T value) {
shift >>= 1;
mask >>= shift;
}
return zero_bits;
return static_cast<int>(zero_bits);
}
#if __has_builtin(__builtin_ctzs)
ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs)
@ -140,7 +140,7 @@ countl_zero(T value) {
else
zero_bits |= shift;
}
return zero_bits;
return static_cast<int>(zero_bits);
}
#if __has_builtin(__builtin_clzs)
ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs)
@ -162,7 +162,7 @@ ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll)
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
countl_one(T value) {
return cpp::countl_zero<T>(~value);
return cpp::countl_zero<T>(static_cast<T>(~value));
}
/// Count the number of ones from the least significant bit to the first
@ -175,7 +175,7 @@ countl_one(T value) {
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
countr_one(T value) {
return cpp::countr_zero<T>(~value);
return cpp::countr_zero<T>(static_cast<T>(~value));
}
/// Returns the number of bits needed to represent value if value is nonzero.
@ -226,25 +226,25 @@ rotr(T value, int rotate);
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
rotl(T value, int rotate) {
constexpr unsigned N = cpp::numeric_limits<T>::digits;
constexpr int N = cpp::numeric_limits<T>::digits;
rotate = rotate % N;
if (!rotate)
return value;
if (rotate < 0)
return cpp::rotr<T>(value, -rotate);
return (value << rotate) | (value >> (N - rotate));
return static_cast<T>((value << rotate) | (value >> (N - rotate)));
}
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
rotr(T value, int rotate) {
constexpr unsigned N = cpp::numeric_limits<T>::digits;
constexpr int N = cpp::numeric_limits<T>::digits;
rotate = rotate % N;
if (!rotate)
return value;
if (rotate < 0)
return cpp::rotl<T>(value, -rotate);
return (value >> rotate) | (value << (N - rotate));
return static_cast<T>((value >> rotate) | (value << (N - rotate)));
}
// TODO: Do we need this function at all? How is it different from

View File

@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
#define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
#include "limits.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
@ -40,7 +41,7 @@ private:
LIBC_INLINE static constexpr size_t length(const char *Str) {
for (const char *End = Str;; ++End)
if (*End == '\0')
return End - Str;
return static_cast<size_t>(End - Str);
}
LIBC_INLINE bool equals(string_view Other) const {
@ -61,7 +62,8 @@ public:
// special value equal to the maximum value representable by the type
// size_type.
LIBC_INLINE_VAR static constexpr size_t npos = -1;
LIBC_INLINE_VAR static constexpr size_t npos =
cpp::numeric_limits<size_t>::max();
LIBC_INLINE constexpr string_view() : Data(nullptr), Len(0) {}

View File

@ -36,7 +36,8 @@ public:
,
float128
#endif
>();
,
bfloat16>();
};
template <typename T>
LIBC_INLINE_VAR constexpr bool is_floating_point_v =

View File

@ -8,20 +8,43 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H
#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H
#include "include/llvm-libc-macros/stdfix-macros.h"
#include "src/__support/CPP/type_traits/bool_constant.h"
#include "src/__support/CPP/type_traits/is_arithmetic.h"
#include "src/__support/CPP/type_traits/is_same.h"
#include "src/__support/CPP/type_traits/remove_cv.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
namespace cpp {
// is_signed
#ifndef LIBC_COMPILER_HAS_FIXED_POINT
template <typename T>
struct is_signed : bool_constant<(is_arithmetic_v<T> && (T(-1) < T(0)))> {
LIBC_INLINE constexpr operator bool() const { return is_signed::value; }
LIBC_INLINE constexpr bool operator()() const { return is_signed::value; }
};
#else
template <typename T> struct is_signed {
private:
template <typename Head, typename... Args>
LIBC_INLINE static constexpr bool __is_unqualified_any_of() {
return (... || is_same_v<remove_cv_t<Head>, Args>);
}
public:
LIBC_INLINE_VAR static constexpr bool value =
(is_arithmetic_v<T> && (T(-1) < T(0))) ||
__is_unqualified_any_of<T, short fract, fract, long fract, short accum,
accum, long accum, short sat fract, sat fract,
long sat fract, short sat accum, sat accum,
long sat accum>();
LIBC_INLINE constexpr operator bool() const { return is_signed::value; }
LIBC_INLINE constexpr bool operator()() const { return is_signed::value; }
};
#endif // LIBC_COMPILER_HAS_FIXED_POINT
template <typename T>
LIBC_INLINE_VAR constexpr bool is_signed_v = is_signed<T>::value;

View File

@ -8,20 +8,45 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H
#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H
#include "include/llvm-libc-macros/stdfix-macros.h"
#include "src/__support/CPP/type_traits/bool_constant.h"
#include "src/__support/CPP/type_traits/is_arithmetic.h"
#include "src/__support/CPP/type_traits/is_same.h"
#include "src/__support/CPP/type_traits/remove_cv.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
namespace cpp {
// is_unsigned
#ifndef LIBC_COMPILER_HAS_FIXED_POINT
template <typename T>
struct is_unsigned : bool_constant<(is_arithmetic_v<T> && (T(-1) > T(0)))> {
LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; }
LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; }
};
#else
template <typename T> struct is_unsigned {
private:
template <typename Head, typename... Args>
LIBC_INLINE static constexpr bool __is_unqualified_any_of() {
return (... || is_same_v<remove_cv_t<Head>, Args>);
}
public:
LIBC_INLINE_VAR static constexpr bool value =
(is_arithmetic_v<T> && (T(-1) > T(0))) ||
__is_unqualified_any_of<T, unsigned short fract, unsigned fract,
unsigned long fract, unsigned short accum,
unsigned accum, unsigned long accum,
unsigned short sat fract, unsigned sat fract,
unsigned long sat fract, unsigned short sat accum,
unsigned sat accum, unsigned long sat accum>();
LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; }
LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; }
};
#endif // LIBC_COMPILER_HAS_FIXED_POINT
template <typename T>
LIBC_INLINE_VAR constexpr bool is_unsigned_v = is_unsigned<T>::value;

View File

@ -38,6 +38,7 @@ enum class FPType {
IEEE754_Binary64,
IEEE754_Binary128,
X86_Binary80,
BFloat16
};
// The classes hierarchy is as follows:
@ -138,6 +139,14 @@ template <> struct FPLayout<FPType::X86_Binary80> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN - 1;
};
template <> struct FPLayout<FPType::BFloat16> {
using StorageType = uint16_t;
LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
LIBC_INLINE_VAR static constexpr int EXP_LEN = 8;
LIBC_INLINE_VAR static constexpr int SIG_LEN = 7;
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
};
// FPStorage derives useful constants from the FPLayout above.
template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
using UP = FPLayout<fp_type>;
@ -247,11 +256,11 @@ protected:
using UP::UP;
LIBC_INLINE constexpr BiasedExponent(Exponent exp)
: UP(static_cast<int32_t>(exp) + EXP_BIAS) {}
: UP(static_cast<uint32_t>(static_cast<int32_t>(exp) + EXP_BIAS)) {}
// Cast operator to get convert from BiasedExponent to Exponent.
LIBC_INLINE constexpr operator Exponent() const {
return Exponent(UP::value - EXP_BIAS);
return Exponent(static_cast<int32_t>(UP::value - EXP_BIAS));
}
LIBC_INLINE constexpr BiasedExponent &operator++() {
@ -686,7 +695,7 @@ public:
}
LIBC_INLINE constexpr void set_biased_exponent(StorageType biased) {
UP::set_biased_exponent(BiasedExponent((int32_t)biased));
UP::set_biased_exponent(BiasedExponent(static_cast<uint32_t>(biased)));
}
LIBC_INLINE constexpr int get_exponent() const {
@ -757,7 +766,7 @@ public:
result.set_significand(number);
result.set_biased_exponent(static_cast<StorageType>(ep + 1));
} else {
result.set_significand(number >> -ep);
result.set_significand(number >> static_cast<unsigned>(-ep));
}
return RetT(result.uintval());
}
@ -801,6 +810,8 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
else if constexpr (cpp::is_same_v<UnqualT, float128>)
return FPType::IEEE754_Binary128;
#endif
else if constexpr (cpp::is_same_v<UnqualT, bfloat16>)
return FPType::BFloat16;
else
static_assert(cpp::always_false<UnqualT>, "Unsupported type");
}

View File

@ -241,7 +241,7 @@ LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst,
}
template <typename word, size_t N>
LIBC_INLINE constexpr bool is_negative(cpp::array<word, N> &array) {
LIBC_INLINE constexpr bool is_negative(const cpp::array<word, N> &array) {
using signed_word = cpp::make_signed_t<word>;
return cpp::bit_cast<signed_word>(array.back()) < 0;
}
@ -284,8 +284,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
if (i < 0)
return 0;
if (i >= int(N))
return is_neg ? -1 : 0;
return array[i];
return is_neg ? cpp::numeric_limits<word>::max() : 0;
return array[static_cast<unsigned>(i)];
};
const size_t index_offset = offset / WORD_BITS;
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,
for (size_t index = 0; index < N; ++index) {
const word part1 = safe_get_at(index + index_offset);
const word part2 = safe_get_at(index + index_offset + 1);
word &dst = out[at(index)];
word &dst = out[static_cast<unsigned>(at(index))];
if (bit_offset == 0)
dst = part1; // no crosstalk between parts.
else if constexpr (direction == LEFT)
@ -465,8 +465,7 @@ public:
}
// Initialize the first word to |v| and the rest to 0.
template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T> &&
!cpp::is_same_v<T, bool>>>
template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T>>>
LIBC_INLINE constexpr BigInt(T v) {
constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT;
const bool is_neg = v < 0;
@ -697,7 +696,8 @@ public:
}
BigInt quotient;
WordType x_word = static_cast<WordType>(x);
constexpr size_t LOG2_WORD_SIZE = cpp::bit_width(WORD_SIZE) - 1;
constexpr size_t LOG2_WORD_SIZE =
static_cast<size_t>(cpp::bit_width(WORD_SIZE) - 1);
constexpr size_t HALF_WORD_SIZE = WORD_SIZE >> 1;
constexpr WordType HALF_MASK = ((WordType(1) << HALF_WORD_SIZE) - 1);
// lower = smallest multiple of WORD_SIZE that is >= e.
@ -866,7 +866,7 @@ public:
LIBC_INLINE constexpr BigInt operator~() const {
BigInt result;
for (size_t i = 0; i < WORD_COUNT; ++i)
result[i] = ~val[i];
result[i] = static_cast<WordType>(~val[i]);
return result;
}
@ -936,6 +936,18 @@ public:
// Return the i-th word of the number.
LIBC_INLINE constexpr WordType &operator[](size_t i) { return val[i]; }
// Return the i-th bit of the number.
LIBC_INLINE constexpr bool get_bit(size_t i) const {
const size_t word_index = i / WORD_SIZE;
return 1 & (val[word_index] >> (i % WORD_SIZE));
}
// Set the i-th bit of the number.
LIBC_INLINE constexpr void set_bit(size_t i) {
const size_t word_index = i / WORD_SIZE;
val[word_index] |= WordType(1) << (i % WORD_SIZE);
}
private:
LIBC_INLINE friend constexpr int cmp(const BigInt &lhs, const BigInt &rhs) {
constexpr auto compare = [](WordType a, WordType b) {
@ -955,7 +967,7 @@ private:
LIBC_INLINE constexpr void bitwise_not() {
for (auto &part : val)
part = ~part;
part = static_cast<WordType>(~part);
}
LIBC_INLINE constexpr void negate() {
@ -968,7 +980,7 @@ private:
}
LIBC_INLINE constexpr void decrement() {
multiword::add_with_carry(val, cpp::array<WordType, 1>{1});
multiword::sub_with_borrow(val, cpp::array<WordType, 1>{1});
}
LIBC_INLINE constexpr void extend(size_t index, bool is_neg) {
@ -989,12 +1001,6 @@ private:
LIBC_INLINE constexpr void clear_msb() {
val.back() &= mask_trailing_ones<WordType, WORD_SIZE - 1>();
}
LIBC_INLINE constexpr void set_bit(size_t i) {
const size_t word_index = i / WORD_SIZE;
val[word_index] |= WordType(1) << (i % WORD_SIZE);
}
LIBC_INLINE constexpr static Division divide_unsigned(const BigInt &dividend,
const BigInt &divider) {
BigInt remainder = dividend;
@ -1003,12 +1009,12 @@ private:
BigInt subtractor = divider;
int cur_bit = multiword::countl_zero(subtractor.val) -
multiword::countl_zero(remainder.val);
subtractor <<= cur_bit;
subtractor <<= static_cast<size_t>(cur_bit);
for (; cur_bit >= 0 && remainder > 0; --cur_bit, subtractor >>= 1) {
if (remainder < subtractor)
continue;
remainder -= subtractor;
quotient.set_bit(cur_bit);
quotient.set_bit(static_cast<size_t>(cur_bit));
}
}
return Division{quotient, remainder};
@ -1270,26 +1276,28 @@ rotr(T value, int rotate);
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
rotl(T value, int rotate) {
constexpr unsigned N = cpp::numeric_limits<T>::digits;
constexpr int N = cpp::numeric_limits<T>::digits;
rotate = rotate % N;
if (!rotate)
return value;
if (rotate < 0)
return cpp::rotr<T>(value, -rotate);
return (value << rotate) | (value >> (N - rotate));
return (value << static_cast<size_t>(rotate)) |
(value >> (N - static_cast<size_t>(rotate)));
}
// Specialization of cpp::rotr ('bit.h') for BigInt.
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T>
rotr(T value, int rotate) {
constexpr unsigned N = cpp::numeric_limits<T>::digits;
constexpr int N = cpp::numeric_limits<T>::digits;
rotate = rotate % N;
if (!rotate)
return value;
if (rotate < 0)
return cpp::rotl<T>(value, -rotate);
return (value >> rotate) | (value << (N - rotate));
return (value >> static_cast<size_t>(rotate)) |
(value << (N - static_cast<size_t>(rotate)));
}
} // namespace cpp
@ -1306,7 +1314,7 @@ mask_trailing_ones() {
T out; // zero initialized
for (size_t i = 0; i <= QUOTIENT; ++i)
out[i] = i < QUOTIENT
? -1
? cpp::numeric_limits<typename T::word_type>::max()
: mask_trailing_ones<typename T::word_type, REMAINDER>();
return out;
}
@ -1322,7 +1330,7 @@ LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() {
T out; // zero initialized
for (size_t i = QUOTIENT; i < T::WORD_COUNT; ++i)
out[i] = i > QUOTIENT
? -1
? cpp::numeric_limits<typename T::word_type>::max()
: mask_leading_ones<typename T::word_type, REMAINDER>();
return out;
}
@ -1375,8 +1383,7 @@ first_trailing_zero(T value) {
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
first_trailing_one(T value) {
return value == cpp::numeric_limits<T>::max() ? 0
: cpp::countr_zero(value) + 1;
return value == 0 ? 0 : cpp::countr_zero(value) + 1;
}
} // namespace LIBC_NAMESPACE_DECL

View File

@ -37,17 +37,27 @@
#define LLVM_LIBC_ATTR(name) EXPAND_THEN_SECOND(LLVM_LIBC_FUNCTION_ATTR_##name)
// MacOS needs to be excluded because it does not support aliasing.
#if defined(LIBC_COPT_PUBLIC_PACKAGING) && (!defined(__APPLE__))
// At the moment, [[gnu::alias()]] is not supported on MacOS, and it is needed
// to cleanly export and alias the C++ symbol `LIBC_NAMESPACE::func` with the C
// symbol `func`. So for public packaging on MacOS, we will only export the C
// symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`.
#if defined(LIBC_COPT_PUBLIC_PACKAGING)
#ifndef __APPLE__
#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \
LLVM_LIBC_ATTR(name) \
LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \
__##name##_impl__ __asm__(#name); \
decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \
type __##name##_impl__ arglist
#else
#else // __APPLE__
#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \
LLVM_LIBC_ATTR(name) \
LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) name asm("_" #name); \
type name arglist
#endif // __APPLE__
#else // LIBC_COPT_PUBLIC_PACKAGING
#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) type name arglist
#endif
#endif // LIBC_COPT_PUBLIC_PACKAGING
// This extra layer of macro allows `name` to be a macro to rename a function.
#define LLVM_LIBC_FUNCTION(type, name, arglist) \

View File

@ -264,7 +264,7 @@ private:
LIBC_INLINE void left_shift(uint32_t shift_amount) {
uint32_t new_digits = this->get_num_new_digits(shift_amount);
int32_t read_index = this->num_digits - 1;
int32_t read_index = static_cast<int32_t>(this->num_digits - 1);
uint32_t write_index = this->num_digits + new_digits;
uint64_t accumulator = 0;
@ -329,7 +329,7 @@ public:
if (saw_dot) {
break;
}
this->decimal_point = total_digits;
this->decimal_point = static_cast<int32_t>(total_digits);
saw_dot = true;
} else {
if (num_string[num_cur] == '0' && this->num_digits == 0) {
@ -350,7 +350,7 @@ public:
}
if (!saw_dot)
this->decimal_point = total_digits;
this->decimal_point = static_cast<int32_t>(total_digits);
if (num_cur < num_len &&
(num_string[num_cur] == 'e' || num_string[num_cur] == 'E')) {
@ -393,7 +393,7 @@ public:
this->left_shift(MAX_SHIFT_AMOUNT);
shift_amount -= MAX_SHIFT_AMOUNT;
}
this->left_shift(shift_amount);
this->left_shift(static_cast<uint32_t>(shift_amount));
}
// Right
else {
@ -401,7 +401,7 @@ public:
this->right_shift(MAX_SHIFT_AMOUNT);
shift_amount += MAX_SHIFT_AMOUNT;
}
this->right_shift(-shift_amount);
this->right_shift(static_cast<uint32_t>(-shift_amount));
}
}
@ -424,8 +424,8 @@ public:
result *= 10;
++cur_digit;
}
return result + static_cast<unsigned int>(
this->should_round_up(this->decimal_point, round));
return result +
static_cast<T>(this->should_round_up(this->decimal_point, round));
}
// Extra functions for testing.

View File

@ -9,7 +9,6 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H
#define LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H
#include "src/__support/macros/config.h"
#if defined(LIBC_COPT_USE_C_ASSERT) || !defined(LIBC_FULL_BUILD)
// The build is configured to just use the public <assert.h> API
@ -25,6 +24,7 @@
#include "src/__support/OSUtil/io.h"
#include "src/__support/integer_to_string.h"
#include "src/__support/macros/attributes.h" // For LIBC_INLINE
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // For LIBC_UNLIKELY
namespace LIBC_NAMESPACE_DECL {

View File

@ -19,10 +19,19 @@
if (LIBC_UNLIKELY((ptr) == nullptr)) \
__builtin_trap(); \
} while (0)
#define LIBC_CRASH_ON_VALUE(var, value) \
do { \
if (LIBC_UNLIKELY((var) == (value))) \
__builtin_trap(); \
} while (0)
#else
#define LIBC_CRASH_ON_NULLPTR(ptr) \
do { \
} while (0)
#define LIBC_CRASH_ON_VALUE(var, value) \
do { \
} while (0)
#endif
#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_NULL_CHECK_H

View File

@ -30,8 +30,10 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
#if defined(LIBC_COMPILER_IS_CLANG)
#define LIBC_LOOP_NOUNROLL _Pragma("nounroll")
#define LIBC_LOOP_UNROLL _Pragma("unroll")
#elif defined(LIBC_COMPILER_IS_GCC)
#define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0")
#define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048")
#else
#error "Unhandled compiler"
#endif
@ -45,6 +47,7 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
#define LIBC_MATH_FAST \
(LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | \
LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)
#define LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT 0x10
#ifndef LIBC_MATH
#define LIBC_MATH 0
@ -58,4 +61,16 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
#define LIBC_MATH_HAS_SMALL_TABLES
#endif
#if (LIBC_MATH & LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT)
#define LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT
#endif
#if (LIBC_MATH & LIBC_MATH_NO_ERRNO)
#define LIBC_MATH_HAS_NO_ERRNO
#endif
#if (LIBC_MATH & LIBC_MATH_NO_EXCEPT)
#define LIBC_MATH_HAS_NO_EXCEPT
#endif
#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H

View File

@ -20,6 +20,8 @@
#if defined(__SSE2__)
#define LIBC_TARGET_CPU_HAS_SSE2
#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
#endif
#if defined(__SSE4_2__)
@ -42,9 +44,55 @@
#define LIBC_TARGET_CPU_HAS_AVX512BW
#endif
#if defined(__ARM_FP)
#if (__ARM_FP & 0x2)
#define LIBC_TARGET_CPU_HAS_ARM_FPU_HALF
#define LIBC_TARGET_CPU_HAS_FPU_HALF
#endif // LIBC_TARGET_CPU_HAS_ARM_FPU_HALF
#if (__ARM_FP & 0x4)
#define LIBC_TARGET_CPU_HAS_ARM_FPU_FLOAT
#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
#endif // LIBC_TARGET_CPU_HAS_ARM_FPU_FLOAT
#if (__ARM_FP & 0x8)
#define LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE
#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
#endif // LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE
#endif // __ARM_FP
#if defined(__riscv_flen)
// https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc
#if defined(__riscv_zfhmin)
#define LIBC_TARGET_CPU_HAS_RISCV_FPU_HALF
#define LIBC_TARGET_CPU_HAS_FPU_HALF
#endif // LIBC_TARGET_CPU_HAS_RISCV_FPU_HALF
#if (__riscv_flen >= 32)
#define LIBC_TARGET_CPU_HAS_RISCV_FPU_FLOAT
#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
#endif // LIBC_TARGET_CPU_HAS_RISCV_FPU_FLOAT
#if (__riscv_flen >= 64)
#define LIBC_TARGET_CPU_HAS_RISCV_FPU_DOUBLE
#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
#endif // LIBC_TARGET_CPU_HAS_RISCV_FPU_DOUBLE
#endif // __riscv_flen
#if defined(__NVPTX__) || defined(__AMDGPU__)
#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
#endif
#if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \
defined(__NVPTX__) || defined(__AMDGPU__) || defined(__LIBC_RISCV_USE_FMA)
#define LIBC_TARGET_CPU_HAS_FMA
// Provide a more fine-grained control of FMA instruction for ARM targets.
#if defined(LIBC_TARGET_CPU_HAS_FPU_HALF)
#define LIBC_TARGET_CPU_HAS_FMA_HALF
#endif // LIBC_TARGET_CPU_HAS_FMA_HALF
#if defined(LIBC_TARGET_CPU_HAS_FPU_FLOAT)
#define LIBC_TARGET_CPU_HAS_FMA_FLOAT
#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
#if defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE)
#define LIBC_TARGET_CPU_HAS_FMA_DOUBLE
#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
#endif
#if defined(LIBC_TARGET_ARCH_IS_AARCH64) || \

View File

@ -13,6 +13,7 @@
#include "hdr/float_macros.h" // LDBL_MANT_DIG
#include "include/llvm-libc-macros/float16-macros.h" // LIBC_TYPES_HAS_FLOAT16
#include "include/llvm-libc-types/float128.h" // float128
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
#include "src/__support/macros/properties/architectures.h"
#include "src/__support/macros/properties/compiler.h"
#include "src/__support/macros/properties/cpu_features.h"
@ -58,4 +59,14 @@ using float16 = _Float16;
// LIBC_TYPES_HAS_FLOAT128 and 'float128' type are provided by
// "include/llvm-libc-types/float128.h"
// -- bfloat16 support ---------------------------------------------------------
namespace LIBC_NAMESPACE_DECL {
namespace fputil {
struct BFloat16;
}
} // namespace LIBC_NAMESPACE_DECL
using bfloat16 = LIBC_NAMESPACE::fputil::BFloat16;
#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H

View File

@ -146,8 +146,7 @@ first_trailing_zero(T value) {
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int>
first_trailing_one(T value) {
return value == cpp::numeric_limits<T>::max() ? 0
: cpp::countr_zero(value) + 1;
return value == 0 ? 0 : cpp::countr_zero(value) + 1;
}
template <typename T>

View File

@ -29,6 +29,8 @@ struct Sign {
static const Sign POS;
static const Sign NEG;
LIBC_INLINE constexpr Sign negate() const { return Sign(!is_negative); }
private:
LIBC_INLINE constexpr explicit Sign(bool is_negative)
: is_negative(is_negative) {}

View File

@ -15,6 +15,7 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H
#define LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H
#include "hdr/errno_macros.h" // For ERANGE
#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/limits.h"
#include "src/__support/CPP/optional.h"
@ -31,7 +32,6 @@
#include "src/__support/str_to_integer.h"
#include "src/__support/str_to_num_result.h"
#include "src/__support/uint128.h"
#include "src/errno/libc_errno.h" // For ERANGE
#include <stdint.h>
@ -108,11 +108,11 @@ eisel_lemire(ExpandedFloat<T> init_num,
}
// Normalization
uint32_t clz = cpp::countl_zero<StorageType>(mantissa);
uint32_t clz = static_cast<uint32_t>(cpp::countl_zero<StorageType>(mantissa));
mantissa <<= clz;
int32_t exp2 =
exp10_to_exp2(exp10) + FPBits::STORAGE_LEN + FPBits::EXP_BIAS - clz;
int32_t exp2 = exp10_to_exp2(exp10) + FPBits::STORAGE_LEN + FPBits::EXP_BIAS -
static_cast<int32_t>(clz);
// Multiplication
const uint64_t *power_of_ten =
@ -225,7 +225,7 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num,
}
// Normalization
uint32_t clz = cpp::countl_zero(mantissa) -
int32_t clz = static_cast<int32_t>(cpp::countl_zero(mantissa)) -
((sizeof(UInt128) - sizeof(StorageType)) * CHAR_BIT);
mantissa <<= clz;
@ -802,7 +802,7 @@ LIBC_INLINE FloatConvertReturn<T> binary_exp_to_float(ExpandedFloat<T> init_num,
// Handle subnormals.
if (biased_exponent <= 0) {
amount_to_shift_right += 1 - biased_exponent;
amount_to_shift_right += static_cast<uint32_t>(1 - biased_exponent);
biased_exponent = 0;
if (amount_to_shift_right > FPBits::STORAGE_LEN) {
@ -909,7 +909,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
cpp::numeric_limits<StorageType>::max() / BASE;
while (true) {
if (isdigit(src[index])) {
uint32_t digit = b36_char_to_int(src[index]);
uint32_t digit = static_cast<uint32_t>(b36_char_to_int(src[index]));
seen_digit = true;
if (mantissa < bitstype_max_div_by_base) {
@ -956,7 +956,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT,
if (result.has_error())
output.error = result.error;
int32_t add_to_exponent = result.value;
index += result.parsed_len;
index += static_cast<size_t>(result.parsed_len);
// Here we do this operation as int64 to avoid overflow.
int64_t temp_exponent = static_cast<int64_t>(exponent) +
@ -1020,7 +1020,7 @@ hexadecimal_string_to_float(const char *__restrict src,
cpp::numeric_limits<StorageType>::max() / BASE;
while (true) {
if (isalnum(src[index])) {
uint32_t digit = b36_char_to_int(src[index]);
uint32_t digit = static_cast<uint32_t>(b36_char_to_int(src[index]));
if (digit < BASE)
seen_digit = true;
else
@ -1070,7 +1070,7 @@ hexadecimal_string_to_float(const char *__restrict src,
output.error = result.error;
int32_t add_to_exponent = result.value;
index += result.parsed_len;
index += static_cast<size_t>(result.parsed_len);
// Here we do this operation as int64 to avoid overflow.
int64_t temp_exponent = static_cast<int64_t>(exponent) +
@ -1135,7 +1135,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
int error = 0;
ptrdiff_t index = first_non_whitespace(src) - src;
size_t index = first_non_whitespace(src);
if (src[index] == '+' || src[index] == '-') {
sign = src[index];
@ -1245,7 +1245,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
// special 80 bit long doubles. Otherwise it should be inlined out.
set_implicit_bit<T>(result);
return {result.get_val(), index, error};
return {result.get_val(), static_cast<ptrdiff_t>(index), error};
}
template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {

View File

@ -15,6 +15,7 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H
#define LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H
#include "hdr/errno_macros.h" // For ERANGE
#include "src/__support/CPP/limits.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/CPP/type_traits/make_unsigned.h"
@ -24,22 +25,20 @@
#include "src/__support/macros/config.h"
#include "src/__support/str_to_num_result.h"
#include "src/__support/uint128.h"
#include "src/errno/libc_errno.h" // For ERANGE
namespace LIBC_NAMESPACE_DECL {
namespace internal {
// Returns a pointer to the first character in src that is not a whitespace
// Returns the idx to the first character in src that is not a whitespace
// character (as determined by isspace())
// TODO: Change from returning a pointer to returning a length.
LIBC_INLINE const char *
LIBC_INLINE size_t
first_non_whitespace(const char *__restrict src,
size_t src_len = cpp::numeric_limits<size_t>::max()) {
size_t src_cur = 0;
while (src_cur < src_len && internal::isspace(src[src_cur])) {
++src_cur;
}
return src + src_cur;
return src_cur;
}
// 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,
if (base < 0 || base == 1 || base > 36)
return {0, 0, EINVAL};
src_cur = first_non_whitespace(src, src_len) - src;
src_cur = first_non_whitespace(src, src_len);
char result_sign = '+';
if (src[src_cur] == '+' || src[src_cur] == '-') {
@ -119,7 +118,7 @@ strtointeger(const char *__restrict src, int base,
ResultType const abs_max =
(is_positive ? cpp::numeric_limits<T>::max() : NEGATIVE_MAX);
ResultType const abs_max_div_by_base =
static_cast<ResultType>(abs_max / base);
abs_max / static_cast<ResultType>(base);
while (src_cur < src_len && isalnum(src[src_cur])) {
int cur_digit = b36_char_to_int(src[src_cur]);
@ -141,17 +140,17 @@ strtointeger(const char *__restrict src, int base,
result = abs_max;
error_val = ERANGE;
} else {
result = static_cast<ResultType>(result * base);
result = result * static_cast<ResultType>(base);
}
if (result > abs_max - cur_digit) {
if (result > abs_max - static_cast<ResultType>(cur_digit)) {
result = abs_max;
error_val = ERANGE;
} else {
result = static_cast<ResultType>(result + cur_digit);
result = result + static_cast<ResultType>(cur_digit);
}
}
ptrdiff_t str_len = is_number ? (src_cur) : 0;
ptrdiff_t str_len = is_number ? static_cast<ptrdiff_t>(src_cur) : 0;
if (error_val == ERANGE) {
if (is_positive || IS_UNSIGNED)

View File

@ -1,47 +0,0 @@
//===-- Implementation header for libc_errno --------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC_ERRNO_LIBC_ERRNO_H
#define LLVM_LIBC_SRC_ERRNO_LIBC_ERRNO_H
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/architectures.h"
#include "hdr/errno_macros.h"
// This header is to be consumed by internal implementations, in which all of
// them should refer to `libc_errno` instead of using `errno` directly from
// <errno.h> header.
// Unit and hermetic tests should:
// - #include "src/errno/libc_errno.h"
// - NOT #include <errno.h>
// - Only use `libc_errno` in the code
// - Depend on libc.src.errno.errno
// Integration tests should:
// - NOT #include "src/errno/libc_errno.h"
// - #include <errno.h>
// - Use regular `errno` in the code
// - Still depend on libc.src.errno.errno
namespace LIBC_NAMESPACE_DECL {
extern "C" int *__llvm_libc_errno() noexcept;
struct Errno {
void operator=(int);
operator int();
};
extern Errno libc_errno;
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_ERRNO_LIBC_ERRNO_H