summaryrefslogtreecommitdiff
path: root/libc/src
diff options
context:
space:
mode:
authorMingming Liu <mingmingl@google.com>2025-09-10 15:25:31 -0700
committerGitHub <noreply@github.com>2025-09-10 15:25:31 -0700
commit1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch)
tree57f4b1f313c8cf74eed8819870f39c36ea263c68 /libc/src
parent898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff)
parentb8cefcb601ddaa18482555c4ff363c01a270c2fe (diff)
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'libc/src')
-rw-r--r--libc/src/__support/CMakeLists.txt1
-rw-r--r--libc/src/__support/CPP/CMakeLists.txt15
-rw-r--r--libc/src/__support/CPP/algorithm.h6
-rw-r--r--libc/src/__support/CPP/bit.h22
-rw-r--r--libc/src/__support/CPP/simd.h282
-rw-r--r--libc/src/__support/CPP/tuple.h144
-rw-r--r--libc/src/__support/CPP/type_traits/is_complex.h7
-rw-r--r--libc/src/__support/CPP/utility/integer_sequence.h10
-rw-r--r--libc/src/__support/FPUtil/BasicOperations.h7
-rw-r--r--libc/src/__support/FPUtil/CMakeLists.txt1
-rw-r--r--libc/src/__support/FPUtil/Hypot.h15
-rw-r--r--libc/src/__support/FPUtil/bfloat16.h6
-rw-r--r--libc/src/__support/StringUtil/error_to_string.cpp19
-rw-r--r--libc/src/__support/StringUtil/platform_errors.h2
-rw-r--r--libc/src/__support/StringUtil/signal_to_string.cpp19
-rw-r--r--libc/src/__support/common.h5
-rw-r--r--libc/src/__support/macros/CMakeLists.txt3
-rw-r--r--libc/src/__support/macros/attributes.h8
-rw-r--r--libc/src/__support/macros/config.h20
-rw-r--r--libc/src/__support/macros/optimization.h3
-rw-r--r--libc/src/__support/macros/properties/architectures.h4
-rw-r--r--libc/src/__support/macros/properties/compiler.h6
-rw-r--r--libc/src/__support/macros/properties/cpu_features.h4
-rw-r--r--libc/src/__support/threads/thread.cpp2
-rw-r--r--libc/src/__support/threads/thread.h2
-rw-r--r--libc/src/dlfcn/CMakeLists.txt1
-rw-r--r--libc/src/dlfcn/dladdr.cpp3
-rw-r--r--libc/src/dlfcn/dladdr.h2
-rw-r--r--libc/src/math/CMakeLists.txt23
-rw-r--r--libc/src/math/atanpif16.h21
-rw-r--r--libc/src/math/canonicalizebf16.h21
-rw-r--r--libc/src/math/copysignbf16.h21
-rw-r--r--libc/src/math/fdimbf16.h21
-rw-r--r--libc/src/math/fmodbf16.h21
-rw-r--r--libc/src/math/frexpbf16.h21
-rw-r--r--libc/src/math/generic/CMakeLists.txt292
-rw-r--r--libc/src/math/generic/atanpif16.cpp157
-rw-r--r--libc/src/math/generic/canonicalizebf16.cpp21
-rw-r--r--libc/src/math/generic/copysignbf16.cpp21
-rw-r--r--libc/src/math/generic/fdimbf16.cpp21
-rw-r--r--libc/src/math/generic/fmodbf16.cpp21
-rw-r--r--libc/src/math/generic/frexpbf16.cpp21
-rw-r--r--libc/src/math/generic/hypotf16.cpp13
-rw-r--r--libc/src/math/generic/ilogbbf16.cpp21
-rw-r--r--libc/src/math/generic/iscanonicalbf16.cpp22
-rw-r--r--libc/src/math/generic/issignalingbf16.cpp21
-rw-r--r--libc/src/math/generic/ldexpbf16.cpp21
-rw-r--r--libc/src/math/generic/llogbbf16.cpp21
-rw-r--r--libc/src/math/generic/logbbf16.cpp19
-rw-r--r--libc/src/math/generic/modfbf16.cpp21
-rw-r--r--libc/src/math/generic/remainderbf16.cpp22
-rw-r--r--libc/src/math/generic/remquobf16.cpp21
-rw-r--r--libc/src/math/generic/scalblnbf16.cpp26
-rw-r--r--libc/src/math/generic/scalbnbf16.cpp26
-rw-r--r--libc/src/math/generic/sqrtbf16.cpp21
-rw-r--r--libc/src/math/generic/totalorderbf16.cpp22
-rw-r--r--libc/src/math/generic/totalordermagbf16.cpp22
-rw-r--r--libc/src/math/ilogbbf16.h21
-rw-r--r--libc/src/math/iscanonicalbf16.h21
-rw-r--r--libc/src/math/issignalingbf16.h21
-rw-r--r--libc/src/math/ldexpbf16.h21
-rw-r--r--libc/src/math/llogbbf16.h21
-rw-r--r--libc/src/math/logbbf16.h21
-rw-r--r--libc/src/math/modfbf16.h21
-rw-r--r--libc/src/math/remainderbf16.h21
-rw-r--r--libc/src/math/remquobf16.h21
-rw-r--r--libc/src/math/scalblnbf16.h21
-rw-r--r--libc/src/math/scalbnbf16.h21
-rw-r--r--libc/src/math/sqrtbf16.h21
-rw-r--r--libc/src/math/totalorderbf16.h21
-rw-r--r--libc/src/math/totalordermagbf16.h21
-rw-r--r--libc/src/setjmp/wasm/sigsetjmp.cpp18
-rw-r--r--libc/src/stdlib/exit.cpp14
-rw-r--r--libc/src/string/CMakeLists.txt1
-rw-r--r--libc/src/string/memory_utils/generic/inline_strlen.h54
-rw-r--r--libc/src/string/string_utils.h20
-rw-r--r--libc/src/sys/time/linux/utimes.cpp22
-rw-r--r--libc/src/time/CMakeLists.txt24
-rw-r--r--libc/src/time/baremetal/CMakeLists.txt26
-rw-r--r--libc/src/time/baremetal/localtime.cpp22
-rw-r--r--libc/src/time/baremetal/localtime_r.cpp24
-rw-r--r--libc/src/time/localtime.cpp24
-rw-r--r--libc/src/time/localtime.h22
-rw-r--r--libc/src/time/localtime_r.cpp25
-rw-r--r--libc/src/time/localtime_r.h22
-rw-r--r--libc/src/time/time_utils.h17
-rw-r--r--libc/src/unistd/linux/setsid.cpp8
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