summaryrefslogtreecommitdiff
path: root/libc/src/__support
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/__support
parent898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff)
parentb8cefcb601ddaa18482555c4ff363c01a270c2fe (diff)
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'libc/src/__support')
-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
25 files changed, 576 insertions, 37 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(),