aboutsummaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/cmake/modules/LLVMLibCObjectRules.cmake58
-rw-r--r--libc/config/windows/README.md2
-rw-r--r--libc/include/dlfcn.yaml66
-rw-r--r--libc/include/llvm-libc-types/Dl_info.h19
-rw-r--r--libc/src/__support/FPUtil/CMakeLists.txt3
-rw-r--r--libc/src/__support/FPUtil/bfloat16.h25
-rw-r--r--libc/src/__support/FPUtil/cast.h66
-rw-r--r--libc/src/__support/FPUtil/dyadic_float.h2
-rw-r--r--libc/src/__support/FPUtil/generic/CMakeLists.txt2
-rw-r--r--libc/src/__support/FPUtil/generic/add_sub.h27
-rw-r--r--libc/src/__support/FPUtil/generic/div.h6
-rw-r--r--libc/src/__support/FPUtil/rounding_mode.h93
-rw-r--r--libc/src/__support/OSUtil/linux/aarch64/vdso.h2
-rw-r--r--libc/src/__support/OSUtil/linux/vdso_sym.h6
-rw-r--r--libc/src/__support/OSUtil/linux/x86_64/vdso.h2
-rw-r--r--libc/src/__support/macros/attributes.h27
-rw-r--r--libc/src/__support/threads/mutex.h22
-rw-r--r--libc/src/__support/wchar/character_converter.cpp14
-rw-r--r--libc/src/__support/wchar/character_converter.h5
-rw-r--r--libc/src/__support/wchar/mbsnrtowcs.h4
-rw-r--r--libc/src/__support/wchar/string_converter.h38
-rw-r--r--libc/src/__support/wchar/wcsnrtombs.h4
-rw-r--r--libc/src/dlfcn/CMakeLists.txt22
-rw-r--r--libc/src/dlfcn/dladdr.cpp21
-rw-r--r--libc/src/dlfcn/dladdr.h20
-rw-r--r--libc/src/dlfcn/dlinfo.cpp23
-rw-r--r--libc/src/dlfcn/dlinfo.h20
-rw-r--r--libc/src/wctype/iswalpha.cpp2
-rw-r--r--libc/src/wctype/iswalpha.h2
-rw-r--r--libc/test/IntegrationTest/CMakeLists.txt1
-rw-r--r--libc/test/IntegrationTest/test.cpp21
-rw-r--r--libc/test/integration/src/__support/GPU/match.cpp4
-rw-r--r--libc/test/src/__support/OSUtil/linux/vdso_test.cpp30
-rw-r--r--libc/test/src/__support/wchar/string_converter_test.cpp110
-rw-r--r--libc/test/src/math/exhaustive/CMakeLists.txt72
-rw-r--r--libc/test/src/math/exhaustive/bfloat16_add_test.cpp65
-rw-r--r--libc/test/src/math/exhaustive/bfloat16_div_test.cpp65
-rw-r--r--libc/test/src/math/exhaustive/bfloat16_mul_test.cpp65
-rw-r--r--libc/test/src/math/exhaustive/bfloat16_sub_test.cpp65
-rw-r--r--libc/test/src/math/exhaustive/exhaustive_test.h2
-rw-r--r--libc/test/src/math/smoke/CMakeLists.txt63
-rw-r--r--libc/test/src/math/smoke/MulTest.h10
-rw-r--r--libc/test/src/math/smoke/bfloat16_add_test.cpp15
-rw-r--r--libc/test/src/math/smoke/bfloat16_div_test.cpp15
-rw-r--r--libc/test/src/math/smoke/bfloat16_mul_test.cpp15
-rw-r--r--libc/test/src/math/smoke/bfloat16_sub_test.cpp15
-rw-r--r--libc/test/src/stdfix/BitsFxTest.h10
-rw-r--r--libc/test/src/wctype/iswalpha_test.cpp78
-rw-r--r--libc/utils/MPFRWrapper/CMakeLists.txt1
-rw-r--r--libc/utils/MPFRWrapper/MPFRUtils.cpp8
50 files changed, 1065 insertions, 268 deletions
diff --git a/libc/cmake/modules/LLVMLibCObjectRules.cmake b/libc/cmake/modules/LLVMLibCObjectRules.cmake
index 805da91..030157b 100644
--- a/libc/cmake/modules/LLVMLibCObjectRules.cmake
+++ b/libc/cmake/modules/LLVMLibCObjectRules.cmake
@@ -1,4 +1,33 @@
set(OBJECT_LIBRARY_TARGET_TYPE "OBJECT_LIBRARY")
+set(ENTRYPOINT_OBJ_TARGET_TYPE "ENTRYPOINT_OBJ")
+set(ENTRYPOINT_EXT_TARGET_TYPE "ENTRYPOINT_EXT")
+
+# Rule to check if a list of dependencies contains any entrypoint objects. Returns a list in entrypoint_deps.
+function(check_entrypoint_deps entrypoint_deps)
+ set(PUBLIC_DEPS "")
+ set(fq_deps_list "")
+ list(APPEND fq_deps_list ${ARGN})
+
+ #don't warn for deps that are allowed, such as errno
+ set(ALLOWED_DEPS
+ "libc.src.errno.errno"
+ "libc.src.setjmp.longjmp"
+ )
+ list(REMOVE_ITEM fq_deps_list ${ALLOWED_DEPS})
+
+ foreach(dep IN LISTS fq_deps_list)
+ if(NOT TARGET ${dep})
+ continue()
+ endif()
+
+ get_target_property(target_type ${dep} "TARGET_TYPE")
+ if(${target_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE})
+ list(APPEND PUBLIC_DEPS ${dep})
+ endif()
+ endforeach()
+ set(${entrypoint_deps} ${PUBLIC_DEPS} PARENT_SCOPE)
+endfunction()
+
# Rule which is essentially a wrapper over add_library to compile a set of
# sources to object files.
@@ -65,6 +94,18 @@ function(create_object_library fq_target_name)
target_include_directories(${fq_target_name} PRIVATE ${LIBC_SOURCE_DIR})
target_compile_options(${fq_target_name} PRIVATE ${compile_options})
+ #loop through the deps, check if any have the TARGET_TYPE of ENTRYPOINT_OBJ_TARGET_TYPE, and print a warning if they do.
+ if(LIBC_CMAKE_VERBOSE_LOGGING)
+ set(entrypoint_deps "")
+ if(NOT "${fq_deps_list}" STREQUAL "")
+ check_entrypoint_deps(entrypoint_deps ${fq_deps_list})
+ endif()
+ if(NOT "${entrypoint_deps}" STREQUAL "")
+ message(WARNING "Object ${fq_target_name} depends on public entrypoint(s) ${entrypoint_deps}.
+ Depending on public entrypoints is not allowed in internal code.")
+ endif()
+ endif()
+
if(SHOW_INTERMEDIATE_OBJECTS)
message(STATUS "Adding object library ${fq_target_name}")
if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
@@ -110,7 +151,6 @@ function(add_object_library target_name)
${ARGN})
endfunction(add_object_library)
-set(ENTRYPOINT_OBJ_TARGET_TYPE "ENTRYPOINT_OBJ")
# A rule for entrypoint object targets.
# Usage:
@@ -179,7 +219,6 @@ function(create_entrypoint_object fq_target_name)
get_target_property(obj_type ${fq_dep_name} "TARGET_TYPE")
if((NOT obj_type) OR (NOT ${obj_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE}))
-
message(FATAL_ERROR "The aliasee of an entrypoint alias should be an entrypoint.")
endif()
@@ -230,6 +269,19 @@ function(create_entrypoint_object fq_target_name)
_get_common_compile_options(common_compile_options "${ADD_ENTRYPOINT_OBJ_FLAGS}")
list(APPEND common_compile_options ${ADD_ENTRYPOINT_OBJ_COMPILE_OPTIONS})
get_fq_deps_list(fq_deps_list ${ADD_ENTRYPOINT_OBJ_DEPENDS})
+
+ #loop through the deps, check if any have the TARGET_TYPE of entrypoint_target_type, and print a warning if they do.
+ if(LIBC_CMAKE_VERBOSE_LOGGING)
+ set(entrypoint_deps "")
+ if(NOT "${fq_deps_list}" STREQUAL "")
+ check_entrypoint_deps(entrypoint_deps ${fq_deps_list})
+ endif()
+ if(NOT "${entrypoint_deps}" STREQUAL "")
+ message(WARNING "Entrypoint ${fq_target_name} depends on public entrypoint(s) ${entrypoint_deps}.
+ Depending on public entrypoints is not allowed in internal code.")
+ endif()
+ endif()
+
set(full_deps_list ${fq_deps_list} libc.src.__support.common)
if(SHOW_INTERMEDIATE_OBJECTS)
@@ -390,8 +442,6 @@ function(add_entrypoint_object target_name)
)
endfunction(add_entrypoint_object)
-set(ENTRYPOINT_EXT_TARGET_TYPE "ENTRYPOINT_EXT")
-
# A rule for external entrypoint targets.
# Usage:
# add_entrypoint_external(
diff --git a/libc/config/windows/README.md b/libc/config/windows/README.md
index 3ac058e..ee5d5fb 100644
--- a/libc/config/windows/README.md
+++ b/libc/config/windows/README.md
@@ -59,7 +59,7 @@ libc, and finally, build and test the libc.
by Clang, so ensure Clang is specified as the C and C++ compiler.
```
- cmake -G Ninja ../llvm-project/llvm -DCMAKE_C_COMPILER=C:/src/clang-build/bin/clang-cl.exe -DCMAKE_CXX_COMPILER=C:/src/clang-build/bin/clang-cl.exe -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_FORCE_BUILD_RUNTIME=libc -DLLVM_ENABLE_PROJECTS=libc -DLLVM_NATIVE_ARCH=x86_64 -DLLVM_HOST_TRIPLE=x86_64-window-x86-gnu
+ cmake -G Ninja ../llvm-project/runtimes -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=C:/src/clang-build/bin/clang-cl.exe -DCMAKE_CXX_COMPILER=C:/src/clang-build/bin/clang-cl.exe -DLLVM_ENABLE_RUNTIMES=libc
```
Some LLVM libc math unittests test correctness/accuracy against results from
diff --git a/libc/include/dlfcn.yaml b/libc/include/dlfcn.yaml
index 6afeb70..db2893a 100644
--- a/libc/include/dlfcn.yaml
+++ b/libc/include/dlfcn.yaml
@@ -37,6 +37,57 @@ macros:
standards:
- gnu
macro_value: "((void *) 0)"
+enums:
+ - name: RTLD_DI_LMID
+ standards:
+ - gnu
+ value: 1
+ - name: RTLD_DI_LINKMAP
+ standards:
+ - gnu
+ value: 2
+ - name: RTLD_DI_CONFIGADDR,
+ standards:
+ - gnu
+ value: 3
+ - name: RTLD_DI_SERINFO
+ standards:
+ - gnu
+ value: 4
+ - name: RTLD_DI_SERINFOSIZE
+ standards:
+ - gnu
+ value: 5
+ - name: RTLD_DI_ORIGIN
+ standards:
+ - gnu
+ value: 6
+ - name: RTLD_DI_PROFILENAME
+ standards:
+ - gnu
+ value: 7
+ - name: RTLD_DI_PROFILEOUT
+ standards:
+ - gnu
+ value: 8
+ - name: RTLD_DI_TLS_MODID
+ standards:
+ - gnu
+ value: 9
+ - name: RTLD_DI_TLS_DATA
+ standards:
+ - gnu
+ value: 10
+ - name: RTLD_DI_PHDR
+ standards:
+ - gnu
+ value: 11
+ - name: RTLD_DI_MAX
+ standards:
+ - gnu
+ value: 11
+types:
+ - type_name: Dl_info
functions:
- name: dlclose
standards:
@@ -63,3 +114,18 @@ functions:
arguments:
- type: void *__restrict
- type: const char *__restrict
+ - name: dlinfo
+ standards:
+ - gnu
+ return_type: int
+ arguments:
+ - type: void *__restrict
+ - type: int
+ - type: void *__restrict
+ - name: dladdr
+ standards:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: const void *
+ - type: Dl_info *
diff --git a/libc/include/llvm-libc-types/Dl_info.h b/libc/include/llvm-libc-types/Dl_info.h
new file mode 100644
index 0000000..b082e30
--- /dev/null
+++ b/libc/include/llvm-libc-types/Dl_info.h
@@ -0,0 +1,19 @@
+//===-- Definition of Dl_info type ----------------------------------------===//
+//
+// 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_TYPES_DL_INFO_H
+#define LLVM_LIBC_TYPES_DL_INFO_H
+
+typedef struct {
+ const char *dli_fname;
+ void *dli_fbase;
+ const char *dli_sname;
+ void *dli_saddr;
+} Dl_info;
+
+#endif // LLVM_LIBC_TYPES_DL_INFO_H
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 6e447fc..37520ea 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -285,6 +285,9 @@ add_header_library(
libc.hdr.stdint_proxy
libc.src.__support.CPP.bit
libc.src.__support.CPP.type_traits
+ libc.src.__support.FPUtil.generic.add_sub
+ libc.src.__support.FPUtil.generic.div
+ libc.src.__support.FPUtil.generic.mul
libc.src.__support.macros.config
libc.src.__support.macros.properties.types
)
diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index fa45d73..3fab2b8 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -15,6 +15,9 @@
#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/comparison_operations.h"
#include "src/__support/FPUtil/dyadic_float.h"
+#include "src/__support/FPUtil/generic/add_sub.h"
+#include "src/__support/FPUtil/generic/div.h"
+#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"
@@ -81,6 +84,28 @@ struct BFloat16 {
LIBC_INLINE bool operator>=(BFloat16 other) const {
return fputil::greater_than_or_equals(*this, other);
}
+
+ LIBC_INLINE constexpr BFloat16 operator-() const {
+ fputil::FPBits<bfloat16> result(*this);
+ result.set_sign(result.is_pos() ? Sign::NEG : Sign::POS);
+ return result.get_val();
+ }
+
+ LIBC_INLINE BFloat16 operator+(BFloat16 other) const {
+ return fputil::generic::add<BFloat16>(*this, other);
+ }
+
+ LIBC_INLINE BFloat16 operator-(BFloat16 other) const {
+ return fputil::generic::sub<BFloat16>(*this, other);
+ }
+
+ LIBC_INLINE BFloat16 operator*(BFloat16 other) const {
+ return fputil::generic::mul<bfloat16>(*this, other);
+ }
+
+ LIBC_INLINE BFloat16 operator/(BFloat16 other) const {
+ return fputil::generic::div<bfloat16>(*this, other);
+ }
}; // struct BFloat16
} // namespace fputil
diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
index e999ece..54c80e8 100644
--- a/libc/src/__support/FPUtil/cast.h
+++ b/libc/src/__support/FPUtil/cast.h
@@ -27,47 +27,47 @@ LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
OutType>
cast(InType x) {
// Casting to the same type is a no-op.
- if constexpr (cpp::is_same_v<InType, OutType>)
+ if constexpr (cpp::is_same_v<InType, OutType>) {
return x;
-
- // bfloat16 is always defined (for now)
- if constexpr (cpp::is_same_v<OutType, bfloat16> ||
- cpp::is_same_v<InType, bfloat16>
+ } else {
+ if constexpr (cpp::is_same_v<OutType, bfloat16> ||
+ cpp::is_same_v<InType, bfloat16>
#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
- || cpp::is_same_v<OutType, float16> ||
- cpp::is_same_v<InType, float16>
+ || cpp::is_same_v<OutType, float16> ||
+ cpp::is_same_v<InType, float16>
#endif
- ) {
- using InFPBits = FPBits<InType>;
- using InStorageType = typename InFPBits::StorageType;
- using OutFPBits = FPBits<OutType>;
- using OutStorageType = typename OutFPBits::StorageType;
+ ) {
+ using InFPBits = FPBits<InType>;
+ using InStorageType = typename InFPBits::StorageType;
+ using OutFPBits = FPBits<OutType>;
+ using OutStorageType = typename OutFPBits::StorageType;
- InFPBits x_bits(x);
+ InFPBits x_bits(x);
- if (x_bits.is_nan()) {
- if (x_bits.is_signaling_nan()) {
- raise_except_if_required(FE_INVALID);
- return OutFPBits::quiet_nan().get_val();
- }
+ if (x_bits.is_nan()) {
+ if (x_bits.is_signaling_nan()) {
+ raise_except_if_required(FE_INVALID);
+ return OutFPBits::quiet_nan().get_val();
+ }
- InStorageType x_mant = x_bits.get_mantissa();
- if (InFPBits::FRACTION_LEN > OutFPBits::FRACTION_LEN)
- x_mant >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
- return OutFPBits::quiet_nan(x_bits.sign(),
- static_cast<OutStorageType>(x_mant))
- .get_val();
- }
+ InStorageType x_mant = x_bits.get_mantissa();
+ if (InFPBits::FRACTION_LEN > OutFPBits::FRACTION_LEN)
+ x_mant >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
+ return OutFPBits::quiet_nan(x_bits.sign(),
+ static_cast<OutStorageType>(x_mant))
+ .get_val();
+ }
- if (x_bits.is_inf())
- return OutFPBits::inf(x_bits.sign()).get_val();
+ if (x_bits.is_inf())
+ return OutFPBits::inf(x_bits.sign()).get_val();
- constexpr size_t MAX_FRACTION_LEN =
- cpp::max(OutFPBits::FRACTION_LEN, InFPBits::FRACTION_LEN);
- DyadicFloat<cpp::bit_ceil(MAX_FRACTION_LEN)> xd(x);
- return xd.template as<OutType, /*ShouldSignalExceptions=*/true>();
- } else {
- return static_cast<OutType>(x);
+ constexpr size_t MAX_FRACTION_LEN =
+ cpp::max(OutFPBits::FRACTION_LEN, InFPBits::FRACTION_LEN);
+ DyadicFloat<cpp::bit_ceil(MAX_FRACTION_LEN)> xd(x);
+ return xd.template as<OutType, /*ShouldSignalExceptions=*/true>();
+ } else {
+ return static_cast<OutType>(x);
+ }
}
}
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 3464e4a..cc0710f 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -576,7 +576,7 @@ LIBC_INLINE constexpr DyadicFloat<Bits> quick_mul(const DyadicFloat<Bits> &a,
// Check the leading bit directly, should be faster than using clz in
// normalize().
if (result.mantissa.val[DyadicFloat<Bits>::MantissaType::WORD_COUNT - 1] >>
- 63 ==
+ (DyadicFloat<Bits>::MantissaType::WORD_SIZE - 1) ==
0)
result.shift_left(1);
} else {
diff --git a/libc/src/__support/FPUtil/generic/CMakeLists.txt b/libc/src/__support/FPUtil/generic/CMakeLists.txt
index 117213f..b75efc8 100644
--- a/libc/src/__support/FPUtil/generic/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/generic/CMakeLists.txt
@@ -68,6 +68,7 @@ add_header_library(
libc.src.__support.FPUtil.rounding_mode
libc.src.__support.macros.attributes
libc.src.__support.macros.optimization
+ libc.src.__support.macros.properties.types
)
add_header_library(
@@ -77,6 +78,7 @@ add_header_library(
DEPENDS
libc.hdr.errno_macros
libc.hdr.fenv_macros
+ libc.src.__support.CPP.algorithm
libc.src.__support.CPP.bit
libc.src.__support.CPP.type_traits
libc.src.__support.FPUtil.basic_operations
diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index d4a4129..b2e9d81 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -104,13 +104,22 @@ add_or_sub(InType x, InType y) {
}
}
- // volatile prevents Clang from converting tmp to OutType and then
- // immediately back to InType before negating it, resulting in double
- // rounding.
- volatile InType tmp = y;
- if constexpr (IsSub)
- tmp = -tmp;
- return cast<OutType>(tmp);
+ if constexpr (cpp::is_same_v<InType, bfloat16> &&
+ cpp::is_same_v<OutType, bfloat16>) {
+ OutFPBits y_bits(y);
+ if constexpr (IsSub)
+ y_bits.set_sign(y_bits.sign().negate());
+ return y_bits.get_val();
+ } else {
+
+ // volatile prevents Clang from converting tmp to OutType and then
+ // immediately back to InType before negating it, resulting in double
+ // rounding.
+ volatile InType tmp = y;
+ if constexpr (IsSub)
+ tmp = -tmp;
+ return cast<OutType>(tmp);
+ }
}
if (y_bits.is_zero())
@@ -165,8 +174,8 @@ add_or_sub(InType x, InType y) {
int alignment = (max_bits.get_biased_exponent() - max_bits.is_normal()) -
(min_bits.get_biased_exponent() - min_bits.is_normal());
- InStorageType aligned_min_mant =
- min_mant >> cpp::min(alignment, RESULT_MANTISSA_LEN);
+ InStorageType aligned_min_mant = static_cast<InStorageType>(
+ min_mant >> cpp::min(alignment, RESULT_MANTISSA_LEN));
bool aligned_min_mant_sticky;
if (alignment <= GUARD_BITS_LEN)
diff --git a/libc/src/__support/FPUtil/generic/div.h b/libc/src/__support/FPUtil/generic/div.h
index 0891ae0..bf7d0b7 100644
--- a/libc/src/__support/FPUtil/generic/div.h
+++ b/libc/src/__support/FPUtil/generic/div.h
@@ -11,6 +11,7 @@
#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
+#include "src/__support/CPP/algorithm.h"
#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/FPUtil/BasicOperations.h"
@@ -34,8 +35,9 @@ div(InType x, InType y) {
using OutStorageType = typename OutFPBits::StorageType;
using InFPBits = FPBits<InType>;
using InStorageType = typename InFPBits::StorageType;
- using DyadicFloat =
- DyadicFloat<cpp::bit_ceil(static_cast<size_t>(InFPBits::SIG_LEN + 1))>;
+ using DyadicFloat = DyadicFloat<cpp::max(
+ static_cast<size_t>(16),
+ cpp::bit_ceil(static_cast<size_t>(InFPBits::SIG_LEN + 1)))>;
InFPBits x_bits(x);
InFPBits y_bits(y);
diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index 4ee0a0b..fdc8498 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -17,30 +17,24 @@
namespace LIBC_NAMESPACE_DECL {
namespace fputil {
+namespace generic {
+
// Quick free-standing test whether fegetround() == FE_UPWARD.
// Using the following observation:
// 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
// = 0x1.000002f for FE_UPWARD.
-LIBC_INLINE static constexpr bool fenv_is_round_up() {
- if (cpp::is_constant_evaluated()) {
- return false;
- } else {
- volatile float x = 0x1.0p-25f;
- return (1.0f + x != 1.0f);
- }
+LIBC_INLINE bool fenv_is_round_up() {
+ static volatile float x = 0x1.0p-25f;
+ return (1.0f + x != 1.0f);
}
// Quick free-standing test whether fegetround() == FE_DOWNWARD.
// Using the following observation:
// -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
// = -0x1.000002f for FE_DOWNWARD.
-LIBC_INLINE static constexpr bool fenv_is_round_down() {
- if (cpp::is_constant_evaluated()) {
- return false;
- } else {
- volatile float x = 0x1.0p-25f;
- return (-1.0f - x != -1.0f);
- }
+LIBC_INLINE bool fenv_is_round_down() {
+ static volatile float x = 0x1.0p-25f;
+ return (-1.0f - x != -1.0f);
}
// Quick free-standing test whether fegetround() == FE_TONEAREST.
@@ -49,14 +43,10 @@ LIBC_INLINE static constexpr bool fenv_is_round_down() {
// = 0x1.100002p0f for FE_UPWARD,
// 1.5f - 2^-24 = 1.5f for FE_TONEAREST, FE_UPWARD
// = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO
-LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
- if (cpp::is_constant_evaluated()) {
- return true;
- } else {
- volatile float x = 0x1.0p-24f;
- float y = 1.5f + x;
- return (y == 1.5f - x);
- }
+LIBC_INLINE bool fenv_is_round_to_nearest() {
+ static volatile float x = 0x1.0p-24f;
+ float y = 1.5f + x;
+ return (y == 1.5f - x);
}
// Quick free-standing test whether fegetround() == FE_TOWARDZERO.
@@ -69,13 +59,56 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
// (0x1.000002p0f + 2^-24) + (-1.0f - 2^-24) = 2^-23 for FE_TOWARDZERO
// = 2^-22 for FE_TONEAREST, FE_UPWARD
// = 0 for FE_DOWNWARD
+LIBC_INLINE bool fenv_is_round_to_zero() {
+ static volatile float x = 0x1.0p-24f;
+ float y = x;
+ return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f);
+}
+
+// Quick free standing get rounding mode based on the above observations.
+LIBC_INLINE int quick_get_round() {
+ static volatile float x = 0x1.0p-24f;
+ float y = x;
+ float z = (0x1.000002p0f + y) + (-1.0f - y);
+
+ if (z == 0.0f)
+ return FE_DOWNWARD;
+ if (z == 0x1.0p-23f)
+ return FE_TOWARDZERO;
+ return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
+}
+
+} // namespace generic
+
+LIBC_INLINE static constexpr bool fenv_is_round_up() {
+ if (cpp::is_constant_evaluated()) {
+ return false;
+ } else {
+ return generic::fenv_is_round_up();
+ }
+}
+
+LIBC_INLINE static constexpr bool fenv_is_round_down() {
+ if (cpp::is_constant_evaluated()) {
+ return false;
+ } else {
+ return generic::fenv_is_round_down();
+ }
+}
+
+LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
+ if (cpp::is_constant_evaluated()) {
+ return true;
+ } else {
+ return generic::fenv_is_round_to_nearest();
+ }
+}
+
LIBC_INLINE static constexpr bool fenv_is_round_to_zero() {
if (cpp::is_constant_evaluated()) {
return false;
} else {
- volatile float x = 0x1.0p-24f;
- volatile float y = 0x1.000002p0f + x;
- return (y + (-1.0f - x) == 0x1.0p-23f);
+ return generic::fenv_is_round_to_zero();
}
}
@@ -84,15 +117,7 @@ LIBC_INLINE static constexpr int quick_get_round() {
if (cpp::is_constant_evaluated()) {
return FE_TONEAREST;
} else {
- volatile float x = 0x1.0p-24f;
- volatile float y = 0x1.000002p0f + x;
- float z = y + (-1.0f - x);
-
- if (z == 0.0f)
- return FE_DOWNWARD;
- if (z == 0x1.0p-23f)
- return FE_TOWARDZERO;
- return (2.0f + x == 2.0f) ? FE_TONEAREST : FE_UPWARD;
+ return generic::quick_get_round();
}
}
diff --git a/libc/src/__support/OSUtil/linux/aarch64/vdso.h b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
index 3c4c620..ee5777a 100644
--- a/libc/src/__support/OSUtil/linux/aarch64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/aarch64/vdso.h
@@ -23,6 +23,8 @@ LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
return "__kernel_clock_gettime";
case VDSOSym::ClockGetRes:
return "__kernel_clock_getres";
+ case VDSOSym::GetRandom:
+ return "__kernel_getrandom";
default:
return "";
}
diff --git a/libc/src/__support/OSUtil/linux/vdso_sym.h b/libc/src/__support/OSUtil/linux/vdso_sym.h
index 968e153..01f0b72 100644
--- a/libc/src/__support/OSUtil/linux/vdso_sym.h
+++ b/libc/src/__support/OSUtil/linux/vdso_sym.h
@@ -35,7 +35,8 @@ enum class VDSOSym {
RTSigReturn,
FlushICache,
RiscvHwProbe,
- VDSOSymCount
+ GetRandom,
+ VDSOSymCount,
};
template <VDSOSym sym> LIBC_INLINE constexpr auto dispatcher() {
@@ -60,6 +61,9 @@ template <VDSOSym sym> LIBC_INLINE constexpr auto dispatcher() {
else if constexpr (sym == VDSOSym::RiscvHwProbe)
return static_cast<int (*)(riscv_hwprobe *, size_t, size_t, cpu_set_t *,
unsigned)>(nullptr);
+ else if constexpr (sym == VDSOSym::GetRandom)
+ return static_cast<int (*)(void *, size_t, unsigned int, void *, size_t)>(
+ nullptr);
else
return static_cast<void *>(nullptr);
}
diff --git a/libc/src/__support/OSUtil/linux/x86_64/vdso.h b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
index abe7c33..f46fcb0 100644
--- a/libc/src/__support/OSUtil/linux/x86_64/vdso.h
+++ b/libc/src/__support/OSUtil/linux/x86_64/vdso.h
@@ -29,6 +29,8 @@ LIBC_INLINE constexpr cpp::string_view symbol_name(VDSOSym sym) {
return "__vdso_time";
case VDSOSym::ClockGetRes:
return "__vdso_clock_getres";
+ case VDSOSym::GetRandom:
+ return "__vdso_getrandom";
default:
return "";
}
diff --git a/libc/src/__support/macros/attributes.h b/libc/src/__support/macros/attributes.h
index c647467..4ff374b 100644
--- a/libc/src/__support/macros/attributes.h
+++ b/libc/src/__support/macros/attributes.h
@@ -28,7 +28,32 @@
#define LIBC_INLINE_ASM __asm__ __volatile__
#define LIBC_UNUSED __attribute__((unused))
-#ifdef LIBC_TARGET_ARCH_IS_GPU
+// Uses the platform specific specialization
+#define LIBC_THREAD_MODE_PLATFORM 0
+
+// Mutex guards nothing, used in single-threaded implementations
+#define LIBC_THREAD_MODE_SINGLE 1
+
+// Vendor provides implementation
+#define LIBC_THREAD_MODE_EXTERNAL 2
+
+// libcxx doesn't define LIBC_THREAD_MODE, unless that is passed in the command
+// line in the CMake invocation. This defaults to the original implementation
+// (before changes in https://github.com/llvm/llvm-project/pull/145358)
+#ifndef LIBC_THREAD_MODE
+#define LIBC_THREAD_MODE LIBC_THREAD_MODE_PLATFORM
+#endif // LIBC_THREAD_MODE
+
+#if LIBC_THREAD_MODE != LIBC_THREAD_MODE_PLATFORM && \
+ LIBC_THREAD_MODE != LIBC_THREAD_MODE_SINGLE && \
+ LIBC_THREAD_MODE != LIBC_THREAD_MODE_EXTERNAL
+#error LIBC_THREAD_MODE must be one of the following values: \
+LIBC_THREAD_MODE_PLATFORM, \
+LIBC_THREAD_MODE_SINGLE, \
+LIBC_THREAD_MODE_EXTERNAL.
+#endif
+
+#if LIBC_THREAD_MODE == LIBC_THREAD_MODE_SINGLE
#define LIBC_THREAD_LOCAL
#else
#define LIBC_THREAD_LOCAL thread_local
diff --git a/libc/src/__support/threads/mutex.h b/libc/src/__support/threads/mutex.h
index cbef0d0..f64f7e7 100644
--- a/libc/src/__support/threads/mutex.h
+++ b/libc/src/__support/threads/mutex.h
@@ -12,28 +12,6 @@
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
-// Uses the platform specific specialization
-#define LIBC_THREAD_MODE_PLATFORM 0
-
-// Mutex guards nothing, used in single-threaded implementations
-#define LIBC_THREAD_MODE_SINGLE 1
-
-// Vendor provides implementation
-#define LIBC_THREAD_MODE_EXTERNAL 2
-
-#if !defined(LIBC_THREAD_MODE)
-#error LIBC_THREAD_MODE is undefined
-#endif // LIBC_THREAD_MODE
-
-#if LIBC_THREAD_MODE != LIBC_THREAD_MODE_PLATFORM && \
- LIBC_THREAD_MODE != LIBC_THREAD_MODE_SINGLE && \
- LIBC_THREAD_MODE != LIBC_THREAD_MODE_EXTERNAL
-#error LIBC_THREAD_MODE must be one of the following values: \
-LIBC_THREAD_MODE_PLATFORM, \
-LIBC_THREAD_MODE_SINGLE, \
-LIBC_THREAD_MODE_EXTERNAL.
-#endif
-
#if LIBC_THREAD_MODE == LIBC_THREAD_MODE_PLATFORM
// Platform independent code will include this header file which pulls
diff --git a/libc/src/__support/wchar/character_converter.cpp b/libc/src/__support/wchar/character_converter.cpp
index 15d0f47..2667288 100644
--- a/libc/src/__support/wchar/character_converter.cpp
+++ b/libc/src/__support/wchar/character_converter.cpp
@@ -132,12 +132,6 @@ ErrorOr<char32_t> CharacterConverter::pop_utf32() {
return utf32;
}
-size_t CharacterConverter::sizeAsUTF32() {
- return 1; // a single utf-32 value can fit an entire character
-}
-
-size_t CharacterConverter::sizeAsUTF8() { return state->total_bytes; }
-
ErrorOr<char8_t> CharacterConverter::pop_utf8() {
if (isEmpty())
return Error(-1);
@@ -170,5 +164,13 @@ ErrorOr<char8_t> CharacterConverter::pop_utf8() {
return static_cast<char8_t>(output);
}
+template <> ErrorOr<char8_t> CharacterConverter::pop() { return pop_utf8(); }
+template <> ErrorOr<char32_t> CharacterConverter::pop() { return pop_utf32(); }
+
+template <> size_t CharacterConverter::sizeAs<char8_t>() {
+ return state->total_bytes;
+}
+template <> size_t CharacterConverter::sizeAs<char32_t>() { return 1; }
+
} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/wchar/character_converter.h b/libc/src/__support/wchar/character_converter.h
index b6d918f..2cc28ab 100644
--- a/libc/src/__support/wchar/character_converter.h
+++ b/libc/src/__support/wchar/character_converter.h
@@ -12,6 +12,7 @@
#include "hdr/types/char32_t.h"
#include "hdr/types/char8_t.h"
#include "hdr/types/size_t.h"
+#include "src/__support/CPP/type_traits.h"
#include "src/__support/common.h"
#include "src/__support/error_or.h"
#include "src/__support/wchar/mbstate.h"
@@ -31,14 +32,14 @@ public:
bool isEmpty();
bool isValidState();
- size_t sizeAsUTF32();
- size_t sizeAsUTF8();
+ template <typename CharType> size_t sizeAs();
int push(char8_t utf8_byte);
int push(char32_t utf32);
ErrorOr<char8_t> pop_utf8();
ErrorOr<char32_t> pop_utf32();
+ template <typename CharType> ErrorOr<CharType> pop();
};
} // namespace internal
diff --git a/libc/src/__support/wchar/mbsnrtowcs.h b/libc/src/__support/wchar/mbsnrtowcs.h
index 54e3152..6abb836 100644
--- a/libc/src/__support/wchar/mbsnrtowcs.h
+++ b/libc/src/__support/wchar/mbsnrtowcs.h
@@ -36,7 +36,7 @@ LIBC_INLINE static ErrorOr<size_t> mbsnrtowcs(wchar_t *__restrict dst,
StringConverter<char8_t> str_conv(reinterpret_cast<const char8_t *>(*src), ps,
len, nmc);
size_t dst_idx = 0;
- ErrorOr<char32_t> converted = str_conv.popUTF32();
+ ErrorOr<char32_t> converted = str_conv.pop<char32_t>();
while (converted.has_value()) {
if (dst != nullptr)
dst[dst_idx] = converted.value();
@@ -47,7 +47,7 @@ LIBC_INLINE static ErrorOr<size_t> mbsnrtowcs(wchar_t *__restrict dst,
return dst_idx;
}
dst_idx++;
- converted = str_conv.popUTF32();
+ converted = str_conv.pop<char32_t>();
}
if (converted.error() == -1) { // if we hit conversion limit
diff --git a/libc/src/__support/wchar/string_converter.h b/libc/src/__support/wchar/string_converter.h
index 869ebdf..ba628bd 100644
--- a/libc/src/__support/wchar/string_converter.h
+++ b/libc/src/__support/wchar/string_converter.h
@@ -12,6 +12,7 @@
#include "hdr/types/char32_t.h"
#include "hdr/types/char8_t.h"
#include "hdr/types/size_t.h"
+#include "src/__support/CPP/type_traits.h"
#include "src/__support/common.h"
#include "src/__support/error_or.h"
#include "src/__support/wchar/character_converter.h"
@@ -53,9 +54,7 @@ public:
size_t srclen = SIZE_MAX)
: cr(ps), src(s), src_len(srclen), src_idx(0), num_to_write(dstlen) {}
- // TODO: following functions are almost identical
- // look into templating CharacterConverter pop functions
- ErrorOr<char32_t> popUTF32() {
+ template <typename CharType> ErrorOr<CharType> pop() {
if (num_to_write == 0)
return Error(-1);
@@ -64,7 +63,7 @@ public:
if (!src_elements_read.has_value())
return Error(src_elements_read.error());
- if (cr.sizeAsUTF32() > num_to_write) {
+ if (cr.sizeAs<CharType>() > num_to_write) {
cr.clear();
return Error(-1);
}
@@ -72,34 +71,9 @@ public:
src_idx += src_elements_read.value();
}
- auto out = cr.pop_utf32();
- if (out.has_value() && out.value() == L'\0')
- src_len = src_idx;
-
- num_to_write--;
-
- return out;
- }
-
- ErrorOr<char8_t> popUTF8() {
- if (num_to_write == 0)
- return Error(-1);
-
- if (cr.isEmpty() || src_idx == 0) {
- auto src_elements_read = pushFullCharacter();
- if (!src_elements_read.has_value())
- return Error(src_elements_read.error());
-
- if (cr.sizeAsUTF8() > num_to_write) {
- cr.clear();
- return Error(-1);
- }
-
- src_idx += src_elements_read.value();
- }
-
- auto out = cr.pop_utf8();
- if (out.has_value() && out.value() == '\0')
+ ErrorOr<CharType> out = cr.pop<CharType>();
+ // if out isn't null terminator or an error
+ if (out.has_value() && out.value() == 0)
src_len = src_idx;
num_to_write--;
diff --git a/libc/src/__support/wchar/wcsnrtombs.h b/libc/src/__support/wchar/wcsnrtombs.h
index 433097c..f593a0e 100644
--- a/libc/src/__support/wchar/wcsnrtombs.h
+++ b/libc/src/__support/wchar/wcsnrtombs.h
@@ -39,7 +39,7 @@ wcsnrtombs(char *__restrict dest, const wchar_t **__restrict ptr_to_src,
reinterpret_cast<const char32_t *>(*ptr_to_src), ps, dest_len,
num_src_widechars);
size_t dst_idx = 0;
- ErrorOr<char8_t> converted = str_conv.popUTF8();
+ ErrorOr<char8_t> converted = str_conv.pop<char8_t>();
while (converted.has_value()) {
if (dest != nullptr)
dest[dst_idx] = converted.value();
@@ -51,7 +51,7 @@ wcsnrtombs(char *__restrict dest, const wchar_t **__restrict ptr_to_src,
}
dst_idx++;
- converted = str_conv.popUTF8();
+ converted = str_conv.pop<char8_t>();
}
if (dest != nullptr)
diff --git a/libc/src/dlfcn/CMakeLists.txt b/libc/src/dlfcn/CMakeLists.txt
index e3a51ba..8ef0540 100644
--- a/libc/src/dlfcn/CMakeLists.txt
+++ b/libc/src/dlfcn/CMakeLists.txt
@@ -38,3 +38,25 @@ add_entrypoint_object(
libc.include.dlfcn
libc.src.errno.errno
)
+
+add_entrypoint_object(
+ dlinfo
+ SRCS
+ dlinfo.cpp
+ HDRS
+ dlinfo.h
+ DEPENDS
+ libc.include.dlfcn
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ dladdr
+ SRCS
+ dladdr.cpp
+ HDRS
+ dladdr.h
+ DEPENDS
+ libc.include.dlfcn
+ libc.src.errno.errno
+)
diff --git a/libc/src/dlfcn/dladdr.cpp b/libc/src/dlfcn/dladdr.cpp
new file mode 100644
index 0000000..61490fd
--- /dev/null
+++ b/libc/src/dlfcn/dladdr.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of dladdr ------------------------------------------===//
+//
+// 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 "dladdr.h"
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// TODO: https:// github.com/llvm/llvm-project/issues/97929
+LLVM_LIBC_FUNCTION(int, dladdr, (const void *addr, Dl_info *info)) {
+ return -1;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/dlfcn/dladdr.h b/libc/src/dlfcn/dladdr.h
new file mode 100644
index 0000000..346fc8d
--- /dev/null
+++ b/libc/src/dlfcn/dladdr.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of dladdr -------------------------*- 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_DLFCN_DLADDR_H
+#define LLVM_LIBC_SRC_DLFCN_DLADDR_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int dladdr(const void *, Dl_info *);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_DLFCN_DLADDR_H
diff --git a/libc/src/dlfcn/dlinfo.cpp b/libc/src/dlfcn/dlinfo.cpp
new file mode 100644
index 0000000..d78cade
--- /dev/null
+++ b/libc/src/dlfcn/dlinfo.cpp
@@ -0,0 +1,23 @@
+
+//===-- Implementation of dlinfo ------------------------------------------===//
+//
+// 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 "dlinfo.h"
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// TODO: https://github.com/llvm/llvm-project/issues/149911
+LLVM_LIBC_FUNCTION(int, dlinfo,
+ (void *restrict handle, int request, void *restrict info)) {
+ return -1;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/dlfcn/dlinfo.h b/libc/src/dlfcn/dlinfo.h
new file mode 100644
index 0000000..c2c34f0
--- /dev/null
+++ b/libc/src/dlfcn/dlinfo.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of dlinfo -------------------------*- 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_DLFCN_DLINFO_H
+#define LLVM_LIBC_SRC_DLFCN_DLINFO_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int dlinfo(void *restrict, int, void *restrict);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_DLFCN_DLINFO_H
diff --git a/libc/src/wctype/iswalpha.cpp b/libc/src/wctype/iswalpha.cpp
index e18f293..09f55d3 100644
--- a/libc/src/wctype/iswalpha.cpp
+++ b/libc/src/wctype/iswalpha.cpp
@@ -14,6 +14,6 @@
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(bool, iswalpha, (wint_t c)) { return internal::iswalpha(c); }
+LLVM_LIBC_FUNCTION(int, iswalpha, (wint_t c)) { return internal::iswalpha(c); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wctype/iswalpha.h b/libc/src/wctype/iswalpha.h
index 681fc6b..0353388 100644
--- a/libc/src/wctype/iswalpha.h
+++ b/libc/src/wctype/iswalpha.h
@@ -14,7 +14,7 @@
namespace LIBC_NAMESPACE_DECL {
-bool iswalpha(wint_t c);
+int iswalpha(wint_t c);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/IntegrationTest/CMakeLists.txt b/libc/test/IntegrationTest/CMakeLists.txt
index 3afe354..235e9fe 100644
--- a/libc/test/IntegrationTest/CMakeLists.txt
+++ b/libc/test/IntegrationTest/CMakeLists.txt
@@ -13,5 +13,6 @@ add_object_library(
DEPENDS
libc.hdr.stdint_proxy
libc.src.__support.OSUtil.osutil
+ libc.src.__support.CPP.atomic
${arch_specific_deps}
)
diff --git a/libc/test/IntegrationTest/test.cpp b/libc/test/IntegrationTest/test.cpp
index 8baf746..19eb255 100644
--- a/libc/test/IntegrationTest/test.cpp
+++ b/libc/test/IntegrationTest/test.cpp
@@ -5,8 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-
#include "hdr/stdint_proxy.h"
+#include "src/__support/CPP/atomic.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include <stddef.h>
@@ -63,16 +63,21 @@ int atexit(void (*func)(void)) { return LIBC_NAMESPACE::atexit(func); }
// which just hands out continuous blocks from a statically allocated chunk of
// memory.
-static constexpr uint64_t MEMORY_SIZE = 16384;
-static uint8_t memory[MEMORY_SIZE];
-static uint8_t *ptr = memory;
+static constexpr uint64_t ALIGNMENT = alignof(double);
+static constexpr uint64_t MEMORY_SIZE = 256 * 1024 /* 256 KiB */;
+alignas(ALIGNMENT) static uint8_t memory[MEMORY_SIZE];
+static size_t ptr = 0;
extern "C" {
-void *malloc(size_t s) {
- void *mem = ptr;
- ptr += s;
- return static_cast<uint64_t>(ptr - memory) >= MEMORY_SIZE ? nullptr : mem;
+void *malloc(size_t size) {
+ LIBC_NAMESPACE::cpp::AtomicRef<size_t> ref(ptr);
+ size = (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
+ size_t old_ptr =
+ ref.fetch_add(size, LIBC_NAMESPACE::cpp::MemoryOrder::RELAXED);
+ if (static_cast<size_t>(old_ptr + size) >= MEMORY_SIZE)
+ return nullptr;
+ return &memory[old_ptr];
}
void free(void *) {}
diff --git a/libc/test/integration/src/__support/GPU/match.cpp b/libc/test/integration/src/__support/GPU/match.cpp
index 2d314c2..70c22b7 100644
--- a/libc/test/integration/src/__support/GPU/match.cpp
+++ b/libc/test/integration/src/__support/GPU/match.cpp
@@ -21,7 +21,9 @@ static void test_match() {
gpu::match_any(mask, gpu::get_lane_id()));
EXPECT_EQ(mask, gpu::match_any(mask, 1));
- uint64_t expected = gpu::get_lane_id() < 16 ? 0xffff : 0xffff0000;
+ uint64_t full_mask =
+ gpu::get_lane_size() > 32 ? 0xffffffffffffffff : 0xffffffff;
+ uint64_t expected = gpu::get_lane_id() < 16 ? 0xffff : full_mask & ~0xffff;
EXPECT_EQ(expected, gpu::match_any(mask, gpu::get_lane_id() < 16));
EXPECT_EQ(mask, gpu::match_all(mask, 1));
EXPECT_EQ(0ull, gpu::match_all(mask, gpu::get_lane_id()));
diff --git a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
index 2f68470..71892a0 100644
--- a/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
+++ b/libc/test/src/__support/OSUtil/linux/vdso_test.cpp
@@ -110,8 +110,8 @@ TEST(LlvmLibcOSUtilVDSOTest, RtSigReturn) {
using namespace testing::ErrnoSetterMatcher;
// must use struct since there is a function of the same name in the same
// scope.
- struct sigaction sa {};
- struct sigaction old_sa {};
+ struct sigaction sa{};
+ struct sigaction old_sa{};
sa.sa_handler = sigprof_handler;
sa.sa_flags = SA_RESTORER;
vdso::TypedSymbol<vdso::VDSOSym::RTSigReturn> symbol;
@@ -158,4 +158,30 @@ TEST(LlvmLibcOSUtilVDSOTest, RiscvHwProbe) {
}
}
+TEST(LlvmLibcOSUtilVDSOTest, GetRandom) {
+ using namespace testing::ErrnoSetterMatcher;
+ vdso::TypedSymbol<vdso::VDSOSym::GetRandom> symbol;
+ if (!symbol)
+ return;
+ // This structure exists in kernel UAPI header; but we define it on our own to
+ // make sure we can test it even on platform without support.
+ struct VGetrandomOpaqueParams {
+ uint32_t size_of_opaque_states;
+ uint32_t mmap_prot;
+ uint32_t mmap_flags;
+ uint32_t reserved[13];
+ };
+ VGetrandomOpaqueParams param{0, 0, 0, {}};
+ // When getrandom vDSO symbol is called with special parameters (~0 for state
+ // size), it populates the desired configuration into VGetrandomOpaqueParams.
+ int res = symbol(
+ /*buf=*/nullptr, /*count=*/0, /*flags=*/0,
+ /*opaque_states=*/&param,
+ /*size_of_opaque_states=*/~0);
+ // Test that the size of the states are correctly populated after a successful
+ // call.
+ EXPECT_EQ(res, 0);
+ EXPECT_GT(param.size_of_opaque_states, 0u);
+}
+
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/__support/wchar/string_converter_test.cpp b/libc/test/src/__support/wchar/string_converter_test.cpp
index d514df9..e45358d 100644
--- a/libc/test/src/__support/wchar/string_converter_test.cpp
+++ b/libc/test/src/__support/wchar/string_converter_test.cpp
@@ -34,32 +34,32 @@ TEST(LlvmLibcStringConverterTest, UTF8To32) {
LIBC_NAMESPACE::internal::StringConverter<char8_t> sc(
reinterpret_cast<const char8_t *>(src), &state, SIZE_MAX);
- auto res = sc.popUTF32();
+ auto res = sc.pop<char32_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x1f921);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 4);
- res = sc.popUTF32();
+ res = sc.pop<char32_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x2211);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 7);
- res = sc.popUTF32();
+ res = sc.pop<char32_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xff);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 9);
- res = sc.popUTF32();
+ res = sc.pop<char32_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x41);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 10);
- res = sc.popUTF32();
+ res = sc.pop<char32_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 11);
- res = sc.popUTF32();
+ res = sc.pop<char32_t>();
ASSERT_FALSE(res.has_value());
ASSERT_EQ(res.error(), -1);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 11);
@@ -75,66 +75,66 @@ TEST(LlvmLibcStringConverterTest, UTF32To8) {
LIBC_NAMESPACE::internal::StringConverter<char32_t> sc(
reinterpret_cast<const char32_t *>(src), &state, SIZE_MAX);
- auto res = sc.popUTF8();
+ auto res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xF0);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x9F);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xA4);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xA1);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
// end of clown emoji, sigma symbol begins
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xE2);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 2);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x88);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 2);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x91);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 2);
// end of sigma symbol, y with diaeresis begins
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xC3);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 3);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xBF);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 3);
// end of y with diaeresis, letter A begins
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x41);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 4);
// null byte
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 5);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_FALSE(res.has_value());
ASSERT_EQ(res.error(), -1);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 5);
@@ -148,28 +148,28 @@ TEST(LlvmLibcStringConverterTest, UTF32To8PartialRead) {
LIBC_NAMESPACE::internal::StringConverter<char32_t> sc(
reinterpret_cast<const char32_t *>(src), &state, SIZE_MAX, 1);
- auto res = sc.popUTF8();
+ auto res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xF0);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x9F);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xA4);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xA1);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
// can only read 1 character from source string, so error on next pop
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_FALSE(res.has_value());
ASSERT_EQ(res.error(), -1);
}
@@ -181,12 +181,12 @@ TEST(LlvmLibcStringConverterTest, UTF8To32PartialRead) {
LIBC_NAMESPACE::internal::StringConverter<char8_t> sc(
reinterpret_cast<const char8_t *>(src), &state, SIZE_MAX, 5);
- auto res = sc.popUTF32();
+ auto res = sc.pop<char32_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x1f921);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 4);
- res = sc.popUTF32();
+ res = sc.pop<char32_t>();
ASSERT_FALSE(res.has_value());
ASSERT_EQ(static_cast<int>(res.error()), -1);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 5);
@@ -200,27 +200,27 @@ TEST(LlvmLibcStringConverterTest, UTF32To8ErrorHandling) {
LIBC_NAMESPACE::internal::StringConverter<char32_t> sc(
reinterpret_cast<const char32_t *>(src), &state, SIZE_MAX);
- auto res = sc.popUTF8();
+ auto res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xF0);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x9F);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xA4);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xA1);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_FALSE(res.has_value());
ASSERT_EQ(static_cast<int>(res.error()), EILSEQ);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
@@ -234,12 +234,12 @@ TEST(LlvmLibcStringConverterTest, UTF8To32ErrorHandling) {
LIBC_NAMESPACE::internal::StringConverter<char8_t> sc(
reinterpret_cast<const char8_t *>(src), &state, SIZE_MAX);
- auto res = sc.popUTF32();
+ auto res = sc.pop<char32_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x1f921);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 4);
- res = sc.popUTF32();
+ res = sc.pop<char32_t>();
ASSERT_FALSE(res.has_value());
ASSERT_EQ(static_cast<int>(res.error()), EILSEQ);
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 4);
@@ -257,12 +257,12 @@ TEST(LlvmLibcStringConverterTest, InvalidCharacterOutsideBounds) {
LIBC_NAMESPACE::internal::StringConverter<char8_t> sc1(
reinterpret_cast<const char8_t *>(src1), &ps1, 1);
- auto res1 = sc1.popUTF32();
+ auto res1 = sc1.pop<char32_t>();
ASSERT_TRUE(res1.has_value());
ASSERT_EQ(static_cast<int>(res1.value()), 0x1f921);
ASSERT_EQ(static_cast<int>(sc1.getSourceIndex()), 4);
- res1 = sc1.popUTF32();
+ res1 = sc1.pop<char32_t>();
ASSERT_FALSE(res1.has_value());
// no space to write error NOT invalid character error (EILSEQ)
ASSERT_EQ(static_cast<int>(res1.error()), -1);
@@ -275,27 +275,27 @@ TEST(LlvmLibcStringConverterTest, InvalidCharacterOutsideBounds) {
LIBC_NAMESPACE::internal::StringConverter<char32_t> sc2(
reinterpret_cast<const char32_t *>(src2), &ps2, 4);
- auto res2 = sc2.popUTF8();
+ auto res2 = sc2.pop<char8_t>();
ASSERT_TRUE(res2.has_value());
ASSERT_EQ(static_cast<int>(res2.value()), 0xF0);
ASSERT_EQ(static_cast<int>(sc2.getSourceIndex()), 1);
- res2 = sc2.popUTF8();
+ res2 = sc2.pop<char8_t>();
ASSERT_TRUE(res2.has_value());
ASSERT_EQ(static_cast<int>(res2.value()), 0x9F);
ASSERT_EQ(static_cast<int>(sc2.getSourceIndex()), 1);
- res2 = sc2.popUTF8();
+ res2 = sc2.pop<char8_t>();
ASSERT_TRUE(res2.has_value());
ASSERT_EQ(static_cast<int>(res2.value()), 0xA4);
ASSERT_EQ(static_cast<int>(sc2.getSourceIndex()), 1);
- res2 = sc2.popUTF8();
+ res2 = sc2.pop<char8_t>();
ASSERT_TRUE(res2.has_value());
ASSERT_EQ(static_cast<int>(res2.value()), 0xA1);
ASSERT_EQ(static_cast<int>(sc2.getSourceIndex()), 1);
- res2 = sc2.popUTF8();
+ res2 = sc2.pop<char8_t>();
ASSERT_FALSE(res2.has_value());
// no space to write error NOT invalid character error (EILSEQ)
ASSERT_EQ(static_cast<int>(res2.error()), -1);
@@ -315,22 +315,22 @@ TEST(LlvmLibcStringConverterTest, MultipleStringConverters32To8) {
LIBC_NAMESPACE::internal::StringConverter<char32_t> sc1(
reinterpret_cast<const char32_t *>(src), &state, SIZE_MAX, 1);
- auto res = sc1.popUTF8();
+ auto res = sc1.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xF0);
ASSERT_EQ(static_cast<int>(sc1.getSourceIndex()), 1);
- res = sc1.popUTF8();
+ res = sc1.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x9F);
ASSERT_EQ(static_cast<int>(sc1.getSourceIndex()), 1);
- res = sc1.popUTF8();
+ res = sc1.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xA4);
ASSERT_EQ(static_cast<int>(sc1.getSourceIndex()), 1);
- res = sc1.popUTF8();
+ res = sc1.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xA1);
ASSERT_EQ(static_cast<int>(sc1.getSourceIndex()), 1);
@@ -340,12 +340,12 @@ TEST(LlvmLibcStringConverterTest, MultipleStringConverters32To8) {
reinterpret_cast<const char32_t *>(src) + sc1.getSourceIndex(), &state,
SIZE_MAX, 1);
- res = sc2.popUTF8();
+ res = sc2.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xC3);
ASSERT_EQ(static_cast<int>(sc2.getSourceIndex()), 1);
- res = sc2.popUTF8();
+ res = sc2.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0xBF);
ASSERT_EQ(static_cast<int>(sc2.getSourceIndex()), 1);
@@ -357,7 +357,7 @@ TEST(LlvmLibcStringConverterTest, MultipleStringConverters8To32) {
LIBC_NAMESPACE::internal::StringConverter<char8_t> sc1(
reinterpret_cast<const char8_t *>(src), &state, SIZE_MAX, 2);
- auto res = sc1.popUTF32();
+ auto res = sc1.pop<char32_t>();
ASSERT_FALSE(res.has_value());
ASSERT_EQ(static_cast<int>(res.error()), -1);
ASSERT_EQ(static_cast<int>(sc1.getSourceIndex()), 2);
@@ -367,12 +367,12 @@ TEST(LlvmLibcStringConverterTest, MultipleStringConverters8To32) {
reinterpret_cast<const char8_t *>(src) + sc1.getSourceIndex(), &state,
SIZE_MAX, 3);
- res = sc2.popUTF32();
+ res = sc2.pop<char32_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0x1f921);
ASSERT_EQ(static_cast<int>(sc2.getSourceIndex()), 2);
- res = sc2.popUTF32();
+ res = sc2.pop<char32_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(res.value()), 0);
ASSERT_EQ(static_cast<int>(sc2.getSourceIndex()), 3);
@@ -384,11 +384,11 @@ TEST(LlvmLibcStringConverterTest, DestLimitUTF8To32) {
LIBC_NAMESPACE::internal::StringConverter<char8_t> sc(
reinterpret_cast<const char8_t *>(src), &state, 1);
- auto res = sc.popUTF32();
+ auto res = sc.pop<char32_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 4);
- res = sc.popUTF32(); // no space to pop this into
+ res = sc.pop<char32_t>(); // no space to pop this into
ASSERT_FALSE(res.has_value());
}
@@ -399,23 +399,23 @@ TEST(LlvmLibcStringConverterTest, DestLimitUTF32To8) {
LIBC_NAMESPACE::internal::StringConverter<char32_t> sc(
reinterpret_cast<const char32_t *>(src), &state, 5);
- auto res = sc.popUTF8();
+ auto res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_TRUE(res.has_value());
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
- res = sc.popUTF8();
+ res = sc.pop<char8_t>();
ASSERT_FALSE(res.has_value());
ASSERT_EQ(static_cast<int>(sc.getSourceIndex()), 1);
}
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 5246337..e40972e 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -567,3 +567,75 @@ add_fp_unittest(
LINK_LIBRARIES
-lpthread
)
+
+add_fp_unittest(
+ bfloat16_add_test
+ NO_RUN_POSTBUILD
+ NEED_MPFR
+ SUITE
+ libc_math_exhaustive_tests
+ SRCS
+ bfloat16_add_test.cpp
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+ DEPENDS
+ .exhaustive_test
+ libc.src.__support.FPUtil.bfloat16
+ libc.src.__support.FPUtil.fp_bits
+ LINK_LIBRARIES
+ -lpthread
+)
+
+add_fp_unittest(
+ bfloat16_div_test
+ NO_RUN_POSTBUILD
+ NEED_MPFR
+ SUITE
+ libc_math_exhaustive_tests
+ SRCS
+ bfloat16_div_test.cpp
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+ DEPENDS
+ .exhaustive_test
+ libc.src.__support.FPUtil.bfloat16
+ libc.src.__support.FPUtil.fp_bits
+ LINK_LIBRARIES
+ -lpthread
+)
+
+add_fp_unittest(
+ bfloat16_mul_test
+ NO_RUN_POSTBUILD
+ NEED_MPFR
+ SUITE
+ libc_math_exhaustive_tests
+ SRCS
+ bfloat16_mul_test.cpp
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+ DEPENDS
+ .exhaustive_test
+ libc.src.__support.FPUtil.bfloat16
+ libc.src.__support.FPUtil.fp_bits
+ LINK_LIBRARIES
+ -lpthread
+)
+
+add_fp_unittest(
+ bfloat16_sub_test
+ NO_RUN_POSTBUILD
+ NEED_MPFR
+ SUITE
+ libc_math_exhaustive_tests
+ SRCS
+ bfloat16_sub_test.cpp
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+ DEPENDS
+ .exhaustive_test
+ libc.src.__support.FPUtil.bfloat16
+ libc.src.__support.FPUtil.fp_bits
+ LINK_LIBRARIES
+ -lpthread
+)
diff --git a/libc/test/src/math/exhaustive/bfloat16_add_test.cpp b/libc/test/src/math/exhaustive/bfloat16_add_test.cpp
new file mode 100644
index 0000000..3f4c779
--- /dev/null
+++ b/libc/test/src/math/exhaustive/bfloat16_add_test.cpp
@@ -0,0 +1,65 @@
+//===-- Exhaustive tests for bfloat16 addition ----------------------------===//
+//
+// 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 "exhaustive_test.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "utils/MPFRWrapper/MPCommon.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+using LIBC_NAMESPACE::fputil::BFloat16;
+
+static BFloat16 add_func(BFloat16 x, BFloat16 y) { return x + y; }
+
+struct Bfloat16AddChecker : public virtual LIBC_NAMESPACE::testing::Test {
+ using FloatType = BFloat16;
+ using FPBits = LIBC_NAMESPACE::fputil::FPBits<bfloat16>;
+ using StorageType = typename FPBits::StorageType;
+
+ uint64_t check(uint16_t x_start, uint16_t x_stop, uint16_t y_start,
+ uint16_t y_stop, mpfr::RoundingMode rounding) {
+ mpfr::ForceRoundingMode r(rounding);
+ if (!r.success)
+ return true;
+ uint16_t xbits = x_start;
+ uint64_t failed = 0;
+ do {
+ BFloat16 x = FPBits(xbits).get_val();
+ uint16_t ybits = xbits;
+ do {
+ BFloat16 y = FPBits(ybits).get_val();
+ mpfr::BinaryInput<BFloat16> input{x, y};
+ bool correct = TEST_MPFR_MATCH_ROUNDING_SILENTLY(
+ mpfr::Operation::Add, input, add_func(x, y), 0.5, rounding);
+ failed += (!correct);
+ } while (ybits++ < y_stop);
+ } while (xbits++ < x_stop);
+ return failed;
+ }
+};
+
+using LlvmLibcBfloat16ExhaustiveAddTest =
+ LlvmLibcExhaustiveMathTest<Bfloat16AddChecker, 1 << 2>;
+
+// range: [0, inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// range: [-0, -inf]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcBfloat16ExhaustiveAddTest, PositiveRange) {
+ test_full_range_all_roundings(POS_START, POS_STOP, POS_START, POS_STOP);
+}
+
+TEST_F(LlvmLibcBfloat16ExhaustiveAddTest, NegativeRange) {
+ test_full_range_all_roundings(NEG_START, NEG_STOP, NEG_START, NEG_STOP);
+}
diff --git a/libc/test/src/math/exhaustive/bfloat16_div_test.cpp b/libc/test/src/math/exhaustive/bfloat16_div_test.cpp
new file mode 100644
index 0000000..2648d5f
--- /dev/null
+++ b/libc/test/src/math/exhaustive/bfloat16_div_test.cpp
@@ -0,0 +1,65 @@
+//===-- Exhaustive tests for bfloat16 division ----------------------------===//
+//
+// 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 "exhaustive_test.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "utils/MPFRWrapper/MPCommon.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+using LIBC_NAMESPACE::fputil::BFloat16;
+
+static BFloat16 div_func(BFloat16 x, BFloat16 y) { return x / y; }
+
+struct Bfloat16DivChecker : public virtual LIBC_NAMESPACE::testing::Test {
+ using FloatType = BFloat16;
+ using FPBits = LIBC_NAMESPACE::fputil::FPBits<bfloat16>;
+ using StorageType = typename FPBits::StorageType;
+
+ uint64_t check(uint16_t x_start, uint16_t x_stop, uint16_t y_start,
+ uint16_t y_stop, mpfr::RoundingMode rounding) {
+ mpfr::ForceRoundingMode r(rounding);
+ if (!r.success)
+ return true;
+ uint16_t xbits = x_start;
+ uint64_t failed = 0;
+ do {
+ BFloat16 x = FPBits(xbits).get_val();
+ uint16_t ybits = xbits;
+ do {
+ BFloat16 y = FPBits(ybits).get_val();
+ mpfr::BinaryInput<BFloat16> input{x, y};
+ bool correct = TEST_MPFR_MATCH_ROUNDING_SILENTLY(
+ mpfr::Operation::Div, input, div_func(x, y), 0.5, rounding);
+ failed += (!correct);
+ } while (ybits++ < y_stop);
+ } while (xbits++ < x_stop);
+ return failed;
+ }
+};
+
+using LlvmLibcBfloat16ExhaustiveDivTest =
+ LlvmLibcExhaustiveMathTest<Bfloat16DivChecker, 1 << 2>;
+
+// range: [0, inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// range: [-0, -inf]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcBfloat16ExhaustiveDivTest, PositiveRange) {
+ test_full_range_all_roundings(POS_START, POS_STOP, POS_START, POS_STOP);
+}
+
+TEST_F(LlvmLibcBfloat16ExhaustiveDivTest, NegativeRange) {
+ test_full_range_all_roundings(NEG_START, NEG_STOP, NEG_START, NEG_STOP);
+}
diff --git a/libc/test/src/math/exhaustive/bfloat16_mul_test.cpp b/libc/test/src/math/exhaustive/bfloat16_mul_test.cpp
new file mode 100644
index 0000000..3cbbcb5
--- /dev/null
+++ b/libc/test/src/math/exhaustive/bfloat16_mul_test.cpp
@@ -0,0 +1,65 @@
+//===-- Exhaustive tests for bfloat16 multiplication ----------------------===//
+//
+// 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 "exhaustive_test.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "utils/MPFRWrapper/MPCommon.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+using LIBC_NAMESPACE::fputil::BFloat16;
+
+static BFloat16 mul_func(BFloat16 x, BFloat16 y) { return x * y; }
+
+struct Bfloat16MulChecker : public virtual LIBC_NAMESPACE::testing::Test {
+ using FloatType = BFloat16;
+ using FPBits = LIBC_NAMESPACE::fputil::FPBits<bfloat16>;
+ using StorageType = typename FPBits::StorageType;
+
+ uint64_t check(uint16_t x_start, uint16_t x_stop, uint16_t y_start,
+ uint16_t y_stop, mpfr::RoundingMode rounding) {
+ mpfr::ForceRoundingMode r(rounding);
+ if (!r.success)
+ return true;
+ uint16_t xbits = x_start;
+ uint64_t failed = 0;
+ do {
+ BFloat16 x = FPBits(xbits).get_val();
+ uint16_t ybits = xbits;
+ do {
+ BFloat16 y = FPBits(ybits).get_val();
+ mpfr::BinaryInput<BFloat16> input{x, y};
+ bool correct = TEST_MPFR_MATCH_ROUNDING_SILENTLY(
+ mpfr::Operation::Mul, input, mul_func(x, y), 0.5, rounding);
+ failed += (!correct);
+ } while (ybits++ < y_stop);
+ } while (xbits++ < x_stop);
+ return failed;
+ }
+};
+
+using LlvmLibcBfloat16ExhaustiveMulTest =
+ LlvmLibcExhaustiveMathTest<Bfloat16MulChecker, 1 << 2>;
+
+// range: [0, inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// range: [-0, -inf]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcBfloat16ExhaustiveMulTest, PositiveRange) {
+ test_full_range_all_roundings(POS_START, POS_STOP, POS_START, POS_STOP);
+}
+
+TEST_F(LlvmLibcBfloat16ExhaustiveMulTest, NegativeRange) {
+ test_full_range_all_roundings(NEG_START, NEG_STOP, NEG_START, NEG_STOP);
+}
diff --git a/libc/test/src/math/exhaustive/bfloat16_sub_test.cpp b/libc/test/src/math/exhaustive/bfloat16_sub_test.cpp
new file mode 100644
index 0000000..11bc6f5
--- /dev/null
+++ b/libc/test/src/math/exhaustive/bfloat16_sub_test.cpp
@@ -0,0 +1,65 @@
+//===-- Exhaustive tests for bfloat16 subtraction -------------------------===//
+//
+// 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 "exhaustive_test.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "utils/MPFRWrapper/MPCommon.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+using LIBC_NAMESPACE::fputil::BFloat16;
+
+static BFloat16 sub_func(BFloat16 x, BFloat16 y) { return x - y; }
+
+struct Bfloat16SubChecker : public virtual LIBC_NAMESPACE::testing::Test {
+ using FloatType = BFloat16;
+ using FPBits = LIBC_NAMESPACE::fputil::FPBits<bfloat16>;
+ using StorageType = typename FPBits::StorageType;
+
+ uint64_t check(uint16_t x_start, uint16_t x_stop, uint16_t y_start,
+ uint16_t y_stop, mpfr::RoundingMode rounding) {
+ mpfr::ForceRoundingMode r(rounding);
+ if (!r.success)
+ return true;
+ uint16_t xbits = x_start;
+ uint64_t failed = 0;
+ do {
+ BFloat16 x = FPBits(xbits).get_val();
+ uint16_t ybits = xbits;
+ do {
+ BFloat16 y = FPBits(ybits).get_val();
+ mpfr::BinaryInput<BFloat16> input{x, y};
+ bool correct = TEST_MPFR_MATCH_ROUNDING_SILENTLY(
+ mpfr::Operation::Sub, input, sub_func(x, y), 0.5, rounding);
+ failed += (!correct);
+ } while (ybits++ < y_stop);
+ } while (xbits++ < x_stop);
+ return failed;
+ }
+};
+
+using LlvmLibcBfloat16ExhaustiveSubTest =
+ LlvmLibcExhaustiveMathTest<Bfloat16SubChecker, 1 << 2>;
+
+// range: [0, inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// range: [-0, -inf]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcBfloat16ExhaustiveSubTest, PositiveRange) {
+ test_full_range_all_roundings(POS_START, POS_STOP, POS_START, POS_STOP);
+}
+
+TEST_F(LlvmLibcBfloat16ExhaustiveSubTest, NegativeRange) {
+ test_full_range_all_roundings(NEG_START, NEG_STOP, NEG_START, NEG_STOP);
+}
diff --git a/libc/test/src/math/exhaustive/exhaustive_test.h b/libc/test/src/math/exhaustive/exhaustive_test.h
index cdf459c..8be65ba 100644
--- a/libc/test/src/math/exhaustive/exhaustive_test.h
+++ b/libc/test/src/math/exhaustive/exhaustive_test.h
@@ -164,7 +164,7 @@ struct LlvmLibcExhaustiveMathTest
range_begin = current_value;
if (stop >= Increment && stop - Increment >= current_value) {
- range_end = current_value + Increment;
+ range_end = static_cast<StorageType>(current_value + Increment);
} else {
range_end = stop;
}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 40b7a342..a722f61 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -5307,6 +5307,69 @@ add_fp_unittest(
)
add_fp_unittest(
+ bfloat16_add_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ bfloat16_add_test.cpp
+ HDRS
+ AddTest.h
+ DEPENDS
+ libc.src.__support.FPUtil.bfloat16
+ libc.src.__support.FPUtil.generic.add_sub
+ libc.src.__support.macros.properties.os
+ libc.src.__support.macros.properties.types
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+)
+
+add_fp_unittest(
+ bfloat16_div_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ bfloat16_div_test.cpp
+ HDRS
+ DivTest.h
+ DEPENDS
+ libc.src.__support.FPUtil.bfloat16
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+)
+
+add_fp_unittest(
+ bfloat16_mul_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ bfloat16_mul_test.cpp
+ HDRS
+ MulTest.h
+ DEPENDS
+ libc.src.__support.FPUtil.basic_operations
+ libc.src.__support.FPUtil.bfloat16
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+)
+
+add_fp_unittest(
+ bfloat16_sub_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ bfloat16_sub_test.cpp
+ HDRS
+ SubTest.h
+ DEPENDS
+ libc.src.__support.FPUtil.bfloat16
+ libc.src.__support.FPUtil.generic.add_sub
+ libc.src.__support.macros.properties.os
+ libc.src.__support.macros.properties.types
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+)
+
+add_fp_unittest(
add_same_type_test
SUITE
libc-math-smoke-tests
diff --git a/libc/test/src/math/smoke/MulTest.h b/libc/test/src/math/smoke/MulTest.h
index cf7f41a..a45f4224 100644
--- a/libc/test/src/math/smoke/MulTest.h
+++ b/libc/test/src/math/smoke/MulTest.h
@@ -53,10 +53,12 @@ public:
EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(in.zero, in.neg_zero));
EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(in.neg_zero, in.zero));
- EXPECT_FP_EQ_ALL_ROUNDING(OutType(1.0), func(1.0, 1.0));
- EXPECT_FP_EQ_ALL_ROUNDING(OutType(15.0), func(3.0, 5.0));
- EXPECT_FP_EQ_ALL_ROUNDING(OutType(0x1.0p-13), func(0x1.0p+1, 0x1.0p-14));
- EXPECT_FP_EQ_ALL_ROUNDING(OutType(0x1.0p-10), func(0x1.0p+2, 0x1.0p-12));
+ EXPECT_FP_EQ_ALL_ROUNDING(InType(1.0), func(InType(1.0), InType(1.0)));
+ EXPECT_FP_EQ_ALL_ROUNDING(InType(15.0), func(InType(3.0), InType(5.0)));
+ EXPECT_FP_EQ_ALL_ROUNDING(OutType(0x1.0p-13),
+ func(InType(0x1.0p+1), InType(0x1.0p-14)));
+ EXPECT_FP_EQ_ALL_ROUNDING(OutType(0x1.0p-10),
+ func(InType(0x1.0p+2), InType(0x1.0p-12)));
}
void test_invalid_operations(MulFunc func) {
diff --git a/libc/test/src/math/smoke/bfloat16_add_test.cpp b/libc/test/src/math/smoke/bfloat16_add_test.cpp
new file mode 100644
index 0000000..1db65a9
--- /dev/null
+++ b/libc/test/src/math/smoke/bfloat16_add_test.cpp
@@ -0,0 +1,15 @@
+//===-- Unittests for bfloat16 addition -----------------------------------===//
+//
+// 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 "AddTest.h"
+
+#include "src/__support/FPUtil/bfloat16.h"
+
+static bfloat16 add_func(bfloat16 x, bfloat16 y) { return x + y; }
+
+LIST_ADD_TESTS(bfloat16, bfloat16, add_func)
diff --git a/libc/test/src/math/smoke/bfloat16_div_test.cpp b/libc/test/src/math/smoke/bfloat16_div_test.cpp
new file mode 100644
index 0000000..c1ab598
--- /dev/null
+++ b/libc/test/src/math/smoke/bfloat16_div_test.cpp
@@ -0,0 +1,15 @@
+//===-- Unittests for bfloat16 division -----------------------------------===//
+//
+// 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 "DivTest.h"
+
+#include "src/__support/FPUtil/bfloat16.h"
+
+static bfloat16 div_func(bfloat16 x, bfloat16 y) { return x / y; }
+
+LIST_DIV_TESTS(bfloat16, bfloat16, div_func)
diff --git a/libc/test/src/math/smoke/bfloat16_mul_test.cpp b/libc/test/src/math/smoke/bfloat16_mul_test.cpp
new file mode 100644
index 0000000..03e38d8
--- /dev/null
+++ b/libc/test/src/math/smoke/bfloat16_mul_test.cpp
@@ -0,0 +1,15 @@
+//===-- Unittests for bfloat16 multiplication -----------------------------===//
+//
+// 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 "MulTest.h"
+
+#include "src/__support/FPUtil/bfloat16.h"
+
+static bfloat16 mul_func(bfloat16 x, bfloat16 y) { return x * y; }
+
+LIST_MUL_TESTS(bfloat16, bfloat16, mul_func)
diff --git a/libc/test/src/math/smoke/bfloat16_sub_test.cpp b/libc/test/src/math/smoke/bfloat16_sub_test.cpp
new file mode 100644
index 0000000..5eb4a9b
--- /dev/null
+++ b/libc/test/src/math/smoke/bfloat16_sub_test.cpp
@@ -0,0 +1,15 @@
+//===-- Unittests for bfloat16 subtraction --------------------------------===//
+//
+// 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 "SubTest.h"
+
+#include "src/__support/FPUtil/bfloat16.h"
+
+static bfloat16 sub_func(bfloat16 x, bfloat16 y) { return x - y; }
+
+LIST_SUB_TESTS(bfloat16, bfloat16, sub_func)
diff --git a/libc/test/src/stdfix/BitsFxTest.h b/libc/test/src/stdfix/BitsFxTest.h
index eca6ab1..cdb363f 100644
--- a/libc/test/src/stdfix/BitsFxTest.h
+++ b/libc/test/src/stdfix/BitsFxTest.h
@@ -54,7 +54,7 @@ public:
if (max >= 11 && FXRep::FRACTION_LEN >= kMinFbits) {
// (10.71875)_10 = (1010.1011100)_2
- constexpr long long kExpected = 1372;
+ constexpr int64_t kExpected = 1372;
EXPECT_EQ(
static_cast<XType>(kExpected << (FXRep::FRACTION_LEN - kMinFbits)),
func(special_num_t));
@@ -63,9 +63,11 @@ public:
if constexpr (FXRep::SIGN_LEN > 0) {
if (min <= -11 && FXRep::FRACTION_LEN >= kMinFbits) {
// (-10.71875)_10 = (-1010.1011100)_2
- constexpr long long kExpected = -1372;
- EXPECT_EQ(static_cast<XType>(kExpected
- << (FXRep::FRACTION_LEN - kMinFbits)),
+ constexpr int64_t kExpected =
+ static_cast<int64_t>(static_cast<uint64_t>(-1372)
+ << (FXRep::FRACTION_LEN - kMinFbits));
+
+ EXPECT_EQ(static_cast<XType>(kExpected),
func(negative_special_num_t));
}
}
diff --git a/libc/test/src/wctype/iswalpha_test.cpp b/libc/test/src/wctype/iswalpha_test.cpp
index f3f75f4..a82c005 100644
--- a/libc/test/src/wctype/iswalpha_test.cpp
+++ b/libc/test/src/wctype/iswalpha_test.cpp
@@ -9,46 +9,48 @@
#include "src/__support/CPP/span.h"
#include "src/wctype/iswalpha.h"
-#include "test/UnitTest/LibcTest.h"
#include "test/UnitTest/Test.h"
-namespace {
-
-// TODO: Merge the wctype tests using this framework.
-constexpr char WALPHA_ARRAY[] = {
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-};
-
-bool in_span(int ch, LIBC_NAMESPACE::cpp::span<const char> arr) {
- for (size_t i = 0; i < arr.size(); ++i)
- if (static_cast<int>(arr[i]) == ch)
- return true;
- return false;
-}
-
-} // namespace
-
TEST(LlvmLibciswalpha, SimpleTest) {
- EXPECT_TRUE(LIBC_NAMESPACE::iswalpha('a'));
- EXPECT_TRUE(LIBC_NAMESPACE::iswalpha('B'));
-
- EXPECT_FALSE(LIBC_NAMESPACE::iswalpha('3'));
- EXPECT_FALSE(LIBC_NAMESPACE::iswalpha(' '));
- EXPECT_FALSE(LIBC_NAMESPACE::iswalpha('?'));
- EXPECT_FALSE(LIBC_NAMESPACE::iswalpha('\0'));
- EXPECT_FALSE(LIBC_NAMESPACE::iswalpha(-1));
+ EXPECT_NE(LIBC_NAMESPACE::iswalpha('a'), 0);
+ EXPECT_NE(LIBC_NAMESPACE::iswalpha('B'), 0);
+
+ EXPECT_EQ(LIBC_NAMESPACE::iswalpha('3'), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswalpha(' '), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswalpha('?'), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswalpha('\0'), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::iswalpha(-1), 0);
}
-TEST(LlvmLibciswalpha, DefaultLocale) {
- // Loops through all characters, verifying that letters return
- // true and everything else returns false.
- for (int ch = -255; ch < 255; ++ch) {
- if (in_span(ch, WALPHA_ARRAY))
- EXPECT_TRUE(LIBC_NAMESPACE::iswalpha(ch));
- else
- EXPECT_FALSE(LIBC_NAMESPACE::iswalpha(ch));
- }
-}
+// TODO: once iswalpha supports more than just ascii-range characters add a
+// proper test.
+
+// namespace {
+
+// // TODO: Merge the wctype tests using this framework.
+// constexpr char WALPHA_ARRAY[] = {
+// 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+// 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+// 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+// 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+// };
+
+// bool in_span(int ch, LIBC_NAMESPACE::cpp::span<const char> arr) {
+// for (size_t i = 0; i < arr.size(); ++i)
+// if (static_cast<int>(arr[i]) == ch)
+// return true;
+// return false;
+// }
+
+// } // namespace
+
+// TEST(LlvmLibciswalpha, DefaultLocale) {
+// // Loops through all characters, verifying that letters return
+// // true and everything else returns false.
+// for (int ch = -255; ch < 255; ++ch) {
+// if (in_span(ch, WALPHA_ARRAY))
+// EXPECT_TRUE(LIBC_NAMESPACE::iswalpha(ch));
+// else
+// EXPECT_FALSE(LIBC_NAMESPACE::iswalpha(ch));
+// }
+// }
diff --git a/libc/utils/MPFRWrapper/CMakeLists.txt b/libc/utils/MPFRWrapper/CMakeLists.txt
index 2669b23..73151c6 100644
--- a/libc/utils/MPFRWrapper/CMakeLists.txt
+++ b/libc/utils/MPFRWrapper/CMakeLists.txt
@@ -43,6 +43,7 @@ if(LIBC_TESTS_CAN_USE_MPFR)
libc.hdr.stdint_proxy
libc.src.__support.CPP.array
libc.src.__support.CPP.stringstream
+ libc.src.__support.FPUtil.bfloat16
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.fpbits_str
LibcTest.unit
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 8853f96..ae12a83 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -11,6 +11,7 @@
#include "src/__support/CPP/array.h"
#include "src/__support/CPP/stringstream.h"
+#include "src/__support/FPUtil/bfloat16.h"
#include "src/__support/FPUtil/fpbits_str.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"
@@ -408,6 +409,8 @@ template void explain_binary_operation_one_output_error(
template void explain_binary_operation_one_output_error(
Operation, const BinaryInput<float128> &, float128, double, RoundingMode);
#endif
+template void explain_binary_operation_one_output_error(
+ Operation, const BinaryInput<bfloat16> &, bfloat16, double, RoundingMode);
template <typename InputType, typename OutputType>
void explain_ternary_operation_one_output_error(
@@ -641,7 +644,10 @@ template bool compare_binary_operation_one_output(Operation,
float128, double,
RoundingMode);
#endif
-
+template bool compare_binary_operation_one_output(Operation,
+ const BinaryInput<bfloat16> &,
+ bfloat16, double,
+ RoundingMode);
template <typename InputType, typename OutputType>
bool compare_ternary_operation_one_output(Operation op,
const TernaryInput<InputType> &input,