diff options
| author | Mingming Liu <mingmingl@google.com> | 2025-09-10 15:25:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-10 15:25:31 -0700 |
| commit | 1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch) | |
| tree | 57f4b1f313c8cf74eed8819870f39c36ea263c68 /libc/src | |
| parent | 898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff) | |
| parent | b8cefcb601ddaa18482555c4ff363c01a270c2fe (diff) | |
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'libc/src')
87 files changed, 2207 insertions, 71 deletions
diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index 2196d9e23bba..b6e87ac336fb 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -97,6 +97,7 @@ add_header_library( common.h endian_internal.h macros/properties/architectures.h + macros/properties/compiler.h macros/attributes.h macros/config.h DEPENDS diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt index 8b65a8839ab2..d9b86b4fd297 100644 --- a/libc/src/__support/CPP/CMakeLists.txt +++ b/libc/src/__support/CPP/CMakeLists.txt @@ -171,6 +171,7 @@ add_header_library( libc.include.llvm-libc-macros.stdfix_macros libc.src.__support.macros.attributes libc.src.__support.macros.properties.types + libc.src.__support.macros.properties.compiler libc.src.__support.macros.properties.complex_types ) @@ -210,3 +211,17 @@ add_object_library( libc.src.__support.common libc.src.__support.macros.properties.os ) + +add_header_library( + tuple + HDRS + tuple.h + DEPENDS + .utility +) + +add_header_library( + simd + HDRS + simd.h +) diff --git a/libc/src/__support/CPP/algorithm.h b/libc/src/__support/CPP/algorithm.h index 7704b3fa81f0..de0c47369d94 100644 --- a/libc/src/__support/CPP/algorithm.h +++ b/libc/src/__support/CPP/algorithm.h @@ -18,6 +18,12 @@ namespace LIBC_NAMESPACE_DECL { namespace cpp { +template <class T = void> struct plus {}; +template <class T = void> struct multiplies {}; +template <class T = void> struct bit_and {}; +template <class T = void> struct bit_or {}; +template <class T = void> struct bit_xor {}; + template <class T> LIBC_INLINE constexpr const T &max(const T &a, const T &b) { return (a < b) ? b : a; } diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h index df1b177ecb10..5a997ef55570 100644 --- a/libc/src/__support/CPP/bit.h +++ b/libc/src/__support/CPP/bit.h @@ -104,10 +104,16 @@ countr_zero(T value) { } #if __has_builtin(__builtin_ctzs) ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs) -#endif +#endif // __has_builtin(__builtin_ctzs) +#if __has_builtin(__builtin_ctz) ADD_SPECIALIZATION(countr_zero, unsigned int, __builtin_ctz) +#endif // __has_builtin(__builtin_ctz) +#if __has_builtin(__builtin_ctzl) ADD_SPECIALIZATION(countr_zero, unsigned long, __builtin_ctzl) +#endif // __has_builtin(__builtin_ctzl) +#if __has_builtin(__builtin_ctzll) ADD_SPECIALIZATION(countr_zero, unsigned long long, __builtin_ctzll) +#endif // __has_builtin(__builtin_ctzll) #endif // __has_builtin(__builtin_ctzg) /// Count number of 0's from the most significant bit to the least @@ -143,10 +149,16 @@ countl_zero(T value) { } #if __has_builtin(__builtin_clzs) ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs) -#endif +#endif // __has_builtin(__builtin_clzs) +#if __has_builtin(__builtin_clz) ADD_SPECIALIZATION(countl_zero, unsigned int, __builtin_clz) +#endif // __has_builtin(__builtin_clz) +#if __has_builtin(__builtin_clzl) ADD_SPECIALIZATION(countl_zero, unsigned long, __builtin_clzl) +#endif // __has_builtin(__builtin_clzl) +#if __has_builtin(__builtin_clzll) ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll) +#endif // __has_builtin(__builtin_clzll) #endif // __has_builtin(__builtin_clzg) #undef ADD_SPECIALIZATION @@ -283,11 +295,17 @@ popcount(T value) { [[nodiscard]] LIBC_INLINE constexpr int popcount<TYPE>(TYPE value) { \ return BUILTIN(value); \ } +#if __has_builtin(__builtin_popcount) ADD_SPECIALIZATION(unsigned char, __builtin_popcount) ADD_SPECIALIZATION(unsigned short, __builtin_popcount) ADD_SPECIALIZATION(unsigned, __builtin_popcount) +#endif // __builtin_popcount +#if __has_builtin(__builtin_popcountl) ADD_SPECIALIZATION(unsigned long, __builtin_popcountl) +#endif // __builtin_popcountl +#if __has_builtin(__builtin_popcountll) ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) +#endif // __builtin_popcountll #endif // __builtin_popcountg #undef ADD_SPECIALIZATION diff --git a/libc/src/__support/CPP/simd.h b/libc/src/__support/CPP/simd.h new file mode 100644 index 000000000000..54fe70a6e983 --- /dev/null +++ b/libc/src/__support/CPP/simd.h @@ -0,0 +1,282 @@ +//===-- Portable SIMD library similar to stdx::simd -------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file provides a generic interface into fixed-size SIMD instructions +// using the clang vector type. The API shares some similarities with the +// stdx::simd proposal, but instead chooses to use vectors as primitive types +// with several extra helper functions. +// +//===----------------------------------------------------------------------===// + +#include "hdr/stdint_proxy.h" +#include "src/__support/CPP/algorithm.h" +#include "src/__support/CPP/limits.h" +#include "src/__support/CPP/type_traits.h" +#include "src/__support/macros/attributes.h" +#include "src/__support/macros/config.h" + +#include <stddef.h> + +#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_SIMD_H +#define LLVM_LIBC_SRC___SUPPORT_CPP_SIMD_H + +#if LIBC_HAS_VECTOR_TYPE + +namespace LIBC_NAMESPACE_DECL { +namespace cpp { + +namespace internal { + +template <typename T> +using get_as_integer_type_t = unsigned _BitInt(sizeof(T) * CHAR_BIT); + +#if defined(LIBC_TARGET_CPU_HAS_AVX512F) +template <typename T> +LIBC_INLINE_VAR constexpr size_t native_vector_size = 64 / sizeof(T); +#elif defined(LIBC_TARGET_CPU_HAS_AVX2) +template <typename T> +LIBC_INLINE_VAR constexpr size_t native_vector_size = 32 / sizeof(T); +#elif defined(LIBC_TARGET_CPU_HAS_SSE2) || defined(LIBC_TARGET_CPU_HAS_ARM_NEON) +template <typename T> +LIBC_INLINE_VAR constexpr size_t native_vector_size = 16 / sizeof(T); +#else +template <typename T> LIBC_INLINE constexpr size_t native_vector_size = 1; +#endif + +template <typename T> LIBC_INLINE constexpr T poison() { + return __builtin_nondeterministic_value(T()); +} +} // namespace internal + +// Type aliases. +template <typename T, size_t N> +using fixed_size_simd = T [[clang::ext_vector_type(N)]]; +template <typename T, size_t N = internal::native_vector_size<T>> +using simd = T [[clang::ext_vector_type(N)]]; +template <typename T> +using simd_mask = simd<bool, internal::native_vector_size<T>>; + +// Type trait helpers. +template <typename T> +struct simd_size : cpp::integral_constant<size_t, __builtin_vectorelements(T)> { +}; +template <class T> constexpr size_t simd_size_v = simd_size<T>::value; + +template <typename T> struct is_simd : cpp::integral_constant<bool, false> {}; +template <typename T, unsigned N> +struct is_simd<simd<T, N>> : cpp::integral_constant<bool, true> {}; +template <class T> constexpr bool is_simd_v = is_simd<T>::value; + +template <typename T> +struct is_simd_mask : cpp::integral_constant<bool, false> {}; +template <unsigned N> +struct is_simd_mask<simd<bool, N>> : cpp::integral_constant<bool, true> {}; +template <class T> constexpr bool is_simd_mask_v = is_simd_mask<T>::value; + +template <typename T> struct simd_element_type; +template <typename T, size_t N> struct simd_element_type<simd<T, N>> { + using type = T; +}; +template <typename T> +using simd_element_type_t = typename simd_element_type<T>::type; + +template <typename T> +using enable_if_simd_t = cpp::enable_if_t<is_simd_v<T>, T>; + +// Casting. +template <typename To, typename From, size_t N> +LIBC_INLINE constexpr static simd<To, N> simd_cast(simd<From, N> v) { + return __builtin_convertvector(v, simd<To, N>); +} + +// SIMD mask operations. +template <size_t N> LIBC_INLINE constexpr static bool all_of(simd<bool, N> m) { + return __builtin_reduce_and(m); +} +template <size_t N> LIBC_INLINE constexpr static bool any_of(simd<bool, N> m) { + return __builtin_reduce_or(m); +} +template <size_t N> LIBC_INLINE constexpr static bool none_of(simd<bool, N> m) { + return !any_of(m); +} +template <size_t N> LIBC_INLINE constexpr static bool some_of(simd<bool, N> m) { + return any_of(m) && !all_of(m); +} +template <size_t N> LIBC_INLINE constexpr static int popcount(simd<bool, N> m) { + return __builtin_popcountg(m); +} +template <size_t N> +LIBC_INLINE constexpr static int find_first_set(simd<bool, N> m) { + return __builtin_ctzg(m); +} +template <size_t N> +LIBC_INLINE constexpr static int find_last_set(simd<bool, N> m) { + constexpr size_t size = simd_size_v<simd<bool, N>>; + return size - 1 - __builtin_clzg(m); +} + +// Elementwise operations. +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> min(simd<T, N> x, simd<T, N> y) { + return __builtin_elementwise_min(x, y); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> max(simd<T, N> x, simd<T, N> y) { + return __builtin_elementwise_max(x, y); +} + +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> abs(simd<T, N> x) { + return __builtin_elementwise_abs(x); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> fma(simd<T, N> x, simd<T, N> y, + simd<T, N> z) { + return __builtin_elementwise_fma(x, y, z); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> ceil(simd<T, N> x) { + return __builtin_elementwise_ceil(x); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> floor(simd<T, N> x) { + return __builtin_elementwise_floor(x); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> roundeven(simd<T, N> x) { + return __builtin_elementwise_roundeven(x); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> round(simd<T, N> x) { + return __builtin_elementwise_round(x); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> trunc(simd<T, N> x) { + return __builtin_elementwise_trunc(x); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> nearbyint(simd<T, N> x) { + return __builtin_elementwise_nearbyint(x); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> rint(simd<T, N> x) { + return __builtin_elementwise_rint(x); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> canonicalize(simd<T, N> x) { + return __builtin_elementwise_canonicalize(x); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> copysign(simd<T, N> x, simd<T, N> y) { + return __builtin_elementwise_copysign(x, y); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> fmod(simd<T, N> x, simd<T, N> y) { + return __builtin_elementwise_fmod(x, y); +} + +// Reduction operations. +template <typename T, size_t N, typename Op = cpp::plus<>> +LIBC_INLINE constexpr static T reduce(simd<T, N> v, Op op = {}) { + return reduce(v, op); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static T reduce(simd<T, N> v, cpp::plus<>) { + return __builtin_reduce_add(v); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static T reduce(simd<T, N> v, cpp::multiplies<>) { + return __builtin_reduce_mul(v); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static T reduce(simd<T, N> v, cpp::bit_and<>) { + return __builtin_reduce_and(v); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static T reduce(simd<T, N> v, cpp::bit_or<>) { + return __builtin_reduce_or(v); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static T reduce(simd<T, N> v, cpp::bit_xor<>) { + return __builtin_reduce_xor(v); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static T hmin(simd<T, N> v) { + return __builtin_reduce_min(v); +} +template <typename T, size_t N> +LIBC_INLINE constexpr static T hmax(simd<T, N> v) { + return __builtin_reduce_max(v); +} + +// Accessor helpers. +template <typename T> +LIBC_INLINE enable_if_simd_t<T> load_unaligned(const void *ptr) { + T tmp; + __builtin_memcpy(&tmp, ptr, sizeof(T)); + return tmp; +} +template <typename T> +LIBC_INLINE enable_if_simd_t<T> load_aligned(const void *ptr) { + return load_unaligned<T>(__builtin_assume_aligned(ptr, alignof(T))); +} +template <typename T> +LIBC_INLINE enable_if_simd_t<T> store_unaligned(T v, void *ptr) { + __builtin_memcpy(ptr, &v, sizeof(T)); +} +template <typename T> +LIBC_INLINE enable_if_simd_t<T> store_aligned(T v, void *ptr) { + store_unaligned<T>(v, __builtin_assume_aligned(ptr, alignof(T))); +} +template <typename T> +LIBC_INLINE enable_if_simd_t<T> +masked_load(simd<bool, simd_size_v<T>> m, void *ptr, + T passthru = internal::poison<simd_element_type<T>>()) { + return __builtin_masked_load(m, ptr, passthru); +} +template <typename T> +LIBC_INLINE enable_if_simd_t<T> masked_store(simd<bool, simd_size_v<T>> m, T v, + void *ptr) { + __builtin_masked_store( + m, v, static_cast<T *>(__builtin_assume_aligned(ptr, alignof(T)))); +} + +// Construction helpers. +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> splat(T v) { + return simd<T, N>(v); +} +template <typename T> LIBC_INLINE constexpr static simd<T> splat(T v) { + return splat<T, simd_size_v<simd<T>>>(v); +} +template <typename T, unsigned N> +LIBC_INLINE constexpr static simd<T, N> iota(T base = T(0), T step = T(1)) { + simd<T, N> v{}; + for (unsigned i = 0; i < N; ++i) + v[i] = base + T(i) * step; + return v; +} +template <typename T> +LIBC_INLINE constexpr static simd<T> iota(T base = T(0), T step = T(1)) { + return iota<T, simd_size_v<simd<T>>>(base, step); +} + +// Conditional helpers. +template <typename T, size_t N> +LIBC_INLINE constexpr static simd<T, N> select(simd<bool, N> m, simd<T, N> x, + simd<T, N> y) { + return m ? x : y; +} + +// TODO: where expressions, scalar overloads, ABI types. + +} // namespace cpp +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_HAS_VECTOR_TYPE +#endif diff --git a/libc/src/__support/CPP/tuple.h b/libc/src/__support/CPP/tuple.h new file mode 100644 index 000000000000..cce8e0ef2bfa --- /dev/null +++ b/libc/src/__support/CPP/tuple.h @@ -0,0 +1,144 @@ +//===-- tuple utility -------------------------------------------*- 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___SUPPORT_CPP_UTILITY_TUPLE_H +#define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_TUPLE_H + +#include "src/__support/CPP/type_traits/decay.h" +#include "src/__support/CPP/utility/integer_sequence.h" + +namespace LIBC_NAMESPACE_DECL { +namespace cpp { + +template <typename... Ts> struct tuple; +template <> struct tuple<> {}; + +template <typename Head, typename... Tail> +struct tuple<Head, Tail...> : tuple<Tail...> { + Head head; + + LIBC_INLINE constexpr tuple() = default; + + template <typename OHead, typename... OTail> + LIBC_INLINE constexpr tuple &operator=(const tuple<OHead, OTail...> &other) { + head = other.get_head(); + this->get_tail() = other.get_tail(); + return *this; + } + + LIBC_INLINE constexpr tuple(const Head &h, const Tail &...t) + : tuple<Tail...>(t...), head(h) {} + + LIBC_INLINE constexpr Head &get_head() { return head; } + LIBC_INLINE constexpr const Head &get_head() const { return head; } + + LIBC_INLINE constexpr tuple<Tail...> &get_tail() { return *this; } + LIBC_INLINE constexpr const tuple<Tail...> &get_tail() const { return *this; } +}; + +template <typename... Ts> LIBC_INLINE constexpr auto make_tuple(Ts &&...args) { + return tuple<cpp::decay_t<Ts>...>(static_cast<Ts &&>(args)...); +} +template <typename... Ts> LIBC_INLINE constexpr auto tie(Ts &...args) { + return tuple<Ts &...>(args...); +} + +template <size_t I, typename Head, typename... Tail> +LIBC_INLINE constexpr auto &get(tuple<Head, Tail...> &t) { + if constexpr (I == 0) + return t.get_head(); + else + return get<I - 1>(t.get_tail()); +} +template <size_t I, typename Head, typename... Tail> +LIBC_INLINE constexpr const auto &get(const tuple<Head, Tail...> &t) { + if constexpr (I == 0) + return t.get_head(); + else + return get<I - 1>(t.get_tail()); +} +template <size_t I, typename Head, typename... Tail> +LIBC_INLINE constexpr auto &&get(tuple<Head, Tail...> &&t) { + if constexpr (I == 0) + return static_cast<Head &&>(t.get_head()); + else + return get<I - 1>(static_cast<tuple<Tail...> &&>(t.get_tail())); +} +template <size_t I, typename Head, typename... Tail> +LIBC_INLINE constexpr const auto &&get(const tuple<Head, Tail...> &&t) { + if constexpr (I == 0) + return static_cast<const Head &&>(t.get_head()); + else + return get<I - 1>(static_cast<const tuple<Tail...> &&>(t.get_tail())); +} + +template <typename T> struct tuple_size; +template <typename... Ts> struct tuple_size<tuple<Ts...>> { + static constexpr size_t value = sizeof...(Ts); +}; + +template <size_t I, typename T> struct tuple_element; +template <size_t I, typename Head, typename... Tail> +struct tuple_element<I, tuple<Head, Tail...>> + : tuple_element<I - 1, tuple<Tail...>> {}; +template <typename Head, typename... Tail> +struct tuple_element<0, tuple<Head, Tail...>> { + using type = cpp::remove_cv_t<cpp::remove_reference_t<Head>>; +}; + +namespace internal { +template <typename... As, typename... Bs, size_t... I, size_t... J> +LIBC_INLINE constexpr auto +tuple_cat(const tuple<As...> &a, const tuple<Bs...> &b, + cpp::index_sequence<I...>, cpp::index_sequence<J...>) { + return tuple<As..., Bs...>(get<I>(a)..., get<J>(b)...); +} + +template <typename First, typename Second, typename... Rest> +LIBC_INLINE constexpr auto tuple_cat(const First &f, const Second &s, + const Rest &...rest) { + auto concat = + tuple_cat(f, s, cpp::make_index_sequence<tuple_size<First>::value>{}, + cpp::make_index_sequence<tuple_size<Second>::value>{}); + if constexpr (sizeof...(Rest)) + return tuple_cat(concat, rest...); + else + return concat; +} +} // namespace internal + +template <typename... Tuples> +LIBC_INLINE constexpr auto tuple_cat(const Tuples &...tuples) { + static_assert(sizeof...(Tuples) > 0, "need at least one element"); + if constexpr (sizeof...(Tuples) == 1) + return (tuples, ...); + else + return internal::tuple_cat(tuples...); +} + +} // namespace cpp +} // namespace LIBC_NAMESPACE_DECL + +// Standard namespace definitions required for structured binding support. +namespace std { + +template <class T> struct tuple_size; +template <size_t I, class T> struct tuple_element; + +template <typename... Ts> +struct tuple_size<LIBC_NAMESPACE::cpp::tuple<Ts...>> + : LIBC_NAMESPACE::cpp::tuple_size<LIBC_NAMESPACE::cpp::tuple<Ts...>> {}; + +template <size_t I, typename... Ts> +struct tuple_element<I, LIBC_NAMESPACE::cpp::tuple<Ts...>> + : LIBC_NAMESPACE::cpp::tuple_element<I, LIBC_NAMESPACE::cpp::tuple<Ts...>> { +}; + +} // namespace std + +#endif // LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_TUPLE_H diff --git a/libc/src/__support/CPP/type_traits/is_complex.h b/libc/src/__support/CPP/type_traits/is_complex.h index 23f05c08ccab..5da1a40892c2 100644 --- a/libc/src/__support/CPP/type_traits/is_complex.h +++ b/libc/src/__support/CPP/type_traits/is_complex.h @@ -13,12 +13,17 @@ #include "src/__support/macros/attributes.h" #include "src/__support/macros/config.h" // LIBC_TYPES_HAS_CFLOAT16 && LIBC_TYPES_HAS_CFLOAT128 +#include "src/__support/macros/properties/compiler.h" #include "src/__support/macros/properties/complex_types.h" namespace LIBC_NAMESPACE_DECL { namespace cpp { // is_complex +#ifdef LIBC_COMPILER_IS_MSVC +// TODO: Add support for complex types with MSVC. +template <typename T> struct is_complex : false_type {}; +#else template <typename T> struct is_complex { private: template <typename Head, typename... Args> @@ -40,6 +45,8 @@ public: #endif >(); }; +#endif // LIBC_COMPILER_IS_MSVC + template <typename T> LIBC_INLINE_VAR constexpr bool is_complex_v = is_complex<T>::value; template <typename T1, typename T2> diff --git a/libc/src/__support/CPP/utility/integer_sequence.h b/libc/src/__support/CPP/utility/integer_sequence.h index 06643d505aca..17c3dbfd229c 100644 --- a/libc/src/__support/CPP/utility/integer_sequence.h +++ b/libc/src/__support/CPP/utility/integer_sequence.h @@ -5,12 +5,15 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H #define LLVM_LIBC_SRC___SUPPORT_CPP_UTILITY_INTEGER_SEQUENCE_H #include "src/__support/CPP/type_traits/is_integral.h" #include "src/__support/macros/config.h" +#include <stddef.h> + namespace LIBC_NAMESPACE_DECL { namespace cpp { @@ -34,6 +37,13 @@ template <typename T, int N> using make_integer_sequence = typename detail::make_integer_sequence<T, N - 1>::type; +// index sequence +template <size_t... Ints> +using index_sequence = integer_sequence<size_t, Ints...>; +template <int N> +using make_index_sequence = + typename detail::make_integer_sequence<size_t, N - 1>::type; + } // namespace cpp } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index 994237ba8492..ca7be6676630 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -244,7 +244,7 @@ LIBC_INLINE T fdim(T x, T y) { return y; } - return (x > y ? x - y : 0); + return (x > y ? x - y : T(0)); } // Avoid reusing `issignaling` macro. @@ -354,10 +354,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> getpayload(T x) { return static_cast<T>(payload_dfloat); } else { - if constexpr (cpp::is_same_v<T, bfloat16>) - return T(static_cast<int>(payload)); - else - return static_cast<T>(payload); + return static_cast<T>(payload); } } diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt index 37520eadba00..e8fc539fd32e 100644 --- a/libc/src/__support/FPUtil/CMakeLists.txt +++ b/libc/src/__support/FPUtil/CMakeLists.txt @@ -231,6 +231,7 @@ add_header_library( Hypot.h DEPENDS .basic_operations + .cast .fenv_impl .fp_bits .rounding_mode diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h index 94da259cd42f..e23f8b52d822 100644 --- a/libc/src/__support/FPUtil/Hypot.h +++ b/libc/src/__support/FPUtil/Hypot.h @@ -12,6 +12,7 @@ #include "BasicOperations.h" #include "FEnvImpl.h" #include "FPBits.h" +#include "cast.h" #include "rounding_mode.h" #include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" @@ -133,8 +134,18 @@ LIBC_INLINE T hypot(T x, T y) { uint16_t a_exp = a_bits.get_biased_exponent(); uint16_t b_exp = b_bits.get_biased_exponent(); - if ((a_exp - b_exp >= FPBits_t::FRACTION_LEN + 2) || (x == 0) || (y == 0)) - return x_abs.get_val() + y_abs.get_val(); + if ((a_exp - b_exp >= FPBits_t::FRACTION_LEN + 2) || (x == 0) || (y == 0)) { +#ifdef LIBC_TYPES_HAS_FLOAT16 + if constexpr (cpp::is_same_v<T, float16>) { + // Compiler runtime for basic operations of float16 might not be correctly + // rounded for all rounding modes. + float af = fputil::cast<float>(x_abs.get_val()); + float bf = fputil::cast<float>(y_abs.get_val()); + return fputil::cast<float16>(af + bf); + } else +#endif // LIBC_TYPES_HAS_FLOAT16 + return x_abs.get_val() + y_abs.get_val(); + } uint64_t out_exp = a_exp; StorageType a_mant = a_bits.get_mantissa(); diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h index ba97b42e2321..13e151208567 100644 --- a/libc/src/__support/FPUtil/bfloat16.h +++ b/libc/src/__support/FPUtil/bfloat16.h @@ -29,7 +29,9 @@ struct BFloat16 { LIBC_INLINE BFloat16() = default; - template <typename T> LIBC_INLINE constexpr explicit BFloat16(T value) { + template <typename T> + LIBC_INLINE constexpr explicit BFloat16(T value) + : bits(static_cast<uint16_t>(0U)) { if constexpr (cpp::is_floating_point_v<T>) { bits = fputil::cast<bfloat16>(value).bits; } else if constexpr (cpp::is_integral_v<T>) { @@ -46,6 +48,8 @@ struct BFloat16 { xd(sign, 0, value); bits = xd.template as<bfloat16, /*ShouldSignalExceptions=*/true>().bits; + } else if constexpr (cpp::is_convertible_v<T, BFloat16>) { + bits = value.operator BFloat16().bits; } else { bits = fputil::cast<bfloat16>(static_cast<float>(value)).bits; } diff --git a/libc/src/__support/StringUtil/error_to_string.cpp b/libc/src/__support/StringUtil/error_to_string.cpp index 3b22021706bb..38916af83795 100644 --- a/libc/src/__support/StringUtil/error_to_string.cpp +++ b/libc/src/__support/StringUtil/error_to_string.cpp @@ -7,8 +7,10 @@ //===----------------------------------------------------------------------===// #include "error_to_string.h" -#include "platform_errors.h" +#include <stddef.h> + +#include "platform_errors.h" #include "src/__support/CPP/span.h" #include "src/__support/CPP/string_view.h" #include "src/__support/CPP/stringstream.h" @@ -17,10 +19,8 @@ #include "src/__support/macros/attributes.h" #include "src/__support/macros/config.h" -#include <stddef.h> - namespace LIBC_NAMESPACE_DECL { -namespace internal { +namespace { constexpr size_t max_buff_size() { constexpr size_t unknown_str_len = sizeof("Unknown error"); @@ -63,23 +63,22 @@ cpp::string_view build_error_string(int err_num, cpp::span<char> buffer) { return buffer_stream.str(); } -} // namespace internal +} // namespace cpp::string_view get_error_string(int err_num) { - return get_error_string(err_num, - {internal::error_buffer, internal::ERR_BUFFER_SIZE}); + return get_error_string(err_num, {error_buffer, ERR_BUFFER_SIZE}); } cpp::string_view get_error_string(int err_num, cpp::span<char> buffer) { - auto opt_str = internal::ERROR_MAPPER.get_str(err_num); + auto opt_str = ERROR_MAPPER.get_str(err_num); if (opt_str) return *opt_str; else - return internal::build_error_string(err_num, buffer); + return build_error_string(err_num, buffer); } cpp::optional<cpp::string_view> try_get_errno_name(int err_num) { - return internal::ERRNO_NAME_MAPPER.get_str(err_num); + return ERRNO_NAME_MAPPER.get_str(err_num); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/StringUtil/platform_errors.h b/libc/src/__support/StringUtil/platform_errors.h index 32e8414b3e3d..5f83865482e7 100644 --- a/libc/src/__support/StringUtil/platform_errors.h +++ b/libc/src/__support/StringUtil/platform_errors.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_STRINGUTIL_PLATFORM_ERRORS_H #define LLVM_LIBC_SRC___SUPPORT_STRINGUTIL_PLATFORM_ERRORS_H -#if defined(__linux__) || defined(__Fuchsia__) +#if defined(__linux__) || defined(__Fuchsia__) || defined(__EMSCRIPTEN__) #include "tables/linux_platform_errors.h" #else #include "tables/minimal_platform_errors.h" diff --git a/libc/src/__support/StringUtil/signal_to_string.cpp b/libc/src/__support/StringUtil/signal_to_string.cpp index b67d28814816..e5863ff1e898 100644 --- a/libc/src/__support/StringUtil/signal_to_string.cpp +++ b/libc/src/__support/StringUtil/signal_to_string.cpp @@ -7,8 +7,11 @@ //===----------------------------------------------------------------------===// #include "signal_to_string.h" -#include "platform_signals.h" +#include <signal.h> +#include <stddef.h> + +#include "platform_signals.h" #include "src/__support/CPP/span.h" #include "src/__support/CPP/string_view.h" #include "src/__support/CPP/stringstream.h" @@ -17,11 +20,8 @@ #include "src/__support/macros/attributes.h" #include "src/__support/macros/config.h" -#include <signal.h> -#include <stddef.h> - namespace LIBC_NAMESPACE_DECL { -namespace internal { +namespace { constexpr size_t max_buff_size() { constexpr size_t base_str_len = sizeof("Real-time signal"); @@ -63,19 +63,18 @@ cpp::string_view build_signal_string(int sig_num, cpp::span<char> buffer) { return buffer_stream.str(); } -} // namespace internal +} // namespace cpp::string_view get_signal_string(int sig_num) { - return get_signal_string( - sig_num, {internal::signal_buffer, internal::SIG_BUFFER_SIZE}); + return get_signal_string(sig_num, {signal_buffer, SIG_BUFFER_SIZE}); } cpp::string_view get_signal_string(int sig_num, cpp::span<char> buffer) { - auto opt_str = internal::signal_mapper.get_str(sig_num); + auto opt_str = signal_mapper.get_str(sig_num); if (opt_str) return *opt_str; else - return internal::build_signal_string(sig_num, buffer); + return build_signal_string(sig_num, buffer); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/common.h b/libc/src/__support/common.h index 15209b76978a..a2808147f3e5 100644 --- a/libc/src/__support/common.h +++ b/libc/src/__support/common.h @@ -16,6 +16,7 @@ #include "src/__support/macros/attributes.h" #include "src/__support/macros/config.h" #include "src/__support/macros/properties/architectures.h" +#include "src/__support/macros/properties/compiler.h" #ifndef LLVM_LIBC_FUNCTION_ATTR #define LLVM_LIBC_FUNCTION_ATTR @@ -41,12 +42,12 @@ // 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) +#if defined(LIBC_COPT_PUBLIC_PACKAGING) && !defined(LIBC_COMPILER_IS_MSVC) #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); \ + __##name##_impl__ asm(#name); \ decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \ type __##name##_impl__ arglist #else // __APPLE__ diff --git a/libc/src/__support/macros/CMakeLists.txt b/libc/src/__support/macros/CMakeLists.txt index a639d3ef89e5..8e17642d02fb 100644 --- a/libc/src/__support/macros/CMakeLists.txt +++ b/libc/src/__support/macros/CMakeLists.txt @@ -4,6 +4,9 @@ add_header_library( config HDRS config.h + DEPENDS + libc.src.__support.macros.properties.architectures + libc.src.__support.macros.properties.compiler ) add_header_library( diff --git a/libc/src/__support/macros/attributes.h b/libc/src/__support/macros/attributes.h index 4ff374b0e4fb..145aa3b65057 100644 --- a/libc/src/__support/macros/attributes.h +++ b/libc/src/__support/macros/attributes.h @@ -17,6 +17,7 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H #define LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H +#include "config.h" #include "properties/architectures.h" #ifndef __has_attribute @@ -73,4 +74,11 @@ LIBC_THREAD_MODE_EXTERNAL. #define LIBC_PREFERED_TYPE(TYPE) #endif +#if __has_attribute(ext_vector_type) && \ + LIBC_HAS_FEATURE(ext_vector_type_boolean) +#define LIBC_HAS_VECTOR_TYPE 1 +#else +#define LIBC_HAS_VECTOR_TYPE 0 +#endif + #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H diff --git a/libc/src/__support/macros/config.h b/libc/src/__support/macros/config.h index 2ab0fba095e6..685188893e7b 100644 --- a/libc/src/__support/macros/config.h +++ b/libc/src/__support/macros/config.h @@ -13,6 +13,13 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H #define LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H +#include "src/__support/macros/properties/architectures.h" +#include "src/__support/macros/properties/compiler.h" + +#ifdef LIBC_COMPILER_IS_MSVC +#include <intrin.h> +#endif // LIBC_COMPILER_IS_MSVC + // Workaround for compilers that do not support builtin detection. // FIXME: This is only required for the GPU portion which should be moved. #ifndef __has_builtin @@ -27,6 +34,19 @@ #define LIBC_HAS_FEATURE(f) 0 #endif +#ifdef LIBC_COMPILER_IS_MSVC + +// __builtin_trap replacement +#ifdef LIBC_TARGET_ARCH_IS_X86 +#define __builtin_trap __ud2 +#else // arm64 +#define __builtin_trap() __break(1) +#endif + +#define __builtin_expect(value, expectation) (value) + +#endif // LIBC_COMPILER_IS_MSVC + #ifdef __clang__ // Declare a LIBC_NAMESPACE with hidden visibility. `namespace // LIBC_NAMESPACE_DECL {` should be used around all declarations and definitions diff --git a/libc/src/__support/macros/optimization.h b/libc/src/__support/macros/optimization.h index 250a9e060728..dbefd20a5cd1 100644 --- a/libc/src/__support/macros/optimization.h +++ b/libc/src/__support/macros/optimization.h @@ -34,6 +34,9 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) { #elif defined(LIBC_COMPILER_IS_GCC) #define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0") #define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048") +#elif defined(LIBC_COMPILER_IS_MSVC) +#define LIBC_LOOP_NOUNROLL +#define LIBC_LOOP_UNROLL #else #error "Unhandled compiler" #endif diff --git a/libc/src/__support/macros/properties/architectures.h b/libc/src/__support/macros/properties/architectures.h index ecc93196be28..21e9bc4288cd 100644 --- a/libc/src/__support/macros/properties/architectures.h +++ b/libc/src/__support/macros/properties/architectures.h @@ -41,6 +41,10 @@ #define LIBC_TARGET_ARCH_IS_ARM #endif +#if defined(__wasm__) +#define LIBC_TARGET_ARCH_IS_WASM +#endif + #if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) #define LIBC_TARGET_ARCH_IS_AARCH64 #endif diff --git a/libc/src/__support/macros/properties/compiler.h b/libc/src/__support/macros/properties/compiler.h index b9ec0dd1defb..6947bc7aa901 100644 --- a/libc/src/__support/macros/properties/compiler.h +++ b/libc/src/__support/macros/properties/compiler.h @@ -34,10 +34,10 @@ #define LIBC_COMPILER_GCC_VER (__GNUC__ * 100 + __GNUC_MINOR__) #endif -#if defined(_MSC_VER) -#define LIBC_COMPILER_IS_MSC +#if defined(_MSC_VER) && !defined(__clang__) +#define LIBC_COMPILER_IS_MSVC // https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros -#define LIBC_COMPILER_MSC_VER (_MSC_VER) +#define LIBC_COMPILER_MSVC_VER (_MSC_VER) #endif #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_COMPILER_H diff --git a/libc/src/__support/macros/properties/cpu_features.h b/libc/src/__support/macros/properties/cpu_features.h index fde30eadfd83..fc6099ca6ccc 100644 --- a/libc/src/__support/macros/properties/cpu_features.h +++ b/libc/src/__support/macros/properties/cpu_features.h @@ -59,6 +59,10 @@ #endif // LIBC_TARGET_CPU_HAS_ARM_FPU_DOUBLE #endif // __ARM_FP +#if defined(__ARM_NEON) +#define LIBC_TARGET_CPU_HAS_ARM_NEON +#endif + #if defined(__riscv_flen) // https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc #if defined(__riscv_zfhmin) diff --git a/libc/src/__support/threads/thread.cpp b/libc/src/__support/threads/thread.cpp index 6f6b75be5766..9618d7829161 100644 --- a/libc/src/__support/threads/thread.cpp +++ b/libc/src/__support/threads/thread.cpp @@ -163,6 +163,8 @@ void call_atexit_callbacks(ThreadAttributes *attrib) { } } +extern "C" void __cxa_thread_finalize() { call_atexit_callbacks(self.attrib); } + } // namespace internal cpp::optional<unsigned int> new_tss_key(TSSDtor *dtor) { diff --git a/libc/src/__support/threads/thread.h b/libc/src/__support/threads/thread.h index 114ab4932af7..6806098653b2 100644 --- a/libc/src/__support/threads/thread.h +++ b/libc/src/__support/threads/thread.h @@ -110,7 +110,7 @@ struct alignas(STACK_ALIGNMENT) ThreadAttributes { ThreadAtExitCallbackMgr *atexit_callback_mgr; void *platform_data; - constexpr ThreadAttributes() + LIBC_INLINE constexpr ThreadAttributes() : detach_state(uint32_t(DetachState::DETACHED)), stack(nullptr), stacksize(0), guardsize(0), tls(0), tls_size(0), owned_stack(false), tid(-1), style(ThreadStyle::POSIX), retval(), diff --git a/libc/src/dlfcn/CMakeLists.txt b/libc/src/dlfcn/CMakeLists.txt index 2ee3ac074267..876d915c8406 100644 --- a/libc/src/dlfcn/CMakeLists.txt +++ b/libc/src/dlfcn/CMakeLists.txt @@ -54,4 +54,5 @@ add_entrypoint_object( dladdr.h DEPENDS libc.include.dlfcn + libc.hdr.types.dl_info ) diff --git a/libc/src/dlfcn/dladdr.cpp b/libc/src/dlfcn/dladdr.cpp index 3db68b4a4c72..7e2a1544ada7 100644 --- a/libc/src/dlfcn/dladdr.cpp +++ b/libc/src/dlfcn/dladdr.cpp @@ -15,7 +15,8 @@ namespace LIBC_NAMESPACE_DECL { // TODO: https:// github.com/llvm/llvm-project/issues/97929 LLVM_LIBC_FUNCTION(int, dladdr, - (const void *__restrict addr, Dl_info *__restrict info)) { + ([[maybe_unused]] const void *__restrict addr, + [[maybe_unused]] Dl_info *__restrict info)) { return -1; } diff --git a/libc/src/dlfcn/dladdr.h b/libc/src/dlfcn/dladdr.h index abbc9a9008d9..1fabe8163902 100644 --- a/libc/src/dlfcn/dladdr.h +++ b/libc/src/dlfcn/dladdr.h @@ -11,6 +11,8 @@ #include "src/__support/macros/config.h" +#include "hdr/types/dl_info.h" + namespace LIBC_NAMESPACE_DECL { int dladdr(const void *__restrict, Dl_info *__restrict); diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index 2fe3d194e134..e418a8b0e24b 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -73,17 +73,21 @@ add_math_entrypoint_object(atanh) add_math_entrypoint_object(atanhf) add_math_entrypoint_object(atanhf16) +add_math_entrypoint_object(atanpif16) + add_math_entrypoint_object(canonicalize) add_math_entrypoint_object(canonicalizef) add_math_entrypoint_object(canonicalizel) add_math_entrypoint_object(canonicalizef16) add_math_entrypoint_object(canonicalizef128) +add_math_entrypoint_object(canonicalizebf16) add_math_entrypoint_object(iscanonical) add_math_entrypoint_object(iscanonicalf) add_math_entrypoint_object(iscanonicall) add_math_entrypoint_object(iscanonicalf16) add_math_entrypoint_object(iscanonicalf128) +add_math_entrypoint_object(iscanonicalbf16) add_math_entrypoint_object(cbrt) add_math_entrypoint_object(cbrtf) @@ -100,6 +104,7 @@ add_math_entrypoint_object(copysignf) add_math_entrypoint_object(copysignl) add_math_entrypoint_object(copysignf16) add_math_entrypoint_object(copysignf128) +add_math_entrypoint_object(copysignbf16) add_math_entrypoint_object(cos) add_math_entrypoint_object(cosf) @@ -203,6 +208,7 @@ add_math_entrypoint_object(fdimf) add_math_entrypoint_object(fdiml) add_math_entrypoint_object(fdimf16) add_math_entrypoint_object(fdimf128) +add_math_entrypoint_object(fdimbf16) add_math_entrypoint_object(fdiv) add_math_entrypoint_object(fdivl) @@ -302,12 +308,14 @@ add_math_entrypoint_object(fmodf) add_math_entrypoint_object(fmodl) add_math_entrypoint_object(fmodf16) add_math_entrypoint_object(fmodf128) +add_math_entrypoint_object(fmodbf16) add_math_entrypoint_object(frexp) add_math_entrypoint_object(frexpf) add_math_entrypoint_object(frexpl) add_math_entrypoint_object(frexpf16) add_math_entrypoint_object(frexpf128) +add_math_entrypoint_object(frexpbf16) add_math_entrypoint_object(fromfp) add_math_entrypoint_object(fromfpf) @@ -343,6 +351,7 @@ add_math_entrypoint_object(ilogbf) add_math_entrypoint_object(ilogbl) add_math_entrypoint_object(ilogbf16) add_math_entrypoint_object(ilogbf128) +add_math_entrypoint_object(ilogbbf16) add_math_entrypoint_object(isnan) add_math_entrypoint_object(isnanf) @@ -353,18 +362,21 @@ add_math_entrypoint_object(issignalingf) add_math_entrypoint_object(issignalingl) add_math_entrypoint_object(issignalingf16) add_math_entrypoint_object(issignalingf128) +add_math_entrypoint_object(issignalingbf16) add_math_entrypoint_object(llogb) add_math_entrypoint_object(llogbf) add_math_entrypoint_object(llogbl) add_math_entrypoint_object(llogbf16) add_math_entrypoint_object(llogbf128) +add_math_entrypoint_object(llogbbf16) add_math_entrypoint_object(ldexp) add_math_entrypoint_object(ldexpf) add_math_entrypoint_object(ldexpl) add_math_entrypoint_object(ldexpf16) add_math_entrypoint_object(ldexpf128) +add_math_entrypoint_object(ldexpbf16) add_math_entrypoint_object(log10) add_math_entrypoint_object(log10f) @@ -386,6 +398,7 @@ add_math_entrypoint_object(logbf) add_math_entrypoint_object(logbl) add_math_entrypoint_object(logbf16) add_math_entrypoint_object(logbf128) +add_math_entrypoint_object(logbbf16) add_math_entrypoint_object(llrint) add_math_entrypoint_object(llrintf) @@ -420,6 +433,7 @@ add_math_entrypoint_object(modff) add_math_entrypoint_object(modfl) add_math_entrypoint_object(modff16) add_math_entrypoint_object(modff128) +add_math_entrypoint_object(modfbf16) add_math_entrypoint_object(nan) add_math_entrypoint_object(nanf) @@ -472,12 +486,14 @@ add_math_entrypoint_object(remainderf) add_math_entrypoint_object(remainderl) add_math_entrypoint_object(remainderf16) add_math_entrypoint_object(remainderf128) +add_math_entrypoint_object(remainderbf16) add_math_entrypoint_object(remquo) add_math_entrypoint_object(remquof) -add_math_entrypoint_object(remquof128) add_math_entrypoint_object(remquol) add_math_entrypoint_object(remquof16) +add_math_entrypoint_object(remquof128) +add_math_entrypoint_object(remquobf16) add_math_entrypoint_object(rint) add_math_entrypoint_object(rintf) @@ -505,12 +521,14 @@ add_math_entrypoint_object(scalblnf) add_math_entrypoint_object(scalblnl) add_math_entrypoint_object(scalblnf16) add_math_entrypoint_object(scalblnf128) +add_math_entrypoint_object(scalblnbf16) add_math_entrypoint_object(scalbn) add_math_entrypoint_object(scalbnf) add_math_entrypoint_object(scalbnl) add_math_entrypoint_object(scalbnf16) add_math_entrypoint_object(scalbnf128) +add_math_entrypoint_object(scalbnbf16) add_math_entrypoint_object(setpayload) add_math_entrypoint_object(setpayloadf) @@ -544,6 +562,7 @@ add_math_entrypoint_object(sqrtf) add_math_entrypoint_object(sqrtl) add_math_entrypoint_object(sqrtf16) add_math_entrypoint_object(sqrtf128) +add_math_entrypoint_object(sqrtbf16) add_math_entrypoint_object(tan) add_math_entrypoint_object(tanf) @@ -566,12 +585,14 @@ add_math_entrypoint_object(totalorderf) add_math_entrypoint_object(totalorderl) add_math_entrypoint_object(totalorderf16) add_math_entrypoint_object(totalorderf128) +add_math_entrypoint_object(totalorderbf16) add_math_entrypoint_object(totalordermag) add_math_entrypoint_object(totalordermagf) add_math_entrypoint_object(totalordermagl) add_math_entrypoint_object(totalordermagf16) add_math_entrypoint_object(totalordermagf128) +add_math_entrypoint_object(totalordermagbf16) add_math_entrypoint_object(trunc) add_math_entrypoint_object(truncf) diff --git a/libc/src/math/atanpif16.h b/libc/src/math/atanpif16.h new file mode 100644 index 000000000000..8f2391a6e47e --- /dev/null +++ b/libc/src/math/atanpif16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for atanpif16 ---------------------*- 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_MATH_ATANPIF16_H +#define LLVM_LIBC_SRC_MATH_ATANPIF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +float16 atanpif16(float16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_ASINF16_H diff --git a/libc/src/math/canonicalizebf16.h b/libc/src/math/canonicalizebf16.h new file mode 100644 index 000000000000..858fa3296986 --- /dev/null +++ b/libc/src/math/canonicalizebf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for canonicalizebf16 --------------*- 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_MATH_CANONICALIZEBF16_H +#define LLVM_LIBC_SRC_MATH_CANONICALIZEBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +int canonicalizebf16(bfloat16 *cx, const bfloat16 *x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_CANONICALIZEBF16_H diff --git a/libc/src/math/copysignbf16.h b/libc/src/math/copysignbf16.h new file mode 100644 index 000000000000..6369616d6f56 --- /dev/null +++ b/libc/src/math/copysignbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for copysignbf16 ------------------*- 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_MATH_COPYSIGNBF16_H +#define LLVM_LIBC_SRC_MATH_COPYSIGNBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 copysignbf16(bfloat16 x, bfloat16 y); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_COPYSIGNBF16_H diff --git a/libc/src/math/fdimbf16.h b/libc/src/math/fdimbf16.h new file mode 100644 index 000000000000..75bec34b70db --- /dev/null +++ b/libc/src/math/fdimbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fdimbf16 ----------------------*- 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_MATH_FDIMBF16_H +#define LLVM_LIBC_SRC_MATH_FDIMBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 fdimbf16(bfloat16 x, bfloat16 y); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_FDIMBF16_H diff --git a/libc/src/math/fmodbf16.h b/libc/src/math/fmodbf16.h new file mode 100644 index 000000000000..176dbcc83eda --- /dev/null +++ b/libc/src/math/fmodbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fmodbf16 ----------------------*- 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_MATH_FMODBF16_H +#define LLVM_LIBC_SRC_MATH_FMODBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 fmodbf16(bfloat16 x, bfloat16 y); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_FMODBF16_H diff --git a/libc/src/math/frexpbf16.h b/libc/src/math/frexpbf16.h new file mode 100644 index 000000000000..1e9bba16ea6c --- /dev/null +++ b/libc/src/math/frexpbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for frexpbf16 ---------------------*- 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_MATH_FREXPFB16_H +#define LLVM_LIBC_SRC_MATH_FREXPFB16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 frexpbf16(bfloat16 x, int *exp); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_FREXPFB16_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 1a61ccb107bc..263c5dfd0832 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -53,6 +53,20 @@ add_entrypoint_object( ) add_entrypoint_object( + canonicalizebf16 + SRCS + canonicalizebf16.cpp + HDRS + ../canonicalizebf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.bfloat16 +) + +add_entrypoint_object( iscanonical SRCS iscanonical.cpp @@ -97,6 +111,20 @@ add_entrypoint_object( ) add_entrypoint_object( + iscanonicalbf16 + SRCS + iscanonicalbf16.cpp + HDRS + ../iscanonicalbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.bfloat16 +) + +add_entrypoint_object( ceil SRCS ceil.cpp @@ -1749,6 +1777,22 @@ add_entrypoint_object( ) add_entrypoint_object( + copysignbf16 + SRCS + copysignbf16.cpp + HDRS + ../copysignbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.manipulation_functions + FLAGS + MISC_MATH_BASIC_OPS_OPT +) + +add_entrypoint_object( frexp SRCS frexp.cpp @@ -1799,6 +1843,20 @@ add_entrypoint_object( ) add_entrypoint_object( + frexpbf16 + SRCS + frexpbf16.cpp + HDRS + ../frexpbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.macros.config + libc.src.__support.macros.properties.types +) + +add_entrypoint_object( ilogb SRCS ilogb.cpp @@ -1851,6 +1909,20 @@ add_entrypoint_object( ) add_entrypoint_object( + ilogbbf16 + SRCS + ilogbbf16.cpp + HDRS + ../ilogbbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.macros.config + libc.src.__support.macros.properties.types +) + +add_entrypoint_object( llogb SRCS llogb.cpp @@ -1903,6 +1975,20 @@ add_entrypoint_object( ) add_entrypoint_object( + llogbbf16 + SRCS + llogbbf16.cpp + HDRS + ../llogbbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.macros.config + libc.src.__support.macros.properties.types +) + +add_entrypoint_object( ldexp SRCS ldexp.cpp @@ -1952,6 +2038,20 @@ add_entrypoint_object( libc.src.__support.math.ldexpf128 ) +add_entrypoint_object( + ldexpbf16 + SRCS + ldexpbf16.cpp + HDRS + ../ldexpbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.macros.config + libc.src.__support.macros.properties.types +) + add_object_library( common_constants HDRS @@ -2225,6 +2325,20 @@ add_entrypoint_object( ) add_entrypoint_object( + logbbf16 + SRCS + logbbf16.cpp + HDRS + ../logbbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.macros.config + libc.src.__support.macros.properties.types +) + +add_entrypoint_object( modf SRCS modf.cpp @@ -2277,6 +2391,20 @@ add_entrypoint_object( ) add_entrypoint_object( + modfbf16 + SRCS + modfbf16.cpp + HDRS + ../modfbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.macros.config + libc.src.__support.macros.properties.types +) + +add_entrypoint_object( fmin SRCS fmin.cpp @@ -3127,7 +3255,21 @@ add_entrypoint_object( libc.src.__support.macros.optimization libc.src.__support.macros.properties.types libc.src.__support.FPUtil.sqrt - ) +) + +add_entrypoint_object( + sqrtbf16 + SRCS + sqrtbf16.cpp + HDRS + ../sqrtbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.sqrt + libc.src.__support.macros.config + libc.src.__support.macros.properties.types +) add_entrypoint_object( remquof @@ -3181,6 +3323,20 @@ add_entrypoint_object( ) add_entrypoint_object( + remquobf16 + SRCS + remquobf16.cpp + HDRS + ../remquobf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.macros.properties.types + libc.src.__support.macros.config +) + +add_entrypoint_object( remainderf SRCS remainderf.cpp @@ -3233,6 +3389,20 @@ add_entrypoint_object( ) add_entrypoint_object( + remainderbf16 + SRCS + remainderbf16.cpp + HDRS + ../remainderbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.macros.properties.types + libc.src.__support.macros.config +) + +add_entrypoint_object( hypotf SRCS hypotf.cpp @@ -3316,6 +3486,20 @@ add_entrypoint_object( ) add_entrypoint_object( + fdimbf16 + SRCS + fdimbf16.cpp + HDRS + ../fdimbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.bfloat16 +) + +add_entrypoint_object( fdiv SRCS fdiv.cpp @@ -3432,6 +3616,20 @@ add_entrypoint_object( ) add_entrypoint_object( + issignalingbf16 + SRCS + issignalingbf16.cpp + HDRS + ../issignalingbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.bfloat16 +) + +add_entrypoint_object( isnan SRCS isnan.cpp @@ -3832,6 +4030,20 @@ add_entrypoint_object( ) add_entrypoint_object( + fmodbf16 + SRCS + fmodbf16.cpp + HDRS + ../fmodbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.generic.fmod +) + +add_entrypoint_object( fromfp SRCS fromfp.cpp @@ -4262,6 +4474,25 @@ add_entrypoint_object( ) add_entrypoint_object( + atanpif16 + SRCS + atanpif16.cpp + HDRS + ../atanpif16.h + DEPENDS + libc.hdr.errno_macros + libc.hdr.fenv_macros + libc.src.__support.FPUtil.cast + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval + libc.src.__support.FPUtil.sqrt + libc.src.__support.macros.optimization + libc.src.__support.macros.properties.types +) + +add_entrypoint_object( asinf SRCS asinf.cpp @@ -4463,6 +4694,21 @@ add_entrypoint_object( ) add_entrypoint_object( + scalblnbf16 + SRCS + scalblnbf16.cpp + HDRS + ../scalblnbf16.h + DEPENDS + libc.hdr.float_macros + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.manipulation_functions +) + +add_entrypoint_object( scalbn SRCS scalbn.cpp @@ -4520,6 +4766,21 @@ add_entrypoint_object( ) add_entrypoint_object( + scalbnbf16 + SRCS + scalbnbf16.cpp + HDRS + ../scalblnbf16.h + DEPENDS + libc.hdr.float_macros + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.manipulation_functions +) + +add_entrypoint_object( fmaf SRCS fmaf.cpp @@ -4600,6 +4861,21 @@ add_entrypoint_object( libc.src.__support.FPUtil.basic_operations libc.src.__support.macros.properties.types ) + +add_entrypoint_object( + totalorderbf16 + SRCS + totalorderbf16.cpp + HDRS + ../totalorderbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.bfloat16 +) + add_entrypoint_object( totalordermag SRCS @@ -4652,6 +4928,20 @@ add_entrypoint_object( ) add_entrypoint_object( + totalordermagbf16 + SRCS + totalordermagbf16.cpp + HDRS + ../totalordermagbf16.h + DEPENDS + libc.src.__support.common + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.bfloat16 +) + +add_entrypoint_object( getpayload SRCS getpayload.cpp diff --git a/libc/src/math/generic/atanpif16.cpp b/libc/src/math/generic/atanpif16.cpp new file mode 100644 index 000000000000..c54087c7165f --- /dev/null +++ b/libc/src/math/generic/atanpif16.cpp @@ -0,0 +1,157 @@ +//===-- Half-precision atanpi function ------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/atanpif16.h" +#include "hdr/errno_macros.h" +#include "hdr/fenv_macros.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/cast.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/FPUtil/sqrt.h" +#include "src/__support/macros/optimization.h" + +namespace LIBC_NAMESPACE_DECL { + +// Using Python's SymPy library, we can obtain the polynomial approximation of +// arctan(x)/pi. The steps are as follows: +// >>> from sympy import * +// >>> import math +// >>> x = symbols('x') +// >>> print(series(atan(x)/math.pi, x, 0, 17)) +// +// Output: +// 0.318309886183791*x - 0.106103295394597*x**3 + 0.0636619772367581*x**5 - +// 0.0454728408833987*x**7 + 0.0353677651315323*x**9 - 0.0289372623803446*x**11 +// + 0.0244853758602916*x**13 - 0.0212206590789194*x**15 + O(x**17) +// +// We will assign this degree-15 Taylor polynomial as g(x). This polynomial +// approximation is accurate for arctan(x)/pi when |x| is in the range [0, 0.5]. +// +// +// To compute arctan(x) for all real x, we divide the domain into the following +// cases: +// +// * Case 1: |x| <= 0.5 +// In this range, the direct polynomial approximation is used: +// arctan(x)/pi = sign(x) * g(|x|) +// or equivalently, arctan(x) = sign(x) * pi * g(|x|). +// +// * Case 2: 0.5 < |x| <= 1 +// We use the double-angle identity for the tangent function, specifically: +// arctan(x) = 2 * arctan(x / (1 + sqrt(1 + x^2))). +// Applying this, we have: +// arctan(x)/pi = sign(x) * 2 * arctan(x')/pi, +// where x' = |x| / (1 + sqrt(1 + x^2)). +// Thus, arctan(x)/pi = sign(x) * 2 * g(x') +// +// When |x| is in (0.5, 1], the value of x' will always fall within the +// interval [0.207, 0.414], which is within the accurate range of g(x). +// +// * Case 3: |x| > 1 +// For values of |x| greater than 1, we use the reciprocal transformation +// identity: +// arctan(x) = pi/2 - arctan(1/x) for x > 0. +// For any x (real number), this generalizes to: +// arctan(x)/pi = sign(x) * (1/2 - arctan(1/|x|)/pi). +// Then, using g(x) for arctan(1/|x|)/pi: +// arctan(x)/pi = sign(x) * (1/2 - g(1/|x|)). +// +// Note that if 1/|x| still falls outside the +// g(x)'s primary range of accuracy (i.e., if 0.5 < 1/|x| <= 1), the rule +// from Case 2 must be applied recursively to 1/|x|. + +LLVM_LIBC_FUNCTION(float16, atanpif16, (float16 x)) { + using FPBits = fputil::FPBits<float16>; + + FPBits xbits(x); + bool is_neg = xbits.is_neg(); + + auto signed_result = [is_neg](double r) -> float16 { + return fputil::cast<float16>(is_neg ? -r : r); + }; + + if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) { + if (xbits.is_nan()) { + if (xbits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + return x; + } + // atanpi(±∞) = ±0.5 + return signed_result(0.5); + } + + if (LIBC_UNLIKELY(xbits.is_zero())) + return x; + + double x_abs = fputil::cast<double>(xbits.abs().get_val()); + + if (LIBC_UNLIKELY(x_abs == 1.0)) + return signed_result(0.25); + + // evaluate atan(x)/pi using polynomial approximation, valid for |x| <= 0.5 + constexpr auto atanpi_eval = [](double x) -> double { + // polynomial coefficients for atan(x)/pi taylor series + // generated using sympy: series(atan(x)/pi, x, 0, 17) + constexpr static double POLY_COEFFS[] = { + 0x1.45f306dc9c889p-2, // x^1: 1/pi + -0x1.b2995e7b7b60bp-4, // x^3: -1/(3*pi) + 0x1.04c26be3b06ccp-4, // x^5: 1/(5*pi) + -0x1.7483758e69c08p-5, // x^7: -1/(7*pi) + 0x1.21bb945252403p-5, // x^9: 1/(9*pi) + -0x1.da1bace3cc68ep-6, // x^11: -1/(11*pi) + 0x1.912b1c2336cf2p-6, // x^13: 1/(13*pi) + -0x1.5bade52f95e7p-6, // x^15: -1/(15*pi) + }; + double x_sq = x * x; + return x * fputil::polyeval(x_sq, POLY_COEFFS[0], POLY_COEFFS[1], + POLY_COEFFS[2], POLY_COEFFS[3], POLY_COEFFS[4], + POLY_COEFFS[5], POLY_COEFFS[6], POLY_COEFFS[7]); + }; + + // Case 1: |x| <= 0.5 - Direct polynomial evaluation + if (LIBC_LIKELY(x_abs <= 0.5)) { + double result = atanpi_eval(x_abs); + return signed_result(result); + } + + // case 2: 0.5 < |x| <= 1 - use double-angle reduction + // atan(x) = 2 * atan(x / (1 + sqrt(1 + x^2))) + // so atanpi(x) = 2 * atanpi(x') where x' = x / (1 + sqrt(1 + x^2)) + if (x_abs <= 1.0) { + double x_abs_sq = x_abs * x_abs; + double sqrt_term = fputil::sqrt<double>(1.0 + x_abs_sq); + double x_prime = x_abs / (1.0 + sqrt_term); + double result = 2.0 * atanpi_eval(x_prime); + return signed_result(result); + } + + // case 3: |x| > 1 - use reciprocal transformation + // atan(x) = pi/2 - atan(1/x) for x > 0 + // so atanpi(x) = 1/2 - atanpi(1/x) + double x_recip = 1.0 / x_abs; + double result; + + // if 1/|x| > 0.5, we need to apply Case 2 transformation to 1/|x| + if (x_recip > 0.5) { + double x_recip_sq = x_recip * x_recip; + double sqrt_term = fputil::sqrt<double>(1.0 + x_recip_sq); + double x_prime = x_recip / (1.0 + sqrt_term); + result = fputil::multiply_add(-2.0, atanpi_eval(x_prime), 0.5); + } else { + // direct evaluation since 1/|x| <= 0.5 + result = 0.5 - atanpi_eval(x_recip); + } + + return signed_result(result); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/canonicalizebf16.cpp b/libc/src/math/generic/canonicalizebf16.cpp new file mode 100644 index 000000000000..9cc379060c3d --- /dev/null +++ b/libc/src/math/generic/canonicalizebf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of canonicalizebf16 function -----------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/canonicalizebf16.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, canonicalizebf16, (bfloat16 * cx, const bfloat16 *x)) { + return fputil::canonicalize(*cx, *x); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/copysignbf16.cpp b/libc/src/math/generic/copysignbf16.cpp new file mode 100644 index 000000000000..48ade2b26981 --- /dev/null +++ b/libc/src/math/generic/copysignbf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of copysignbf16 function ---------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/copysignbf16.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, copysignbf16, (bfloat16 x, bfloat16 y)) { + return fputil::copysign(x, y); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/fdimbf16.cpp b/libc/src/math/generic/fdimbf16.cpp new file mode 100644 index 000000000000..0f54055b763e --- /dev/null +++ b/libc/src/math/generic/fdimbf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of fdimbf16 function -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/fdimbf16.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, fdimbf16, (bfloat16 x, bfloat16 y)) { + return fputil::fdim(x, y); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/fmodbf16.cpp b/libc/src/math/generic/fmodbf16.cpp new file mode 100644 index 000000000000..902a680fe860 --- /dev/null +++ b/libc/src/math/generic/fmodbf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of fmodbf16 function -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/fmodbf16.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/FPUtil/generic/FMod.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, fmodbf16, (bfloat16 x, bfloat16 y)) { + return fputil::generic::FMod<bfloat16>::eval(x, y); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/frexpbf16.cpp b/libc/src/math/generic/frexpbf16.cpp new file mode 100644 index 000000000000..004f64f282f7 --- /dev/null +++ b/libc/src/math/generic/frexpbf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of frexpbf16 function ------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/frexpbf16.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, frexpbf16, (bfloat16 x, int *exp)) { + return fputil::frexp(x, *exp); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/hypotf16.cpp b/libc/src/math/generic/hypotf16.cpp index d782c2687cdb..fa90069f9ff0 100644 --- a/libc/src/math/generic/hypotf16.cpp +++ b/libc/src/math/generic/hypotf16.cpp @@ -48,16 +48,15 @@ LLVM_LIBC_FUNCTION(float16, hypotf16, (float16 x, float16 y)) { return a_bits.get_val(); } - // TODO: Investigate why replacing the return line below with: - // return x_bits.get_val() + y_bits.get_val(); - // fails the hypotf16 smoke tests. + float af = fputil::cast<float>(a_bits.get_val()); + float bf = fputil::cast<float>(b_bits.get_val()); + + // Compiler runtime basic operations for float16 might not be correctly + // rounded for all rounding modes. if (LIBC_UNLIKELY(a_u - b_u >= static_cast<uint16_t>((FPBits::FRACTION_LEN + 2) << FPBits::FRACTION_LEN))) - return a_bits.get_val() + b_bits.get_val(); - - float af = fputil::cast<float>(a_bits.get_val()); - float bf = fputil::cast<float>(b_bits.get_val()); + return fputil::cast<float16>(af + bf); // These squares are exact. float a_sq = af * af; diff --git a/libc/src/math/generic/ilogbbf16.cpp b/libc/src/math/generic/ilogbbf16.cpp new file mode 100644 index 000000000000..6811139c6dcf --- /dev/null +++ b/libc/src/math/generic/ilogbbf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of ilogbbf16 function ------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/ilogbbf16.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, ilogbbf16, (bfloat16 x)) { + return fputil::intlogb<int>(x); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/iscanonicalbf16.cpp b/libc/src/math/generic/iscanonicalbf16.cpp new file mode 100644 index 000000000000..34c11bfcb83d --- /dev/null +++ b/libc/src/math/generic/iscanonicalbf16.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of iscanonicalbf16 function ------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/iscanonicalbf16.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, iscanonicalbf16, (bfloat16 x)) { + bfloat16 tmp; + return fputil::canonicalize(tmp, x) == 0; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/issignalingbf16.cpp b/libc/src/math/generic/issignalingbf16.cpp new file mode 100644 index 000000000000..3bb17efaa0ff --- /dev/null +++ b/libc/src/math/generic/issignalingbf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of issignalingbf16 function ------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/issignalingbf16.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, issignalingbf16, (bfloat16 x)) { + return fputil::issignaling_impl(x); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/ldexpbf16.cpp b/libc/src/math/generic/ldexpbf16.cpp new file mode 100644 index 000000000000..42a5039e81bc --- /dev/null +++ b/libc/src/math/generic/ldexpbf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of ldexpbf16 function ------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/ldexpbf16.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, ldexpbf16, (bfloat16 x, int exp)) { + return fputil::ldexp(x, exp); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/llogbbf16.cpp b/libc/src/math/generic/llogbbf16.cpp new file mode 100644 index 000000000000..74c27620053d --- /dev/null +++ b/libc/src/math/generic/llogbbf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of llogbbf16 function ------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/llogbbf16.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(long, llogbbf16, (bfloat16 x)) { + return fputil::intlogb<long>(x); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/logbbf16.cpp b/libc/src/math/generic/logbbf16.cpp new file mode 100644 index 000000000000..5a43ddfafde7 --- /dev/null +++ b/libc/src/math/generic/logbbf16.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of logbbf16 function -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/logbbf16.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, logbbf16, (bfloat16 x)) { return fputil::logb(x); } + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/modfbf16.cpp b/libc/src/math/generic/modfbf16.cpp new file mode 100644 index 000000000000..09458f6a2db4 --- /dev/null +++ b/libc/src/math/generic/modfbf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of modfbf16 function -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/modfbf16.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, modfbf16, (bfloat16 x, bfloat16 *iptr)) { + return fputil::modf(x, *iptr); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/remainderbf16.cpp b/libc/src/math/generic/remainderbf16.cpp new file mode 100644 index 000000000000..e70726a6cbc5 --- /dev/null +++ b/libc/src/math/generic/remainderbf16.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of remainderbf16 function --------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/remainderbf16.h" +#include "src/__support/FPUtil/DivisionAndRemainderOperations.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, remainderbf16, (bfloat16 x, bfloat16 y)) { + int quotient; + return fputil::remquo(x, y, quotient); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/remquobf16.cpp b/libc/src/math/generic/remquobf16.cpp new file mode 100644 index 000000000000..e1b13f8deb19 --- /dev/null +++ b/libc/src/math/generic/remquobf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of remquobf16 function -----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/remquobf16.h" +#include "src/__support/FPUtil/DivisionAndRemainderOperations.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, remquobf16, (bfloat16 x, bfloat16 y, int *exp)) { + return fputil::remquo(x, y, *exp); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/scalblnbf16.cpp b/libc/src/math/generic/scalblnbf16.cpp new file mode 100644 index 000000000000..f85f702660ed --- /dev/null +++ b/libc/src/math/generic/scalblnbf16.cpp @@ -0,0 +1,26 @@ +//===-- Implementation of scalblnbf16 function ----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/scalblnbf16.h" +#include "hdr/float_macros.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +#if FLT_RADIX != 2 +#error "FLT_RADIX != 2 is not supported." +#endif + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, scalblnbf16, (bfloat16 x, long n)) { + return fputil::ldexp(x, n); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/scalbnbf16.cpp b/libc/src/math/generic/scalbnbf16.cpp new file mode 100644 index 000000000000..108f9e7d4d05 --- /dev/null +++ b/libc/src/math/generic/scalbnbf16.cpp @@ -0,0 +1,26 @@ +//===-- Implementation of scalbnbf16 function -----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/scalbnbf16.h" +#include "hdr/float_macros.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +#if FLT_RADIX != 2 +#error "FLT_RADIX != 2 is not supported." +#endif + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, scalbnbf16, (bfloat16 x, int n)) { + return fputil::ldexp(x, n); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/sqrtbf16.cpp b/libc/src/math/generic/sqrtbf16.cpp new file mode 100644 index 000000000000..061e5522a4d8 --- /dev/null +++ b/libc/src/math/generic/sqrtbf16.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of sqrtbf16 function -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/sqrtbf16.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/FPUtil/sqrt.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(bfloat16, sqrtbf16, (bfloat16 x)) { + return fputil::sqrt<bfloat16>(x); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/totalorderbf16.cpp b/libc/src/math/generic/totalorderbf16.cpp new file mode 100644 index 000000000000..bb9c86e281f6 --- /dev/null +++ b/libc/src/math/generic/totalorderbf16.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of totalorderbf16 function -------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/totalorderbf16.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, totalorderbf16, + (const bfloat16 *x, const bfloat16 *y)) { + return static_cast<int>(fputil::totalorder(*x, *y)); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/totalordermagbf16.cpp b/libc/src/math/generic/totalordermagbf16.cpp new file mode 100644 index 000000000000..3fc61d9d8bcb --- /dev/null +++ b/libc/src/math/generic/totalordermagbf16.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of totalordermagbf16 function ----------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/totalordermagbf16.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, totalordermagbf16, + (const bfloat16 *x, const bfloat16 *y)) { + return static_cast<int>(fputil::totalordermag(*x, *y)); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/ilogbbf16.h b/libc/src/math/ilogbbf16.h new file mode 100644 index 000000000000..da2384b6d62f --- /dev/null +++ b/libc/src/math/ilogbbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for ilogbbf16 ---------------------*- 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_MATH_ILOGBBF16_H +#define LLVM_LIBC_SRC_MATH_ILOGBBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +int ilogbbf16(bfloat16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_ILOGBBF16_H diff --git a/libc/src/math/iscanonicalbf16.h b/libc/src/math/iscanonicalbf16.h new file mode 100644 index 000000000000..f4f975ed9b24 --- /dev/null +++ b/libc/src/math/iscanonicalbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for iscanonicalbf16 ---------------*- 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_MATH_ISCANONICALBF16_H +#define LLVM_LIBC_SRC_MATH_ISCANONICALBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +int iscanonicalbf16(bfloat16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_ISCANONICALBF16_H diff --git a/libc/src/math/issignalingbf16.h b/libc/src/math/issignalingbf16.h new file mode 100644 index 000000000000..afbe70fddf1c --- /dev/null +++ b/libc/src/math/issignalingbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for issignalingbf16 ---------------*- 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_MATH_ISSIGNALINGBF16_H +#define LLVM_LIBC_SRC_MATH_ISSIGNALINGBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +int issignalingbf16(bfloat16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_ISSIGNALINGBF16_H diff --git a/libc/src/math/ldexpbf16.h b/libc/src/math/ldexpbf16.h new file mode 100644 index 000000000000..7436d8dc5c14 --- /dev/null +++ b/libc/src/math/ldexpbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for ldexpbf16 ---------------------*- 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_MATH_LDEXPBF16_H +#define LLVM_LIBC_SRC_MATH_LDEXPBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 ldexpbf16(bfloat16 x, int exp); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_LDEXPBF16_H diff --git a/libc/src/math/llogbbf16.h b/libc/src/math/llogbbf16.h new file mode 100644 index 000000000000..13f0570585d8 --- /dev/null +++ b/libc/src/math/llogbbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for llogbbf16 ---------------------*- 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_MATH_LLOGBBF16_H +#define LLVM_LIBC_SRC_MATH_LLOGBBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +long llogbbf16(bfloat16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_LLOGBBF16_H diff --git a/libc/src/math/logbbf16.h b/libc/src/math/logbbf16.h new file mode 100644 index 000000000000..2c0d77e9df8a --- /dev/null +++ b/libc/src/math/logbbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for logbbf16 ----------------------*- 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_MATH_LOGBBF16_H +#define LLVM_LIBC_SRC_MATH_LOGBBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 logbbf16(bfloat16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_LOGBBF16_H diff --git a/libc/src/math/modfbf16.h b/libc/src/math/modfbf16.h new file mode 100644 index 000000000000..df05b6c5b0aa --- /dev/null +++ b/libc/src/math/modfbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for modfbf16 ----------------------*- 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_MATH_MODFBF16_H +#define LLVM_LIBC_SRC_MATH_MODFBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 modfbf16(bfloat16 x, bfloat16 *iptr); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_MODFBF16_H diff --git a/libc/src/math/remainderbf16.h b/libc/src/math/remainderbf16.h new file mode 100644 index 000000000000..a1a2eaa3a0ef --- /dev/null +++ b/libc/src/math/remainderbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for remainderbf16 -----------------*- 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_MATH_REMAINDERBF16_H +#define LLVM_LIBC_SRC_MATH_REMAINDERBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 remainderbf16(bfloat16 x, bfloat16 y); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_REMAINDERBF16_H diff --git a/libc/src/math/remquobf16.h b/libc/src/math/remquobf16.h new file mode 100644 index 000000000000..909db17dec58 --- /dev/null +++ b/libc/src/math/remquobf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for remquobf16 --------------------*- 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_MATH_REMQUOBF16_H +#define LLVM_LIBC_SRC_MATH_REMQUOBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 remquobf16(bfloat16 x, bfloat16 y, int *exp); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_REMQUOBF16_H diff --git a/libc/src/math/scalblnbf16.h b/libc/src/math/scalblnbf16.h new file mode 100644 index 000000000000..10aad05fc6b1 --- /dev/null +++ b/libc/src/math/scalblnbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for scalblnbf16 -------------------*- 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_MATH_SCALBLNBF16_H +#define LLVM_LIBC_SRC_MATH_SCALBLNBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 scalblnbf16(bfloat16 x, long n); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_SCALBLNBF16_H diff --git a/libc/src/math/scalbnbf16.h b/libc/src/math/scalbnbf16.h new file mode 100644 index 000000000000..67efa338fe63 --- /dev/null +++ b/libc/src/math/scalbnbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for scalbnbf16 --------------------*- 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_MATH_SCALBNBF16_H +#define LLVM_LIBC_SRC_MATH_SCALBNBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 scalbnbf16(bfloat16 x, int n); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_SCALBNBF16_H diff --git a/libc/src/math/sqrtbf16.h b/libc/src/math/sqrtbf16.h new file mode 100644 index 000000000000..4300e9cab6ad --- /dev/null +++ b/libc/src/math/sqrtbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for sqrtbf16 ----------------------*- 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_MATH_SQRTBF16_H +#define LLVM_LIBC_SRC_MATH_SQRTBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 sqrtbf16(bfloat16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_SQRTBF16_H diff --git a/libc/src/math/totalorderbf16.h b/libc/src/math/totalorderbf16.h new file mode 100644 index 000000000000..2414852db92b --- /dev/null +++ b/libc/src/math/totalorderbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for totalorderbf16 ----------------*- 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_MATH_TOTALORDERF16_H +#define LLVM_LIBC_SRC_MATH_TOTALORDERF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +int totalorderbf16(const bfloat16 *x, const bfloat16 *y); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_TOTALORDERF16_H diff --git a/libc/src/math/totalordermagbf16.h b/libc/src/math/totalordermagbf16.h new file mode 100644 index 000000000000..c48de1ca8e54 --- /dev/null +++ b/libc/src/math/totalordermagbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for totalordermagbf16 -------------*- 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_MATH_TOTALORDERMAGF16_H +#define LLVM_LIBC_SRC_MATH_TOTALORDERMAGF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +int totalordermagbf16(const bfloat16 *x, const bfloat16 *y); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_TOTALORDERMAGF16_H diff --git a/libc/src/setjmp/wasm/sigsetjmp.cpp b/libc/src/setjmp/wasm/sigsetjmp.cpp new file mode 100644 index 000000000000..e9dfb3f837e7 --- /dev/null +++ b/libc/src/setjmp/wasm/sigsetjmp.cpp @@ -0,0 +1,18 @@ +//===-- Implementation of sigsetjmp ---------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/setjmp/sigsetjmp.h" +#include "hdr/offsetof_macros.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE_DECL { +[[gnu::returns_twice]] int sigsetjmp(jmp_buf sigjmp_buf, + [[maybe_unused]] int savesigs) { + return setjmp(sigjmp_buf); +} +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdlib/exit.cpp b/libc/src/stdlib/exit.cpp index 28a6f8a63c0c..f26d48ac00d7 100644 --- a/libc/src/stdlib/exit.cpp +++ b/libc/src/stdlib/exit.cpp @@ -15,7 +15,21 @@ namespace LIBC_NAMESPACE_DECL { extern "C" void __cxa_finalize(void *); +// exit needs to clean up TLS and call associated destructors. +// TODO: Strictly speaking, it is not valid to call exit in overlay mode +// as we have no way to ensure system libc will call the TLS destructors. +// We should run exit related tests in hermetic mode but this is currently +// blocked by https://github.com/llvm/llvm-project/issues/133925. +extern "C" [[gnu::weak]] void __cxa_thread_finalize(); + +// TODO: use recursive mutex to protect this routine. [[noreturn]] LLVM_LIBC_FUNCTION(void, exit, (int status)) { +// FIXME: The NVPTX target does not support external weak symbols correctly +// despite being an ELF platform. Disable pending a future split. +#if !defined(LIBC_TARGET_ARCH_IS_NVPTX) + if (__cxa_thread_finalize) + __cxa_thread_finalize(); +#endif __cxa_finalize(nullptr); internal::exit(status); } diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt index 809decfbe5f0..5c9f622d4439 100644 --- a/libc/src/string/CMakeLists.txt +++ b/libc/src/string/CMakeLists.txt @@ -20,6 +20,7 @@ add_header_library( libc.hdr.stdint_proxy libc.src.__support.CPP.bitset libc.src.__support.CPP.type_traits + libc.src.__support.CPP.simd libc.src.__support.common ${string_config_options} ) diff --git a/libc/src/string/memory_utils/generic/inline_strlen.h b/libc/src/string/memory_utils/generic/inline_strlen.h new file mode 100644 index 000000000000..68fba2afb3a5 --- /dev/null +++ b/libc/src/string/memory_utils/generic/inline_strlen.h @@ -0,0 +1,54 @@ +//===-- Strlen for generic SIMD types -------------------------------------===// +// +// 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_STRING_MEMORY_UTILS_GENERIC_INLINE_STRLEN_H +#define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_INLINE_STRLEN_H + +#include "src/__support/CPP/bit.h" +#include "src/__support/CPP/simd.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +// Exploit the underlying integer representation to do a variable shift. +LIBC_INLINE constexpr cpp::simd_mask<char> shift_mask(cpp::simd_mask<char> m, + size_t shift) { + using bitmask_ty = cpp::internal::get_as_integer_type_t<cpp::simd_mask<char>>; + bitmask_ty r = cpp::bit_cast<bitmask_ty>(m) >> shift; + return cpp::bit_cast<cpp::simd_mask<char>>(r); +} + +[[clang::no_sanitize("address")]] LIBC_INLINE size_t +string_length(const char *src) { + constexpr cpp::simd<char> null_byte = cpp::splat('\0'); + + size_t alignment = alignof(cpp::simd<char>); + const cpp::simd<char> *aligned = reinterpret_cast<const cpp::simd<char> *>( + __builtin_align_down(src, alignment)); + + cpp::simd<char> chars = cpp::load_aligned<cpp::simd<char>>(aligned); + cpp::simd_mask<char> mask = cpp::simd_cast<bool>(chars == null_byte); + size_t offset = src - reinterpret_cast<const char *>(aligned); + if (cpp::any_of(shift_mask(mask, offset))) + return cpp::find_first_set(shift_mask(mask, offset)); + + for (;;) { + cpp::simd<char> chars = cpp::load_aligned<cpp::simd<char>>(++aligned); + cpp::simd_mask<char> mask = cpp::simd_cast<bool>(chars == null_byte); + if (cpp::any_of(mask)) + return (reinterpret_cast<const char *>(aligned) - src) + + cpp::find_first_set(mask); + } +} +} // namespace internal + +namespace string_length_impl = internal; +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_INLINE_STRLEN_H diff --git a/libc/src/string/string_utils.h b/libc/src/string/string_utils.h index ce461581b9d9..10803488b6cf 100644 --- a/libc/src/string/string_utils.h +++ b/libc/src/string/string_utils.h @@ -23,14 +23,16 @@ #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY #if defined(LIBC_COPT_STRING_UNSAFE_WIDE_READ) -#if defined(LIBC_TARGET_ARCH_IS_X86) +#if LIBC_HAS_VECTOR_TYPE +#include "src/string/memory_utils/generic/inline_strlen.h" +#elif defined(LIBC_TARGET_ARCH_IS_X86) #include "src/string/memory_utils/x86_64/inline_strlen.h" #elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && defined(__ARM_NEON) #include "src/string/memory_utils/aarch64/inline_strlen.h" #else namespace string_length_impl = LIBC_NAMESPACE::wide_read; #endif -#endif +#endif // defined(LIBC_COPT_STRING_UNSAFE_WIDE_READ) namespace LIBC_NAMESPACE_DECL { namespace internal { @@ -210,28 +212,28 @@ LIBC_INLINE char *string_token(char *__restrict src, static_assert(CHAR_BIT == 8, "bitset of 256 assumes char is 8 bits"); cpp::bitset<256> delims; for (; *delimiter_string != '\0'; ++delimiter_string) - delims.set(static_cast<size_t>(*delimiter_string)); + delims.set(*reinterpret_cast<const unsigned char *>(delimiter_string)); - char *tok_start = src; + unsigned char *tok_start = reinterpret_cast<unsigned char *>(src); if constexpr (SkipDelim) - while (*tok_start != '\0' && delims.test(static_cast<size_t>(*tok_start))) + while (*tok_start != '\0' && delims.test(*tok_start)) ++tok_start; if (*tok_start == '\0' && SkipDelim) { *context = nullptr; return nullptr; } - char *tok_end = tok_start; - while (*tok_end != '\0' && !delims.test(static_cast<size_t>(*tok_end))) + unsigned char *tok_end = tok_start; + while (*tok_end != '\0' && !delims.test(*tok_end)) ++tok_end; if (*tok_end == '\0') { *context = nullptr; } else { *tok_end = '\0'; - *context = tok_end + 1; + *context = reinterpret_cast<char *>(tok_end + 1); } - return tok_start; + return reinterpret_cast<char *>(tok_start); } LIBC_INLINE size_t strlcpy(char *__restrict dst, const char *__restrict src, diff --git a/libc/src/sys/time/linux/utimes.cpp b/libc/src/sys/time/linux/utimes.cpp index 9c00ce9909f2..e740190bc819 100644 --- a/libc/src/sys/time/linux/utimes.cpp +++ b/libc/src/sys/time/linux/utimes.cpp @@ -21,24 +21,21 @@ namespace LIBC_NAMESPACE_DECL { -#ifdef SYS_utimes -constexpr auto UTIMES_SYSCALL_ID = SYS_utimes; -#elif defined(SYS_utimensat) -constexpr auto UTIMES_SYSCALL_ID = SYS_utimensat; -#elif defined(SYS_utimensat_time64) -constexpr auto UTIMES_SYSCALL_ID = SYS_utimensat_time64; -#else -#error "utimes, utimensat, utimensat_time64, syscalls not available." -#endif - LLVM_LIBC_FUNCTION(int, utimes, (const char *path, const struct timeval times[2])) { int ret; #ifdef SYS_utimes // No need to define a timespec struct, use the syscall directly. - ret = LIBC_NAMESPACE::syscall_impl<int>(UTIMES_SYSCALL_ID, path, times); + ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_utimes, path, times); #elif defined(SYS_utimensat) || defined(SYS_utimensat_time64) + +#if defined(SYS_utimensat) + constexpr auto UTIMES_SYSCALL_ID = SYS_utimensat; +#elif defined(SYS_utimensat_time64) + constexpr auto UTIMES_SYSCALL_ID = SYS_utimensat_time64; +#endif + // the utimensat syscall requires a timespec struct, not timeval. struct timespec ts[2]; struct timespec *ts_ptr = nullptr; // default value if times is nullptr @@ -74,6 +71,9 @@ LLVM_LIBC_FUNCTION(int, utimes, // flags=0 means don't follow symlinks (like utimes) ret = LIBC_NAMESPACE::syscall_impl<int>(UTIMES_SYSCALL_ID, AT_FDCWD, path, ts_ptr, 0); + +#else +#error "utimes, utimensat, utimensat_time64, syscalls not available." #endif // SYS_utimensat if (ret < 0) { diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt index 304b3f247a50..ec942e38d1af 100644 --- a/libc/src/time/CMakeLists.txt +++ b/libc/src/time/CMakeLists.txt @@ -86,6 +86,30 @@ add_entrypoint_object( ) add_entrypoint_object( + localtime + SRCS + localtime.cpp + HDRS + localtime.h + DEPENDS + .time_utils + libc.hdr.types.time_t + libc.hdr.types.struct_tm +) + +add_entrypoint_object( + localtime_r + SRCS + localtime_r.cpp + HDRS + localtime_r.h + DEPENDS + .time_utils + libc.hdr.types.time_t + libc.hdr.types.struct_tm +) + +add_entrypoint_object( difftime SRCS difftime.cpp diff --git a/libc/src/time/baremetal/CMakeLists.txt b/libc/src/time/baremetal/CMakeLists.txt index 3072c8b14959..cbe9cf3db3e2 100644 --- a/libc/src/time/baremetal/CMakeLists.txt +++ b/libc/src/time/baremetal/CMakeLists.txt @@ -19,3 +19,29 @@ add_entrypoint_object( libc.hdr.time_macros libc.hdr.types.struct_timespec ) + +add_entrypoint_object( + localtime + SRCS + localtime.cpp + HDRS + ../localtime.h + time_utils.h + DEPENDS + .time_utils + libc.hdr.types.struct_tm + libc.hdr.types.time_t +) + +add_entrypoint_object( + localtime_r + SRCS + localtime_r.cpp + HDRS + ../localtime.h + time_utils.h + DEPENDS + .time_utils + libc.hdr.types.struct_tm + libc.hdr.types.time_t +) diff --git a/libc/src/time/baremetal/localtime.cpp b/libc/src/time/baremetal/localtime.cpp new file mode 100644 index 000000000000..d39c2738e81a --- /dev/null +++ b/libc/src/time/baremetal/localtime.cpp @@ -0,0 +1,22 @@ +//===-- Implementation of localtime for baremetal -------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/time/localtime.h" +#include "hdr/types/struct_tm.h" +#include "hdr/types/time_t.h" +#include "src/time/time_utils.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(struct tm *, localtime, (time_t *timer)) { + static struct tm tm_out; + + return time_utils::localtime_internal(timer, &tm_out); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/baremetal/localtime_r.cpp b/libc/src/time/baremetal/localtime_r.cpp new file mode 100644 index 000000000000..3b57450ca449 --- /dev/null +++ b/libc/src/time/baremetal/localtime_r.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of localtime_r for baremetal -----------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/time/localtime_r.h" +#include "hdr/types/struct_tm.h" +#include "hdr/types/time_t.h" +#include "src/__support/macros/null_check.h" +#include "src/time/time_utils.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(struct tm *, localtime_r, + (const time_t *timer, struct tm *buf)) { + LIBC_CRASH_ON_NULLPTR(timer); + + return time_utils::localtime_internal(timer, buf); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/localtime.cpp b/libc/src/time/localtime.cpp new file mode 100644 index 000000000000..90a296178bae --- /dev/null +++ b/libc/src/time/localtime.cpp @@ -0,0 +1,24 @@ +//===-- Linux implementation of the localtime function --------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/time/localtime.h" +#include "hdr/types/struct_tm.h" +#include "hdr/types/time_t.h" +#include "src/__support/macros/null_check.h" +#include "src/time/time_utils.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(struct tm *, localtime, (const time_t *timer)) { + LIBC_CRASH_ON_NULLPTR(timer); + + static struct tm tm_out; + return time_utils::localtime_internal(timer, &tm_out); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/localtime.h b/libc/src/time/localtime.h new file mode 100644 index 000000000000..663aa70a1321 --- /dev/null +++ b/libc/src/time/localtime.h @@ -0,0 +1,22 @@ +//===-- Implementation header of localtime ----------------------*- 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_TIME_LOCALTIME_H +#define LLVM_LIBC_SRC_TIME_LOCALTIME_H + +#include "hdr/types/struct_tm.h" +#include "hdr/types/time_t.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE_DECL { + +struct tm *localtime(const time_t *timer); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_TIME_LOCALTIME_H diff --git a/libc/src/time/localtime_r.cpp b/libc/src/time/localtime_r.cpp new file mode 100644 index 000000000000..70bbbeed271e --- /dev/null +++ b/libc/src/time/localtime_r.cpp @@ -0,0 +1,25 @@ +//===-- Linux implementation of localtime_r function ----------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/time/localtime_r.h" +#include "hdr/types/struct_tm.h" +#include "hdr/types/time_t.h" +#include "src/__support/macros/null_check.h" +#include "src/time/time_utils.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(struct tm *, localtime_r, + (const time_t *timer, struct tm *buf)) { + LIBC_CRASH_ON_NULLPTR(timer); + LIBC_CRASH_ON_NULLPTR(buf); + + return time_utils::localtime_internal(timer, buf); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/localtime_r.h b/libc/src/time/localtime_r.h new file mode 100644 index 000000000000..6fea40222a4f --- /dev/null +++ b/libc/src/time/localtime_r.h @@ -0,0 +1,22 @@ +//===-- Implementation header of localtime_r --------------------*- 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_TIME_LOCALTIME_R_H +#define LLVM_LIBC_SRC_TIME_LOCALTIME_R_H + +#include "hdr/types/struct_tm.h" +#include "hdr/types/time_t.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE_DECL { + +struct tm *localtime_r(const time_t *timer, struct tm *buf); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_TIME_LOCALTIME_R_H diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h index 84d412c1e846..18dc28760594 100644 --- a/libc/src/time/time_utils.h +++ b/libc/src/time/time_utils.h @@ -93,11 +93,22 @@ LIBC_INLINE tm *gmtime_internal(const time_t *timer, tm *result) { return result; } -// TODO: localtime is not yet implemented and a temporary solution is to -// use gmtime, https://github.com/llvm/llvm-project/issues/107597 +LIBC_INLINE tm *localtime_internal(const time_t *timer, tm *result) { + time_t seconds = *timer; + // Update the tm structure's year, month, day, etc. from seconds. + if (update_from_seconds(seconds, result) < 0) { + out_of_range(); + return nullptr; + } + + // TODO(zimirza): implement timezone database + + return result; +} + LIBC_INLINE tm *localtime(const time_t *t_ptr) { static tm result; - return time_utils::gmtime_internal(t_ptr, &result); + return time_utils::localtime_internal(t_ptr, &result); } // Returns number of years from (1, year). diff --git a/libc/src/unistd/linux/setsid.cpp b/libc/src/unistd/linux/setsid.cpp index df4629bb326c..b1a265c9a01d 100644 --- a/libc/src/unistd/linux/setsid.cpp +++ b/libc/src/unistd/linux/setsid.cpp @@ -11,6 +11,7 @@ #include "hdr/types/pid_t.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" +#include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" #include <sys/syscall.h> // For syscall numbers. @@ -18,7 +19,12 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(pid_t, setsid, ()) { - return LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_setsid); + pid_t ret = LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_setsid); + if (ret < 0) { + libc_errno = static_cast<int>(-ret); + return -1; + } + return ret; } } // namespace LIBC_NAMESPACE_DECL |
